unit-conversion.html (54973B)
1 <html> 2 <head> 3 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 5 <meta http-equiv="Content-Language" content="en" /> 6 <title>s6: how to convert systemd unit files to an s6 installation</title> 7 <meta name="Description" content="s6: how to convert systemd unit files to an s6 installation" /> 8 <meta name="Keywords" content="s6 systemd unit files configuration conversion porting" /> 9 <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> --> 10 </head> 11 <body> 12 13 <p> 14 <a href="index.html">s6</a><br /> 15 <a href="//skarnet.org/software/">Software</a><br /> 16 <a href="//skarnet.org/">skarnet.org</a> 17 </p> 18 19 <h1> How to convert systemd unit files to an s6 installation </h1> 20 21 <p> 22 Converting a set of services managed by <a href="https://systemd.io/">systemd</a> 23 to a set of services managed by <a href="index.html">s6</a> is 24 a recurring question on our support channels, and having an automated conversion tool 25 parsing a set of <a href="https://man7.org/linux/man-pages/man5/systemd.unit.5.html">systemd 26 unit files</a> and outputting a set of <a href="servicedir.html">s6 27 service directories</a> or 28 <a href="//skarnet.org/software/s6-rc/s6-rc-compile.html#source">s6-rc service 29 definition directories</a> would be useful to people who want to migrate to 30 s6 but have an existing base of services running under systemd. 31 </p> 32 33 <p> 34 Unfortunately, automating such a conversion is extremely difficult. The main 35 reason for this is that systemd and s6 are architectured in very different ways: 36 how they view a set of services, how they modelize a machine, what kind of solution 37 they bring to a given problem, and the extent of what they're supposed to manage 38 — there are few similarities between how systemd and s6 operate. As a 39 consequence, the way systemd maps a set of services into unit files is not 40 isomorphic to the way s6 does, so translating a setup between systemd and s6 41 requires intelligence. It is not possible to write an automated tool that converts 42 a set of services accurately and idiomatically without doing a full, deep system 43 analysis - and writing such a tool would be a huge undertaking. 44 </p> 45 46 <p> 47 Fortunately, in practice, most unit files only use a small subset of all the 48 theoretically supported directives: most services that run under systemd can be 49 converted to run under s6 without too much trouble. So, depending on the exact 50 nature of the set of services, it may be possible to write a reasonable converter, 51 that is limited in what it supports but does not require a full understanding 52 of systemd (or even s6). 53 </p> 54 55 <p> 56 This document targets people who think about writing a tool to automatically 57 convert a set of unit files to a set of s6 services and are trying to assess 58 its feasability and difficulty. We analyze all the directives that may appear 59 in a unit file for their services, and rate the difficulty of translating the 60 directive, i.e. the amount of complexity that would need to go into the 61 converter tool if that directive were to be supported. 62 </p> 63 64 <p> 65 We rate difficulty on a scale from <strong>0</strong> to <strong>10</strong>. 66 A <strong>0</strong> means that the directive is irrelevant to s6 and can 67 be ignored. A <strong>1</strong> means that there is a straightforward, 68 one-for-one way of translating the systemd directive into s6 parlance. A 69 <strong>10</strong> means that the directive is so systemd-specific that it 70 is impossible to express it on an s6 system and the unit file cannot be 71 converted as is. A <strong>9</strong> means that it is theoretically possible 72 to convert, given infinite time and manpower to write a tool that analyzes 73 the systemd-managed system holistically and outputs an equivalent system 74 managed by s6, but in practice nobody's ever going to write such a tool. 75 </p> 76 77 <p> 78 We only address directives that can appear in <em>service units</em>, which 79 are the ones that can reasonably be expected to translate to s6 or s6-rc 80 services. We do not address directives that can only appear in other kinds 81 of unit files such as slices, timers, sockets, etc. 82 </p> 83 84 <hr /> 85 86 <ul> 87 <li> 88 <a href="#by-directive">All the directives listed by the order in the 89 systemd documentation, with their difficulty</a> 90 <ul> 91 <li> <a href="#systemd.unit">in systemd.unit(5)</a> 92 <ul> 93 <li> <a href="#unit-section"><tt>[Unit]</tt> section</a> </li> 94 <li> <a href="#install-section"><tt>[Install]</tt> section</a> </li> 95 </ul> 96 </li> 97 <li> <a href="#systemd.service">in systemd.service(5)</a> 98 <ul> 99 <li> <a href="#service-section"><tt>[Service]</tt> section</a> </li> 100 </ul> 101 </li> 102 <li> <a href="#systemd.exec">in systemd.exec(5)</a> 103 <ul> 104 <li> <a href="#systemd.exec-paths">Paths</a> </li> 105 <li> <a href="#systemd.exec-identity">User/group identity</a> </li> 106 <li> <a href="#systemd.exec-security">Security</a> </li> 107 <li> <a href="#systemd.exec-mandatoryac">Mandatory access control</a> </li> 108 <li> <a href="#systemd.exec-properties">Process properties</a> </li> 109 <li> <a href="#systemd.exec-scheduling">Scheduling</a> </li> 110 <li> <a href="#systemd.exec-sandboxing">Sandboxing</a> </li> 111 <li> <a href="#systemd.exec-filtering">System call filtering</a> </li> 112 <li> <a href="#systemd.exec-environment">Environment</a> </li> 113 <li> <a href="#systemd.exec-logging">Logging and standard input/output</a> </li> 114 <li> <a href="#systemd.exec-credentials">Credentials</a> </li> 115 <li> <a href="#systemd.exec-sysv">System V compatibility</a> </li> 116 </ul> 117 </li> 118 <li> <a href="#systemd.kill">in systemd.kill(5)</a> </li> 119 <li> <a href="#systemd.resource-control">in systemd.resource-control(5)</a> </li> 120 </ul> 121 </li> 122 <li> 123 <a href="#by-difficulty">All the directives listed by their difficulty</a> 124 <ul> 125 <li> <a href="#difficulty-0">0</a> </li> 126 <li> <a href="#difficulty-1">1</a> </li> 127 <li> <a href="#difficulty-2">2</a> </li> 128 <li> <a href="#difficulty-3">3</a> </li> 129 <li> <a href="#difficulty-4">4</a> </li> 130 <li> <a href="#difficulty-5">5</a> </li> 131 <li> <a href="#difficulty-6">6</a> </li> 132 <li> <a href="#difficulty-7">7</a> </li> 133 <li> <a href="#difficulty-8">8</a> </li> 134 <li> <a href="#difficulty-9">9</a> </li> 135 <li> <a href="#difficulty-10">10</a> </li> 136 </ul> 137 </li> 138 </ul> 139 140 <hr /> 141 142 <h2 id="by-directive"> Difficulty by directive </h2> 143 144 <p> 145 Use this section to answer the question: "I have this directive in my unit file, 146 how hard would it be to write a converter tool that processes this file?" 147 </p> 148 149 <h3 id="systemd.unit"> 150 Directives documented in <a href="https://man7.org/linux/man-pages/man5/systemd.unit.5.html">systemd.unit(5)</a> 151 </h3> 152 153 <h4 id="unit-section"> 154 <tt>[Unit]</tt> section 155 </h4> 156 157 <ul> 158 <li> <tt>Description=</tt> : <strong>0</strong>. </li> 159 <p /> 160 <li> <tt>Documentation=</tt> : <strong>0</strong>. </li> 161 <p /> 162 <li> <tt>Wants=</tt> : <strong>3</strong>. Dependencies between services 163 are implemented via <a href="//skarnet.org/software/s6-rc/">s6-rc</a>; in order 164 to implement <tt>Wants=</tt>. the converter needs to target s6-rc, which is a 165 reasonable requirement for a complete set of services. However, <tt>Wants=</tt> 166 expresses weak dependencies, which are not supported by the current version of 167 s6-rc, so the exact nature of the dependency needs to be checked by hand. </li> 168 <p /> 169 <li> <tt>Requires=</tt> : <strong>2</strong>. The converter needs to 170 target <a href="//skarnet.org/software/s6-rc/">s6-rc</a>, but <tt>Requires=</tt> 171 dependencies map well to the s6-rc dependency model. </li> 172 <p /> 173 <li> <tt>Requisite=</tt> : <strong>3</strong>. systemd supports a lot of 174 weird types of dependencies that the current version of s6-rc does not (by 175 design). </li> 176 <p /> 177 <li> <tt>BindsTo=</tt> : <strong>3</strong>. Same. </li> 178 <p /> 179 <li> <tt>PartOf=</tt> : <strong>3</strong>. Same. </li> 180 <p /> 181 <li> <tt>Upholds=</tt> : <strong>0</strong>. In s6, services are upheld by 182 the supervisor, not by other services. </li> 183 <p /> 184 <li> <tt>Conflicts=</tt> : <strong>5</strong>. There are no negative 185 dependencies in the s6 world, and a converter tool would have to implement it 186 on top of the existing system. </li> 187 <p /> 188 <li> <tt>Before=</tt> : <strong>2</strong>. systemd loves to have a 189 zillion of keywords to express slightly different kinds of dependencies, and 190 only a small subset of all the possible combinations are useful. </li> 191 <p /> 192 <li> <tt>After=</tt> : <strong>2</strong>. </li> 193 <p /> 194 <li> <tt>OnFailure=</tt> : <strong>5</strong>. Permanent failure is 195 a very exceptional state in s6, there are no hooks to do something when 196 permanent failure occurs; so a converter would need to add scripting around that. </li> 197 <p /> 198 <li> <tt>OnSuccess=</tt> : <strong>2</strong>. These are oneshot 199 dependencies. </li> 200 <p /> 201 <li> <tt>PropagatesReloadTo=</tt> : <strong>0</strong>. Under s6-rc 202 you can either reload a single service or the whole dependency chain that 203 starts at the service. Other configurations just make no sense. </li> 204 <p /> 205 <li> <tt>ReloadPropagatedFrom=</tt> : <strong>0</strong>. Same. </li> 206 <p /> 207 <li> <tt>PropagatesStopTo=</tt> : <strong>0</strong>. Same with stopping 208 a single service or a dependency chain of services. </li> 209 <p /> 210 <li> <tt>StopPropagatedFrom=</tt> : <strong>0</strong>. Same. </li> 211 <p /> 212 <li> <tt>JoinsNamespaceOf=</tt> : <strong>8</strong>. There are no 213 native s6 tools to manage namespaces. </li> 214 <p /> 215 <li> <tt>RequiresMountsFor=</tt> : <strong>4</strong>. Mounts are 216 not handled in a special way in s6, the converter would have to know 217 what service mounts what filesystem. </li> 218 <p /> 219 <li> <tt>OnFailureJobMode=</tt> : <strong>6</strong>. This is what 220 happens when you mix layers. </li> 221 <p /> 222 <li> <tt>IgnoreOnIsolate=</tt> : <strong>0</strong>. </li> 223 <p /> 224 <li> <tt>StopWhenUnneeded=</tt> : <strong>0</strong>. </li> 225 <p /> 226 <li> <tt>RefuseManualStart=</tt> : <strong>4</strong>. Would need 227 some scripting around. There's no reason to ever use that directive though. </li> 228 <p /> 229 <li> <tt>RefuseManualStop=</tt> : <strong>1</strong>. </li> 230 <p /> 231 <li> <tt>AllowIsolate=</tt> : <strong>0</strong>. </li> 232 <p /> 233 <li> <tt>DefaultDependencies=</tt> : <strong>2</strong>. </li> 234 <p /> 235 <li> <tt>CollectMode=</tt> : <strong>0</strong>. </li> 236 <p /> 237 <li> <tt>FailureAction=</tt> : <strong>3</strong>. Anything involving 238 permanent failure need to be scripted around, because s6 considers that 239 it is an extreme state that requires administrator attention and will 240 stop making automatic decisions. </li> 241 <p /> 242 <li> <tt>SuccessAction=</tt> : <strong>3</strong>. That's a oneshot 243 dependency, but systemd doesn't realize that. </li> 244 <p /> 245 <li> <tt>FailureActionExitStatus=</tt> : <strong>1</strong>. </li> 246 <p /> 247 <li> <tt>SuccessActionExitStatus=</tt> : <strong>1</strong>. </li> 248 <p /> 249 <li> <tt>JobTimeoutSec=</tt> : <strong>9</strong>. s6 has no 250 concept of jobs. </li> 251 <p /> 252 <li> <tt>JobRunningTimeoutSec=</tt> : <strong>9</strong>. Same. </li> 253 <p /> 254 <li> <tt>JobTimeoutAction=</tt> : <strong>9</strong>. Same. </li> 255 <p /> 256 <li> <tt>JobTimeoutRebootArgument=</tt> : <strong>9</strong>. Same. </li> 257 <p /> 258 <li> <tt>StartLimitIntervalSec=</tt> : <strong>3</strong>. s6 does 259 not limit start rate. It can stop a service that has a high <em>death</em> 260 rate: that's the configuration knob that makes sense. That directive can 261 be converted to check death interval instead. </li> 262 <p /> 263 <li> <tt>StartLimitBurst=</tt> : <strong>3</strong>. Same. </li> 264 <p /> 265 <li> <tt>StartLimitAction=</tt> : <strong>3</strong>. Same. </li> 266 <p /> 267 <li> <tt>RebootArgument=</tt> : <strong>5</strong>. Any "system mode" 268 action such as a reboot has no place in an s6 set of services anyway; 269 systemd obviously likes to mix unrelated layers. In the s6 world, the only 270 place where a reboot should occur is 271 <a href="//skarnet.org/software/s6-linux-init/">s6-linux-init</a>, and the 272 related scripting in <tt>rc.init</tt> files. </li> 273 <p /> 274 <li> <tt>SourcePath=</tt> : <strong>0</strong>. </li> 275 <p /> 276 <li> Conditions and Asserts: <strong>9</strong>. Most of these are tied to the 277 global machine state and absolutely not local to a given set of services. And 278 even for those that are not, what they do is change the whole service manager's 279 behaviour depending on some external dynamic state such as the existence of a 280 file in the filesystem — and that is entirely contrary to the s6 281 philosophy of making services predictable and reproducible. </li> 282 </ul> 283 284 <h4 id="install-section"> 285 <tt>[Install]</tt> section 286 </h4> 287 288 <p> 289 Any directive under <tt>[Install]</tt> can be ignored, since it has no 290 meaning on the run-time behaviour of the service. So the difficulty is 291 <strong>0</strong>. However, an automatic converter would need to 292 analyze the whole installed service configuration, e.g. the links in 293 <tt>/etc/systemd/system/multi-user.target.wants/</tt>, in order to 294 understand the dependencies between services. systemd targets can 295 typically be converted into s6-rc bundles. 296 </p> 297 298 <h3 id="systemd.service"> 299 Directives documented in <a href="https://man7.org/linux/man-pages/man5/systemd.service.5.html">systemd.service(5)</a> 300 </h3> 301 302 <h4 id="service-section"> 303 <tt>[Service]</tt> section 304 </h4> 305 306 <ul> 307 <li> <tt>Type=</tt> : depending on its type, a systemd "service" 308 can translate to wildly different things under s6. 309 <ul> 310 <li> <tt>simple</tt> : <strong>1</strong>. </li> 311 <li> <tt>exec</tt> : <strong>1</strong>. </li> 312 <li> <tt>forking</tt> : <strong>2</strong>. This type is strongly discouraged. </li> 313 <li> <tt>oneshot</tt> : <strong>1</strong>. </li> 314 <li> <tt>dbus</tt> : <strong>5</strong>. This type requires implementing dbus 315 management programs for s6. </li> 316 <li> <tt>notify</tt> : <strong>7</strong>. This type requires an implementation 317 of a compatibility server for 318 <a href="https://man7.org/linux/man-pages/man3/sd_notify.3.html"><tt>sd_notify()</tt></a>, 319 which is heavily tied to the monolithic systemd architecture and is difficult to support 320 in a modular system such as s6. It is much easier to modify the services themselves so 321 they use the <a href="notifywhenup.html">s6 readiness 322 notification mechanism</a> instead of sd_notify. </li> 323 <li> <tt>idle</tt> : <strong>0</strong>. This type is meaningless under s6 and 324 should be treated like <tt>simple</tt>. </li> 325 </ul> 326 </li> 327 <p /> 328 <li> <tt>ExitType=</tt> : again, it depends on the value. 329 <ul> 330 <li> <tt>main</tt> : <strong>1</strong>. </li> 331 <li> <tt>cgroup</tt> : <strong>3</strong>. This requires implementing, or 332 having access to, command-line cgroup tools. </li> 333 </ul> 334 </li> 335 <p /> 336 <li> <tt>RemainAfterExit=</tt> : <strong>0</strong>. </li> 337 <p /> 338 <li> <tt>GuessMainPid=</tt> : <strong>0</strong>. But don't use <tt>forking</tt> 339 if you can avoid it. </li> 340 <p /> 341 <li> <tt>PIDFile=</tt> : <strong>2</strong>. Same. </li> 342 <p /> 343 <li> <tt>BusName=</tt> : <strong>5</strong>. Avoid type <tt>dbus</tt> if possible. </li> 344 <p /> 345 <li> <tt>ExecStart=</tt> : <strong>2</strong>, with caveats. This is the bread and 346 butter of service definitions; all your services will likely have such a directive, and 347 the contents of <tt>ExecStart=</tt> will typically go into a run script (for longruns) or 348 an up file (for oneshots). However, since systemd hates simplicity, there are a number 349 of transformations that have to happen to the command line before it can be used in a 350 script, and in particular if the command has a <em>special executable prefix</em>. 351 Implementing these has its own difficulty ratings: 352 <ul> 353 <li> <tt>@</tt> : <strong>1</strong>. </li> 354 <li> <tt>-</tt> : <strong>1</strong>. </li> 355 <li> <tt>:</tt> : <strong>2</strong>. </li> 356 <li> <tt>+</tt> : <strong>5</strong>. </li> 357 <li> <tt>!</tt> : <strong>3</strong>. </li> 358 <li> <tt>!!</tt> : <strong>3</strong>. </li> 359 </ul> 360 </li> 361 <p /> 362 <li> <tt>ExecStartPre=</tt> : <strong>2</strong>. In order to have a strict 363 semantic equivalence with their systemd version, <tt>ExecStartPre=</tt> lines must 364 be implemented as s6-rc oneshots, and the whole unit file must be implemented as 365 a bundle. </li> 366 <p /> 367 <li> <tt>ExecStartPost=</tt> : <strong>2</strong>. Same. </li> 368 <p /> 369 <li> <tt>ExecCondition=</tt> : <strong>2</strong>. </li> 370 <p /> 371 <li> <tt>ExecReload=</tt> : <strong>0</strong>. A reloading command that 372 does not involve restarting the service does not need the service manager as 373 a third-party. systemd cannot help inserting itself where it does not belong. </li> 374 <p /> 375 <li> <tt>ExecStop=</tt> : <strong>5</strong>. s6 only supports terminating 376 services via signals, so if a service needs a specific command to be stopped, 377 the converter needs to target an interface layer on top of s6 with a repository 378 of stop commands; such a layer would likely need to be on top of s6-rc as well 379 and a lot of complexity would ensue. Fortunately, a huge majority of services 380 support termination via signals and it is often easy to avoid relying on 381 <tt>ExecStop=</tt>. </li> 382 <p /> 383 <li> <tt>ExecStopPost=</tt> : <strong>2</strong>. These are the 384 <tt>down</tt> scripts of the <tt>ExecStartPre=</tt> oneshots. </li> 385 <p /> 386 <li> <tt>RestartSec=</tt> : <strong>2</strong>. s6 has no setting for that, 387 because it aims for maximum uptime; but there are still ways to implement that 388 bad idea. </li> 389 <p /> 390 <li> <tt>TimeoutStartSec=</tt> : <strong>1</strong>. </li> 391 <p /> 392 <li> <tt>TimeoutStopSec=</tt> : <strong>1</strong>. </li> 393 <p /> 394 <li> <tt>TimeoutAbortSec=</tt> : <strong>7</strong>. This would need a 395 watchdog implementation, in the server implementation of <tt>sd_notify()</tt>. </li> 396 <p /> 397 <li> <tt>TimeoutSec=</tt> : <strong>1</strong>. </li> 398 <p /> 399 <li> <tt>TimeoutStartFailureMode=</tt> : <strong>0</strong> for 400 <tt>terminate</tt> and <tt>kill</tt>, <strong>7</strong> for <tt>abort</tt>. </li> 401 <p /> 402 <li> <tt>TimeoutStopFailureMode=</tt> : <strong>0</strong> for 403 <tt>terminate</tt> and <tt>kill</tt>, <strong>7</strong> for <tt>abort</tt>. </li> 404 <p /> 405 <li> <tt>RuntimeMaxSec=</tt> : <strong>4</strong>. This is the exact 406 opposite of what you need a process supervisor for, so s6 does not 407 implement it. It is best to run such a process (not a <em>service</em>) 408 outside of any kind of supervision framework. </li> 409 <p /> 410 <li> <tt>RuntimeRandomizedExtraSec=</tt> : <strong>4</strong>. Same. </li> 411 <p /> 412 <li> <tt>WatchdogSec=</tt> : <strong>7</strong>. Requires a watchdog 413 implementation in the very specific systemd way. </li> 414 <p /> 415 <li> <tt>Restart=</tt> : depends on the value. 416 <ul> 417 <li> <tt>no</tt> : <strong>2</strong>, but why use a process supervisor 418 in the first place? </li> 419 <li> <tt>on-success</tt> : <strong>2</strong>. </li> 420 <li> <tt>on-failure</tt> : <strong>2</strong>. </li> 421 <li> <tt>on-abnormal</tt> : <strong>2</strong>. </li> 422 <li> <tt>on-watchdog</tt> : <strong>7</strong>. Again, this requires 423 a watchdog implementation. </li> 424 <li> <tt>on-abort</tt> : <strong>2</strong>. </li> 425 <li> <tt>always</tt> : <strong>1</strong>. </li> 426 </ul> 427 </li> 428 <p /> 429 <li> <tt>SuccessExitStatus=</tt> : <strong>3</strong>. This can be easily 430 scripted, but supporting all the systemd formats is annoying. </li> 431 <p /> 432 <li> <tt>RestartPreventExitStatus=</tt> : <strong>1</strong>. This is 433 exactly what <a href="s6-permafailon.html">s6-permafailon</a> 434 is for. </li> 435 <p /> 436 <li> <tt>RestartForceExitStatus=</tt> : <strong>2</strong>. </li> 437 <p /> 438 <li> <tt>RootDirectoryStartOnly=</tt> : <strong>2</strong>. </li> 439 <p /> 440 <li> <tt>NonBlocking=</tt> : <strong>5</strong>. This requires an 441 emulation of systemd's socket activation. s6 provides the useful parts of 442 it, like a <a href="s6-fdholder-daemon.html">process 443 to hold file descriptors</a>, but the systemd-specific API around socket 444 activation, <a href="https://www.freedesktop.org/software/systemd/man/sd_listen_fds.html">sd_listen_fds(3)</a>, 445 still needs to be implemented. </li> 446 <p /> 447 <li> <tt>NotifyAccess=</tt> : <strong>1</strong> if <tt>none</tt>, <strong>7</strong> 448 otherwise, because it needs an implementation of <tt>sd_notify()</tt>. </li> 449 <p /> 450 <li> <tt>Sockets=</tt> : <strong>5</strong>. Requires an implementation 451 of systemd's socket activation. </li> 452 <p /> 453 <li> <tt>FileDescriptorStoreMax=</tt> : <strong>7</strong>. Requires an implementation 454 of <tt>sd_notify()</tt>; the fd store itself is native to s6. </li> 455 <p /> 456 <li> <tt>USBFunctionDescriptors=</tt> : <strong>9</strong>. This is 457 low-level machine management, not service management. </li> 458 <p /> 459 <li> <tt>USBFunctionStrings=</tt> : <strong>9</strong>. Same. </li> 460 <p /> 461 <li> <tt>OOMPolicy=</tt> : <strong>9</strong>. Same. </li> 462 </ul> 463 464 <h3 id="systemd.exec"> 465 Directives documented in <a href="https://man7.org/linux/man-pages/man5/systemd.exec.5.html">systemd.exec(5)</a> 466 </h3> 467 468 <h4 id="systemd.exec-paths"> 469 Paths 470 </h4> 471 472 <ul> 473 <li> <tt>ExecSearchPath=</tt> : <strong>1</strong>. </li> 474 <p /> 475 <li> <tt>WorkingDirectory=</tt> : <strong>2</strong>. </li> 476 <p /> 477 <li> <tt>RootDirectory=</tt> : <strong>1</strong>. </li> 478 <p /> 479 <li> <tt>RootImage=</tt> : <strong>6</strong>. I am discovering these 480 options in real time and shaking my head - systemd still manages to baffle me 481 with the amount of gratuitous ad-hoc that went into it. Still, this is 482 regular low-level programming for Linux, this is less difficult to implement than 483 systemd-specific stuff, that's why it only gets a 6. </li> 484 <p /> 485 <li> <tt>RootImageOptions=</tt> : <strong>6</strong>. Same. </li> 486 <p /> 487 <li> <tt>RootHash=</tt> : <strong>9</strong>. Please. </li> 488 <p /> 489 <li> <tt>RootHashSignature=</tt> : <strong>9</strong>. </li> 490 <p /> 491 <li> <tt>RootVerity=</tt> : <strong>9</strong>. </li> 492 <p /> 493 <li> <tt>MountAPIVFS=</tt> : <strong>6</strong>. </li> 494 <p /> 495 <li> <tt>ProtectProc=</tt> : <strong>6</strong>. </li> 496 <p /> 497 <li> <tt>ProcSubset=</tt> : <strong>6</strong>. </li> 498 <p /> 499 <li> <tt>BindPaths=</tt> : <strong>6</strong>. </li> 500 <p /> 501 <li> <tt>BindReadOnlyPaths=</tt> : <strong>6</strong>. </li> 502 <p /> 503 <li> <tt>MountImages=</tt> : <strong>6</strong>. </li> 504 <p /> 505 <li> <tt>ExtensionImages=</tt> : <strong>6</strong>. </li> 506 <p /> 507 <li> <tt>ExtensionDirectories=</tt> : <strong>6</strong>. It's a full low-level 508 userspace implementation at this point. It's not very <em>complex</em>, the 6 feels 509 accurate, but it's a whole lot of work. This is how systemd maintains its 510 hegemony: not because it does incredible, awe-inspiring magic, but because it 511 substitutes its monolithic self to a whole ecosystem, imposes its own API, and 512 locks users in — people who want to smoothly transition away from systemd need 513 to implement <em>the whole shtick</em>, which is obviously a huge undertaking, as 514 the author of <a href="https://web.archive.org/web/20150516113530/http://uselessd.darknedgy.net/">uselessd</a> 515 can confirm. </li> 516 </ul> 517 518 <h4 id="systemd.exec-identity"> 519 User/group identity 520 </h4> 521 522 <ul> 523 <li> <tt>User=</tt> : <strong>3</strong>. This looks very simple, but is 524 treacherous, because <tt>User=</tt> is a mash of two very different features: 525 setting users <em>statically</em> (via numeric ID, which don't change meanings 526 between two invocations) and setting users <em>dynamically</em> (via user name, 527 which needs to be interpreted by 528 <a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwnam.html">getpwnam(3)</a> 529 on every invocation of the service. s6 supports both, but since these are two 530 different things, the way to do them in s6 is different (statically setting the 531 UID and GID variables and calling 532 <a href="s6-applyuidgid.html">s6-applyuidgid -U</a>, 533 or calling <a href="s6-setuidgid.html">s6-setuidgid</a>). 534 This is the exact kind of small detail that makes writing an automatic converter more difficult 535 than it should be: the systemd unit file syntax is rife with semantic pitfalls, and managing 536 your way across it requires very close attention. </li> 537 <p /> 538 <li> <tt>Group=</tt> : <strong>3</strong>. Same. </li> 539 <p /> 540 <li> <tt>DynamicUser=</tt> : <strong>5</strong>. Of course this flag has an 541 <em>entirely</em> different meaning from setting users statically or dynamically, or 542 else it would be too easy to understand. No, this flag is about <em>allocating temporary 543 new users</em>, which is a prime example of overengineering. </li> 544 <p /> 545 <li> <tt>SupplementaryGroups=</tt> : <strong>1</strong>. Same. </li> 546 <p /> 547 <li> <tt>PAMName=</tt> : <strong>4</strong>. Requires PAM command-line 548 utilities. </li> 549 </ul> 550 551 <h4 id="systemd.exec-capabilities"> 552 Capabilities 553 </h4> 554 555 <ul> 556 <li> <tt>CapabilityBoundingSet=</tt> : <strong>4</strong>. This requires 557 command-line tools implementing capabilities. </li> 558 <p /> 559 <li> <tt>AmbientCapabilities=</tt> : <strong>4</strong>. Same. </li> 560 </ul> 561 562 <h4 id="systemd.exec-security"> 563 Security 564 </h4> 565 566 <ul> 567 <li> <tt>NoNewPrivileges=</tt> : <strong>4</strong>. Similar to capabilities, 568 this requires a command-line tool controlling the Linux-specific 569 <a href="https://man7.org/linux/man-pages/man2/prctl.2.html">prctl(2)</a> system 570 call. </li> 571 <p /> 572 <li> <tt>SecureBits=</tt> : <strong>4</strong>. Same. </li> 573 </ul> 574 575 <h4 id="systemd.exec-mandatoryac"> 576 Mandatory access control 577 </h4> 578 579 <ul> 580 <li> <tt>SELinuxContext=</tt> : <strong>5</strong>. This requires 581 command-line tools managing SELinux. </li> 582 <p /> 583 <li> <tt>AppArmorProfile=</tt> : <strong>5</strong>. Same, with AppArmor. </li> 584 <p /> 585 <li> <tt>SmackProcessLabel=</tt> : <strong>5</strong>. Same, with SMACK. 586 systemd needs to know and understand all the Linux security modules in order 587 to interact with them. s6 does not - it expects a service's run script to 588 perform all the needed process state changes and controls before executing 589 into the daemon. </li> 590 </ul> 591 592 <h4 id="systemd.exec-properties"> 593 Process properties 594 </h4> 595 596 <ul> 597 <li> <tt>LimitCPU=</tt> : <strong>1</strong>. </li> 598 <p /> 599 <li> <tt>LimitFSIZE=</tt> : <strong>1</strong>. </li> 600 <p /> 601 <li> <tt>LimitDATA=</tt> : <strong>1</strong>. </li> 602 <p /> 603 <li> <tt>LimitSTACK=</tt> : <strong>1</strong>. </li> 604 <p /> 605 <li> <tt>LimitCORE=</tt> : <strong>1</strong>. </li> 606 <p /> 607 <li> <tt>LimitRSS=</tt> : <strong>1</strong>. </li> 608 <p /> 609 <li> <tt>LimitNOFILE=</tt> : <strong>1</strong>. </li> 610 <p /> 611 <li> <tt>LimitAS=</tt> : <strong>1</strong>. </li> 612 <p /> 613 <li> <tt>LimitNPROC=</tt> : <strong>1</strong>. </li> 614 <p /> 615 <li> <tt>LimitMEMLOCK=</tt> : <strong>1</strong>. </li> 616 <p /> 617 <li> <tt>LimitLOCKS=</tt> : <strong>2</strong>. This resource limit 618 isn't natively supported by 619 <a href="//skarnet.org/software/s6/s6-softlimit.html">s6-softlimit</a>, but 620 it could appear in a future s6 version - and it's easy to add in any case. </li> 621 <p /> 622 <li> <tt>LimitSIGPENDING=</tt> : <strong>2</strong>. Same. </li> 623 <p /> 624 <li> <tt>LimitMSGQUEUE=</tt> : <strong>2</strong>. Same. </li> 625 <p /> 626 <li> <tt>LimitNICE=</tt> : <strong>2</strong>. Same. </li> 627 <p /> 628 <li> <tt>LimitRTPRIO=</tt> : <strong>2</strong>. Same. </li> 629 <p /> 630 <li> <tt>LimitRTTIME=</tt> : <strong>2</strong>. Same. </li> 631 <p /> 632 <li> <tt>UMask=</tt> : <strong>1</strong>. </li> 633 <p /> 634 <li> <tt>CoredumpFilter=</tt> : <strong>4</strong>. Requires a 635 command-line tool around <a href="https://man7.org/linux/man-pages/man2/prctl.2.html">prctl(2)</a>. </li> 636 <p /> 637 <li> <tt>KeyringMode=</tt> : <strong>5</strong>. Requires 638 interaction with PAM and an understanding of keyrings. Fortunately, 639 practically nothing will need that. </li> 640 <p /> 641 <li> <tt>OOMScoreAdjust=</tt> : <strong>2</strong>. </li> 642 <p /> 643 <li> <tt>TimerSlackNSec=</tt> : <strong>4</strong>. Requires a 644 command-line tool around <a href="https://man7.org/linux/man-pages/man2/prctl.2.html">prctl(2)</a>. </li> 645 <p /> 646 <li> <tt>Personality=</tt> : <strong>3</strong>. Requires a 647 command-line tool around <a href="https://man7.org/linux/man-pages/man2/personality.2.html">personality(2)</a>. </li> 648 <p /> 649 <li> <tt>IgnoreSIGPIPE=</tt> : <strong>2</strong>. </li> 650 </ul> 651 652 <h4 id="systemd.exec-scheduling"> 653 Scheduling 654 </h4> 655 656 <ul> 657 <li> <tt>Nice=</tt> : <strong>1</strong>. </li> 658 <p /> 659 <li> <tt>CPUSchedulingPolicy=</tt> : <strong>3</strong>. Requires a 660 command-line tool around <a href="https://man7.org/linux/man-pages/man2/sched_setscheduler.2.html">sched_setscheduler(2)</a>. </li> 661 <p /> 662 <li> <tt>CPUSchedulingPriority=</tt> : <strong>3</strong>. Same. </li> 663 <p /> 664 <li> <tt>CPUSchedulingResetOnFork=</tt> : <strong>3</strong>. Same. </li> 665 <p /> 666 <li> <tt>CPUAffinity=</tt> : <strong>3</strong>. Requires a 667 command-line tool around <a href="https://man7.org/linux/man-pages/man2/sched_setaffinity.2.html">sched_setaffinity(2)</a>. </li> 668 <p /> 669 <li> <tt>NUMAPolicy=</tt> : <strong>3</strong>. Requires a 670 command-line tool around <a href="https://man7.org/linux/man-pages/man2/set_mempolicy.2.html">set_mempolicy(2)</a>. </li> 671 <p /> 672 <li> <tt>NUMAMask=</tt> : <strong>3</strong>. Same. </li> 673 <p /> 674 <li> <tt>IOSchedulingClass=</tt> : <strong>3</strong>. Requires a 675 command-line tool around <a href="https://man7.org/linux/man-pages/man2/ioprio_set.2.html">ioprio_set(2)</a>. </li> 676 <p /> 677 <li> <tt>IOSchedulingPriority=</tt> : <strong>3</strong>. Same. </li> 678 </ul> 679 680 <h4 id="systemd.exec-sandboxing"> 681 Sandboxing 682 </h4> 683 684 <p> 685 systemd gracefully turns off the sandboxing options on systems that 686 do not support the necessary functionality, so all these options can 687 be ignored (difficulty <strong>0</strong>) and the services will still 688 work. However, in order to actually implementing the sandboxing, it is 689 necessary to pair s6 with command-line tools that perform the required 690 process state changes by interfacing with namespaces, cgroups, seccomp, 691 or any other relevant feature of the Linux kernel, so for all these 692 directives the difficulty is somewhere between <strong>2</strong>, if 693 the tool already exists, and <strong>8</strong>, if it requires writing 694 a full container implementation from scratch. The following numbers are 695 only a rough guess. 696 </p> 697 698 <ul> 699 <li> <tt>ProtectSystem=</tt> : <strong>6</strong>. </li> 700 <p /> 701 <li> <tt>ProtectHome=</tt> : <strong>6</strong>. </li> 702 <p /> 703 <li> <tt>RuntimeDirectory=</tt> : <strong>1</strong>. </li> 704 <p /> 705 <li> <tt>StateDirectory=</tt> : <strong>1</strong>. </li> 706 <p /> 707 <li> <tt>CacheDirectory=</tt> : <strong>1</strong>. </li> 708 <p /> 709 <li> <tt>LogsDirectory=</tt> : <strong>1</strong>. </li> 710 <p /> 711 <li> <tt>ConfigurationDirectory=</tt> : <strong>1</strong>. </li> 712 <p /> 713 <li> <tt>RuntimeDirectoryMode=</tt> : <strong>1</strong>. </li> 714 <p /> 715 <li> <tt>StateDirectoryMode=</tt> : <strong>1</strong>. </li> 716 <p /> 717 <li> <tt>CacheDirectoryMode=</tt> : <strong>1</strong>. </li> 718 <p /> 719 <li> <tt>LogsDirectoryMode=</tt> : <strong>1</strong>. </li> 720 <p /> 721 <li> <tt>ConfigurationDirectoryMode=</tt> : <strong>1</strong>. </li> 722 <p /> 723 <li> <tt>RuntimeDirectoryPreserve=</tt> : <strong>3</strong>. </li> 724 <p /> 725 <li> <tt>TimeoutCleanSec=</tt> : <strong>3</strong>. </li> 726 <p /> 727 <li> <tt>ReadWritePaths=</tt> : <strong>5</strong>. </li> 728 <p /> 729 <li> <tt>ReadOnlyPaths=</tt> : <strong>5</strong>. </li> 730 <p /> 731 <li> <tt>InaccessiblePaths=</tt> : <strong>5</strong>. </li> 732 <p /> 733 <li> <tt>ExecPaths=</tt> : <strong>5</strong>. </li> 734 <p /> 735 <li> <tt>NoExecPaths=</tt> : <strong>5</strong>. </li> 736 <p /> 737 <li> <tt>TemporaryFileSystem=</tt> : <strong>5</strong>. </li> 738 <p /> 739 <li> <tt>PrivateTmp=</tt> : <strong>5</strong>. </li> 740 <p /> 741 <li> <tt>PrivateDevices=</tt> : <strong>5</strong>. </li> 742 <p /> 743 <li> <tt>PrivateNetwork=</tt> : <strong>8</strong>. </li> 744 <p /> 745 <li> <tt>NetworkNamespacePath=</tt> : <strong>8</strong>. </li> 746 <p /> 747 <li> <tt>PrivateIPC=</tt> : <strong>5</strong>. </li> 748 <p /> 749 <li> <tt>IPCNamespacePath=</tt> : <strong>5</strong>. </li> 750 <p /> 751 <li> <tt>PrivateUsers=</tt> : <strong>5</strong>. </li> 752 <p /> 753 <li> <tt>ProtectHostname=</tt> : <strong>5</strong>. </li> 754 <p /> 755 <li> <tt>ProtectClock=</tt> : <strong>7</strong>. </li> 756 <p /> 757 <li> <tt>ProtectKernelTunables=</tt> : <strong>7</strong>. </li> 758 <p /> 759 <li> <tt>ProtectKernelModules=</tt> : <strong>7</strong>. </li> 760 <p /> 761 <li> <tt>ProtectKernelLogs=</tt> : <strong>7</strong>. </li> 762 <p /> 763 <li> <tt>ProtectControlGroups=</tt> : <strong>7</strong>. </li> 764 <p /> 765 <li> <tt>RestrictAddressFamilies=</tt> : <strong>7</strong>. </li> 766 <p /> 767 <li> <tt>RestrictFilesystems=</tt> : <strong>7</strong>. </li> 768 <p /> 769 <li> <tt>RestrictNamespaces=</tt> : <strong>7</strong>. </li> 770 <p /> 771 <li> <tt>LockPersonality=</tt> : <strong>7</strong>. </li> 772 <p /> 773 <li> <tt>MemoryDenyWriteExecute=</tt> : <strong>7</strong>. </li> 774 <p /> 775 <li> <tt>RestrictRealtime=</tt> : <strong>7</strong>. </li> 776 <p /> 777 <li> <tt>RestrictSUIDSGID=</tt> : <strong>7</strong>. </li> 778 <p /> 779 <li> <tt>RemoveIPC=</tt> : <strong>5</strong>. </li> 780 <p /> 781 <li> <tt>PrivateMounts=</tt> : <strong>5</strong>. </li> 782 </ul> 783 784 <h4 id="systemd.exec-filtering"> 785 System call filtering 786 </h4> 787 788 <ul> 789 <li> <tt>SystemCallFilter=</tt> : <strong>8</strong>. </li> 790 <p /> 791 <li> <tt>SystemCallErrorNumber=</tt> : <strong>8</strong>. </li> 792 <p /> 793 <li> <tt>SystemCallArchitectures=</tt> : <strong>8</strong>. </li> 794 <p /> 795 <li> <tt>SystemCallLog=</tt> : <strong>8</strong>. </li> 796 </ul> 797 798 <h4 id="systemd.exec-environment"> 799 Environment 800 </h4> 801 802 <ul> 803 <li> <tt>Environment=</tt> : <strong>1</strong>. </li> 804 <p /> 805 <li> <tt>EnvironmentFile=</tt> : <strong>1</strong>. </li> 806 <p /> 807 <li> <tt>PassEnvironment=</tt> : <strong>1</strong>. </li> 808 <p /> 809 <li> <tt>UnsetEnvironment=</tt> : <strong>1</strong>. </li> 810 </ul> 811 812 <h4 id="systemd.exec-logging"> 813 Logging and standard input/output 814 </h4> 815 816 <ul> 817 <li> <tt>StandardInput=</tt> : <strong>1</strong>. </li> 818 <p /> 819 <li> <tt>StandardOutput=</tt> : <strong>1</strong>, except 820 for <tt>journal</tt> which cannot be supported (<strong>10</strong>). </li> 821 <p /> 822 <li> <tt>StandardError=</tt> : same. </li> 823 <p /> 824 <li> <tt>StandardInputText=</tt> : <strong>2</strong>. </li> 825 <p /> 826 <li> <tt>StandardInputData=</tt> : <strong>2</strong>. </li> 827 <p /> 828 <li> <tt>LogLevelMax=</tt> : <strong>3</strong>. </li> 829 <p /> 830 <li> <tt>LogExtraFields=</tt> : <strong>10</strong>. </li> 831 <p /> 832 <li> <tt>LogRateLimitIntervalSec=</tt> : <strong>10</strong>. </li> 833 <p /> 834 <li> <tt>LogRateLimitBurst=</tt> : <strong>10</strong>. </li> 835 <p /> 836 <li> <tt>LogFilterPatterns=</tt> : <strong>4</strong>. </li> 837 <p /> 838 <li> <tt>LogNamespace=</tt> : <strong>10</strong>. </li> 839 <p /> 840 <li> <tt>SyslogIdentifier=</tt> : <strong>2</strong>. </li> 841 <p /> 842 <li> <tt>SyslogFacility=</tt> : <strong>2</strong>. </li> 843 <p /> 844 <li> <tt>SyslogLevel=</tt> : <strong>2</strong>. </li> 845 <p /> 846 <li> <tt>SyslogLevelPrefix=</tt> : <strong>4</strong>. </li> 847 <p /> 848 <li> <tt>TTYPath=</tt> : <strong>1</strong>. </li> 849 <p /> 850 <li> <tt>TTYReset=</tt> : <strong>3</strong>. </li> 851 <p /> 852 <li> <tt>TTYVHangup=</tt> : <strong>3</strong>. </li> 853 <p /> 854 <li> <tt>TTYRows=</tt> : <strong>3</strong>. </li> 855 <p /> 856 <li> <tt>TTYColumns=</tt> : <strong>3</strong>. </li> 857 <p /> 858 <li> <tt>TTYDisallocate=</tt> : <strong>3</strong>. </li> 859 <p /> 860 </ul> 861 862 <h4 id="systemd.exec-credentials"> 863 Credentials 864 </h4> 865 866 <p> 867 systemd implements its own credentials store mechanism, for no obvious 868 benefit. The whole credentials system needs to be reimplemented outside 869 of systemd in order for credentials-related directives to be supported 870 by s6. Consequently, all these directives are rated <strong>6</strong>. 871 </p> 872 873 <h4 id="systemd.exec-sysv"> 874 System V compatibility 875 </h4> 876 877 <p> 878 The utmp directives can be made significantly easier to implement if the target 879 system is using <a href="//skarnet.org/software/utmps/">utmps</a>, 880 because the directives then become a single call to 881 <a href="//skarnet.org/software/utmps/utmps-write.html">utmps-write</a> 882 with the relevant options. If <a href="//skarnet.org/software/utmps/">utmps</a> 883 cannot be used, then the utmp calls need to be reimplemented. 884 </p> 885 886 <ul> 887 <li> <tt>UtmpIdentifier=</tt> : <strong>4</strong>. </li> 888 <p /> 889 <li> <tt>UtmpMode=</tt> : <strong>4</strong>. </li> 890 </ul> 891 892 <h3 id="systemd.kill"> 893 Directives documented in <a href="https://man7.org/linux/man-pages/man5/systemd.kill.5.html">systemd.kill(5)</a> 894 </h3> 895 896 <ul> 897 <li> <tt>KillMode=</tt> : depends on the kill mode. 898 <tt>control-group</tt> and <tt>mixed</tt> are <strong>3</strong>, 899 because they require cgroup control commands (that can be implemented 900 in shell). <tt>process</tt> is <strong>1</strong>. <tt>none</tt> is 901 <strong>2</strong>. </li> 902 <p /> 903 <li> <tt>KillSignal=</tt> : <strong>1</strong>. </li> 904 <p /> 905 <li> <tt>RestartKillSignal=</tt> : <strong>5</strong>. s6 906 doesn't use a different signal for restarting; implementing this 907 requires an outer layer. (This is overengineering.) </li> 908 <p /> 909 <li> <tt>SendSIGHUP=</tt> : <strong>5</strong>. Same. </li> 910 <p /> 911 <li> <tt>SendSIGKILL=</tt> : <strong>1</strong>. </li> 912 <p /> 913 <li> <tt>FinalKillSignal=</tt> : <strong>5</strong>. (This 914 is <em>absolute</em> overengineering.) </li> 915 <p /> 916 <li> <tt>WatchdogSignal=</tt> : <strong>7</strong>. Only meaningful 917 with an implementation of systemd's watchdog system. </li> 918 </ul> 919 920 <h3 id="systemd.resource-control"> 921 Directives documented in <a href="https://man7.org/linux/man-pages/man5/systemd.resource-control.5.html">systemd.resource-control(5)</a> 922 </h3> 923 924 <p> 925 All these directives relate to cgroups, so implementing them means 926 having access to at least some cgroups commands (difficulty at least 927 <strong>3</strong>. Others are even more involved, requiring tight 928 service integration with the system. Generally, seeing these directives 929 in your unit files is a bad sign; despite some of them only having 930 <strong>3</strong> or <strong>4</strong> listed, we do not recommend 931 implementing <a href="https://man7.org/linux/man-pages/man5/systemd.resource-control.5.html">systemd.resource-control(5)</a> 932 without having a full holistic view of the system. 933 </p> 934 935 <ul> 936 <li> <tt>CPUAccounting=</tt> : <strong>3</strong>. </li> 937 <p /> 938 <li> <tt>CPUWeight=</tt> : <strong>4</strong>. </li> 939 <p /> 940 <li> <tt>StartupCPUWeight=</tt> : <strong>9</strong>. Involves 941 startup and shutdown. </li> 942 <p /> 943 <li> <tt>CPUQuota=</tt> : <strong>4</strong>. </li> 944 <p /> 945 <li> <tt>CPUQuotaPeriodSec=</tt> : <strong>4</strong>. </li> 946 <p /> 947 <li> <tt>AllowedCPUs=</tt> : <strong>3</strong>. </li> 948 <p /> 949 <li> <tt>StartupAllowedCPUs=</tt> : <strong>9</strong>. Involves 950 startup and shutdown. </li> 951 <p /> 952 <li> <tt>AllowedMemoryNodes=</tt> : <strong>3</strong>. </li> 953 <p /> 954 <li> <tt>StartupAllowedMemoryNodes=</tt> : <strong>9</strong>. 955 Involves startup and shutdown. </li> 956 <p /> 957 <li> <tt>MemoryAccounting=</tt> : <strong>3</strong>. </li> 958 <p /> 959 <li> <tt>MemoryMin=</tt> : <strong>3</strong>. </li> 960 <p /> 961 <li> <tt>MemoryLow=</tt> : <strong>3</strong>. </li> 962 <p /> 963 <li> <tt>MemoryHigh=</tt> : <strong>3</strong>. </li> 964 <p /> 965 <li> <tt>MemoryMax=</tt> : <strong>3</strong>. </li> 966 <p /> 967 <li> <tt>MemorySwapMax=</tt> : <strong>3</strong>. </li> 968 <p /> 969 <li> <tt>MemoryZSwapMax=</tt> : <strong>3</strong>. </li> 970 <p /> 971 <li> <tt>TasksAccounting=</tt> : <strong>3</strong>. </li> 972 <p /> 973 <li> <tt>TasksMax=</tt> : <strong>3</strong>. </li> 974 <p /> 975 <li> <tt>IOAccounting=</tt> : <strong>3</strong>. </li> 976 <p /> 977 <li> <tt>IOWeight=</tt> : <strong>3</strong>. </li> 978 <p /> 979 <li> <tt>StartupIOWeight=</tt> : <strong>9</strong>. Involves 980 startup and shutdown. </li> 981 <p /> 982 <li> <tt>IODeviceWeight=</tt> : <strong>5</strong>. </li> 983 <p /> 984 <li> <tt>IOReadBandwidthMax=</tt> : <strong>5</strong>. </li> 985 <p /> 986 <li> <tt>IOWriteBandwidthMax=</tt> : <strong>5</strong>. </li> 987 <p /> 988 <li> <tt>IOReadIOPSMax=</tt> : <strong>5</strong>. </li> 989 <p /> 990 <li> <tt>IOWriteIOPSMax=</tt> : <strong>5</strong>. </li> 991 <p /> 992 <li> <tt>IODeviceLatencyTargetSec=</tt> : <strong>4</strong>. </li> 993 <p /> 994 <li> <tt>IPAccounting=</tt> : <strong>7</strong>. </li> 995 <p /> 996 <li> <tt>IPAddressAllow=</tt> : <strong>7</strong>. </li> 997 <p /> 998 <li> <tt>IPAddressDeny=</tt> : <strong>7</strong>. </li> 999 <p /> 1000 <li> <tt>IPIngressFilterPath=</tt> : <strong>8</strong>. </li> 1001 <p /> 1002 <li> <tt>IPEgressFilterPath=</tt> : <strong>8</strong>. </li> 1003 <p /> 1004 <li> <tt>BPFProgram=</tt> : <strong>8</strong>. </li> 1005 <p /> 1006 <li> <tt>SocketBindAllow=</tt> : <strong>6</strong>. </li> 1007 <p /> 1008 <li> <tt>SocketBindDeny=</tt> : <strong>6</strong>. </li> 1009 <p /> 1010 <li> <tt>RestrictNetworkInterfaces=</tt> : <strong>4</strong>. </li> 1011 <p /> 1012 <li> <tt>DeviceAllow=</tt> : <strong>6</strong>. </li> 1013 <p /> 1014 <li> <tt>DevicePolicy=</tt> : <strong>6</strong>. </li> 1015 <p /> 1016 <li> <tt>Slice=</tt> : <strong>9</strong>. Slices are a systemd concept, 1017 and fully implementing them requires a holistic system analysis. </li> 1018 <p /> 1019 <li> <tt>Delegate=</tt> : <strong>4</strong>. </li> 1020 <p /> 1021 <li> <tt>DisableControllers=</tt> : <strong>3</strong>. </li> 1022 <p /> 1023 <li> <tt>ManagedOOMSwap=</tt> : <strong>8</strong>. Out-of-memory 1024 management is an entire systemd subsystem; instead of implementing that, 1025 we recommend provisioning your machines correctly, and freeing up more 1026 resources for your applications by using s6. 1027 <p /> 1028 <li> <tt>ManagedOOMMemoryPressure=</tt> : <strong>8</strong>. </li> 1029 <p /> 1030 <li> <tt>ManagedOOMMemoryPressureLimit=</tt> : <strong>8</strong>. </li> 1031 <p /> 1032 <li> <tt>ManagedOOMPreference=</tt> : <strong>8</strong>. </li> 1033 </ul> 1034 1035 1036 <h2 id="by-difficulty"> Directives rated by difficulty </h2> 1037 1038 <p> 1039 Use this section to answer the question: "If I were to write a converter tool 1040 from systemd to s6, what subset of the unit file syntax should I focus on 1041 first?" 1042 </p> 1043 1044 <p> 1045 Take this classification with a grain of salt: for instance, it does not 1046 make sense to implement an easy directive if it's only used in the context 1047 of a larger subsystem that's much harder to implement - typically, most 1048 cgroups-related resource control directives. 1049 </p> 1050 1051 <h3 id="difficulty-0"> 1052 Difficulty: 0 — directives that can be ignored 1053 </h3> 1054 1055 <ul> 1056 <li> <tt>Description=</tt> </li> 1057 <li> <tt>Documentation=</tt> </li> 1058 <li> <tt>Upholds=</tt> </li> 1059 <li> <tt>PropagatesReloadTo=</tt> </li> 1060 <li> <tt>PropagatesStopTo=</tt> </li> 1061 <li> <tt>StopPropagatedFrom=</tt> </li> 1062 <li> <tt>IgnoreOnIsolate=</tt> </li> 1063 <li> <tt>StopWhenUnneeded=</tt> </li> 1064 <li> <tt>AllowIsolate=</tt> </li> 1065 <li> <tt>CollectMode=</tt> </li> 1066 <li> <tt>SourcePath=</tt> </li> 1067 <li> <tt>Type=idle</tt> </li> 1068 <li> <tt>RemainAfterExit=</tt> </li> 1069 <li> <tt>GuessMainPid=</tt> </li> 1070 <li> <tt>ExecReload=</tt> </li> 1071 <li> <tt>TimeoutStartFailureMode=</tt> </li> 1072 <li> <tt>TimeoutStopFailureMode=</tt> </li> 1073 </ul> 1074 1075 <h3 id="difficulty-1"> 1076 Difficulty: 1 — direct functionality mapping 1077 </h3> 1078 1079 <ul> 1080 <li> <tt>RefuseManualStop=</tt> </li> 1081 <li> <tt>FailureActionExitStatus=</tt> </li> 1082 <li> <tt>SuccessActionExitStatus=</tt> </li> 1083 <li> <tt>Type=simple</tt>, <tt>exec</tt> or <tt>oneshot</tt> </li> 1084 <li> <tt>ExitType=main</tt> </li> 1085 <li> <tt>TimeoutStartSec=</tt> </li> 1086 <li> <tt>TimeoutStopSec=</tt> </li> 1087 <li> <tt>TimeoutSec=</tt> </li> 1088 <li> <tt>Restart=always</tt> </li> 1089 <li> <tt>RestartPreventExitStatus=</tt> </li> 1090 <li> <tt>NotifyAccess=none</tt> </li> 1091 <li> <tt>ExecSearchPath=</tt> </li> 1092 <li> <tt>RootDirectory=</tt> </li> 1093 <li> <tt>SupplementaryGroups=</tt> </li> 1094 <li> <tt>LimitCPU=</tt> </li> 1095 <li> <tt>LimitFSIZE=</tt> </li> 1096 <li> <tt>LimitDATA=</tt> </li> 1097 <li> <tt>LimitSTACK=</tt> </li> 1098 <li> <tt>LimitCORE=</tt> </li> 1099 <li> <tt>LimitRSS=</tt> </li> 1100 <li> <tt>LimitNOFILE=</tt> </li> 1101 <li> <tt>LimitAS=</tt> </li> 1102 <li> <tt>LimitNPROC=</tt> </li> 1103 <li> <tt>LimitMEMLOCK=</tt> </li> 1104 <li> <tt>UMask=</tt> </li> 1105 <li> <tt>Nice=</tt> </li> 1106 <li> <tt>RuntimeDirectory=</tt> </li> 1107 <li> <tt>StateDirectory=</tt> </li> 1108 <li> <tt>CacheDirectory=</tt> </li> 1109 <li> <tt>LogsDirectory=</tt> </li> 1110 <li> <tt>ConfigurationDirectory=</tt> </li> 1111 <li> <tt>RuntimeDirectoryMode=</tt> </li> 1112 <li> <tt>StateDirectoryMode=</tt> </li> 1113 <li> <tt>CacheDirectoryMode=</tt> </li> 1114 <li> <tt>LogsDirectoryMode=</tt> </li> 1115 <li> <tt>ConfigurationDirectoryMode=</tt> </li> 1116 <li> <tt>Environment=</tt> </li> 1117 <li> <tt>EnvironmentFile=</tt> </li> 1118 <li> <tt>PassEnvironment=</tt> </li> 1119 <li> <tt>UnsetEnvironment=</tt> </li> 1120 <li> <tt>StandardInput=</tt> </li> 1121 <li> <tt>StandardOutput=</tt> (except <tt>journal</tt>) </li> 1122 <li> <tt>StandardError=</tt> (except <tt>journal</tt>) </li> 1123 <li> <tt>TTYPath=</tt> </li> 1124 <li> <tt>KillMode=process</tt> </li> 1125 <li> <tt>KillSignal=</tt> </li> 1126 <li> <tt>SendSIGKILL=</tt> </li> 1127 </ul> 1128 1129 <h3 id="difficulty-2"> 1130 Difficulty: 2 — straightforward implementation 1131 </h3> 1132 1133 <ul> 1134 <li> <tt>Requires=</tt> </li> 1135 <li> <tt>Before=</tt> </li> 1136 <li> <tt>After=</tt> </li> 1137 <li> <tt>OnSuccess=</tt> </li> 1138 <li> <tt>DefaultDependencies=</tt> </li> 1139 <li> <tt>Type=forking</tt> </li> 1140 <li> <tt>PIDFile=</tt> </li> 1141 <li> <tt>ExecStart=</tt> (omitting some prefixes) </li> 1142 <li> <tt>ExecStartPre=</tt> </li> 1143 <li> <tt>ExecStartPost=</tt> </li> 1144 <li> <tt>ExecCondition=</tt> </li> 1145 <li> <tt>ExecStopPost=</tt> </li> 1146 <li> <tt>RestartSec=</tt> </li> 1147 <li> <tt>Restart=</tt> except <tt>on-watchdog</tt> </li> 1148 <li> <tt>RestartForceExitStatus=</tt> </li> 1149 <li> <tt>RootDirectoryStartOnly=</tt> </li> 1150 <li> <tt>WorkingDirectory=</tt> </li> 1151 <li> <tt>LimitLOCKS=</tt> </li> 1152 <li> <tt>LimitSIGPENDING=</tt> </li> 1153 <li> <tt>LimitMSGQUEUE=</tt> </li> 1154 <li> <tt>LimitNICE=</tt> </li> 1155 <li> <tt>LimitRTPRIO=</tt> </li> 1156 <li> <tt>LimitRTTIME=</tt> </li> 1157 <li> <tt>OOMScoreAdjust=</tt> </li> 1158 <li> <tt>IgnoreSIGPIPE=</tt> </li> 1159 <li> <tt>StandardInputText=</tt> </li> 1160 <li> <tt>StandardInputData=</tt> </li> 1161 <li> <tt>SyslogIdentifier=</tt> </li> 1162 <li> <tt>SyslogFacility=</tt> </li> 1163 <li> <tt>SyslogLevel=</tt> </li> 1164 <li> <tt>KillMode=none</tt> </li> 1165 </ul> 1166 1167 <h3 id="difficulty-3"> 1168 Difficulty: 3 — requires easy additional programming 1169 </h3> 1170 1171 <ul> 1172 <li> <tt>Wants=</tt> </li> 1173 <li> <tt>Requisite=</tt> </li> 1174 <li> <tt>BindsTo=</tt> </li> 1175 <li> <tt>PartOf=</tt> </li> 1176 <li> <tt>FailureAction=</tt> </li> 1177 <li> <tt>SuccessAction=</tt> </li> 1178 <li> <tt>StartLimitIntervalSec=</tt> </li> 1179 <li> <tt>StartLimitBurst=</tt> </li> 1180 <li> <tt>StartLimitAction=</tt> </li> 1181 <li> <tt>ExitType=cgroup</tt> </li> 1182 <li> <tt>SuccessExitStatus=</tt> </li> 1183 <li> <tt>User=</tt> </li> 1184 <li> <tt>Group=</tt> </li> 1185 <li> <tt>Personality=</tt> </li> 1186 <li> <tt>CPUSchedulingPolicy=</tt> </li> 1187 <li> <tt>CPUSchedulingPriority=</tt> </li> 1188 <li> <tt>CPUSchedulingResetOnFork=</tt> </li> 1189 <li> <tt>CPUAffinity=</tt> </li> 1190 <li> <tt>NUMAPolicy=</tt> </li> 1191 <li> <tt>NUMAMask=</tt> </li> 1192 <li> <tt>IOSchedulingClass=</tt> </li> 1193 <li> <tt>IOSchedulingPriority=</tt> </li> 1194 <li> <tt>RuntimeDirectoryPreserve=</tt> </li> 1195 <li> <tt>TimeoutCleanSec=</tt> </li> 1196 <li> <tt>LoglevelMax=</tt> </li> 1197 <li> <tt>TTYReset=</tt> </li> 1198 <li> <tt>TTYVHangup=</tt> </li> 1199 <li> <tt>TTYRows=</tt> </li> 1200 <li> <tt>TTYColumns=</tt> </li> 1201 <li> <tt>TTYDisallocate=</tt> </li> 1202 <li> <tt>KillMode=control-group</tt> and <tt>mixed</tt> </li> 1203 <li> <tt>CPUAccounting=</tt> </li> 1204 <li> <tt>AllowedCPUs=</tt> </li> 1205 <li> <tt>AllowedMemoryNodes=</tt> </li> 1206 <li> <tt>MemoryAccounting=</tt> </li> 1207 <li> <tt>MemoryMin=</tt> </li> 1208 <li> <tt>MemoryLow=</tt> </li> 1209 <li> <tt>MemoryHigh=</tt> </li> 1210 <li> <tt>MemoryMax=</tt> </li> 1211 <li> <tt>MemorySwapMax=</tt> </li> 1212 <li> <tt>MemoryZSwapMax=</tt> </li> 1213 <li> <tt>TasksAccounting=</tt> </li> 1214 <li> <tt>TasksMax=</tt> </li> 1215 <li> <tt>IOAccounting=</tt> </li> 1216 <li> <tt>IOWeight=</tt> </li> 1217 <li> <tt>DisableControllers=</tt> </li> 1218 </ul> 1219 1220 <h3 id="difficulty-4"> 1221 Difficulty: 4 — requires medium additional programming 1222 </h3> 1223 1224 <ul> 1225 <li> <tt>RuntimeMaxSec=</tt> </li> 1226 <li> <tt>RuntimeRandomizedExtraSec=</tt> </li> 1227 <li> <tt>RequiresMountsFor=</tt> </li> 1228 <li> <tt>RefuseManualStart=</tt> </li> 1229 <li> <tt>PAMName=</tt> </li> 1230 <li> <tt>CapabilityBoundingSet=</tt> </li> 1231 <li> <tt>AmbientCapabilities=</tt> </li> 1232 <li> <tt>NoNewPrivileges=</tt> </li> 1233 <li> <tt>SecureBits=</tt> </li> 1234 <li> <tt>CoredumpFilter=</tt> </li> 1235 <li> <tt>TimerSlackNSec=</tt> </li> 1236 <li> <tt>LogFilterPatterns=</tt> </li> 1237 <li> <tt>SyslogLevelPrefix=</tt> </li> 1238 <li> <tt>UtmpIdentifier=</tt> </li> 1239 <li> <tt>UtmpMode=</tt> </li> 1240 <li> <tt>CPUWeight=</tt> </li> 1241 <li> <tt>CPUQuota=</tt> </li> 1242 <li> <tt>CPUQuotaPeriodSec=</tt> </li> 1243 <li> <tt>IODeviceLatencyTargetSec=</tt> </li> 1244 <li> <tt>RestrictNetworkInterfaces=</tt> </li> 1245 <li> <tt>Delegate=</tt> </li> 1246 </ul> 1247 1248 <h3 id="difficulty-5"> 1249 Difficulty: 5 — requires complex additional programming 1250 </h3> 1251 1252 <ul> 1253 <li> <tt>Conflicts=</tt> </li> 1254 <li> <tt>OnFailure=</tt> </li> 1255 <li> <tt>RebootArgument=</tt> </li> 1256 <li> <tt>Type=dbus</tt> </li> 1257 <li> <tt>BusName=</tt> </li> 1258 <li> <tt>ExecStop=</tt> </li> 1259 <li> <tt>NonBlocking=</tt> </li> 1260 <li> <tt>Sockets=</tt> </li> 1261 <li> <tt>DynamicUser=</tt> </li> 1262 <li> <tt>SELinuxContext=</tt> </li> 1263 <li> <tt>AppArmorProfile=</tt> </li> 1264 <li> <tt>SmackProcessLabel=</tt> </li> 1265 <li> <tt>KeyringMode=</tt> </li> 1266 <li> <tt>ReadWritePaths=</tt> </li> 1267 <li> <tt>ReadOnlyPaths=</tt> </li> 1268 <li> <tt>InaccessiblePaths=</tt> </li> 1269 <li> <tt>ExecPaths=</tt> </li> 1270 <li> <tt>NoExecPaths=</tt> </li> 1271 <li> <tt>TemporaryFilesystem=</tt> </li> 1272 <li> <tt>PrivateTmp=</tt> </li> 1273 <li> <tt>PrivateDevices=</tt> </li> 1274 <li> <tt>PrivateIPC=</tt> </li> 1275 <li> <tt>IPCNamespacePath=</tt> </li> 1276 <li> <tt>PrivateUsers=</tt> </li> 1277 <li> <tt>ProtectHostname=</tt> </li> 1278 <li> <tt>RemoveIPC=</tt> </li> 1279 <li> <tt>PrivateMounts=</tt> </li> 1280 <li> <tt>RestartKillSignal=</tt> </li> 1281 <li> <tt>SendSIGHUP=</tt> </li> 1282 <li> <tt>FinalKillSignal=</tt> </li> 1283 <li> <tt>IODeviceWeight=</tt> </li> 1284 <li> <tt>IOReadBandwidthMax=</tt> </li> 1285 <li> <tt>IOWriteBandwidthMax=</tt> </li> 1286 <li> <tt>IOReadIOPSMax=</tt> </li> 1287 <li> <tt>IOWriteIOPSMax=</tt> </li> 1288 </ul> 1289 1290 <h3 id="difficulty-6"> 1291 Difficulty: 6 — requires a full independent implementation 1292 of a Linux subsystem and/or a part of the systemd architecture 1293 </h3> 1294 1295 <ul> 1296 <li> <tt>OnFailureJobMode=</tt> </li> 1297 <li> <tt>RootImage=</tt> </li> 1298 <li> <tt>RootImageOptions=</tt> </li> 1299 <li> <tt>MountAPIVFS=</tt> </li> 1300 <li> <tt>ProtectProc=</tt> </li> 1301 <li> <tt>ProcSubset=</tt> </li> 1302 <li> <tt>BindPaths=</tt> </li> 1303 <li> <tt>BindReadOnlyPaths=</tt> </li> 1304 <li> <tt>MountImages=</tt> </li> 1305 <li> <tt>ExtensionImages=</tt> </li> 1306 <li> <tt>ExtensionDirectories=</tt> </li> 1307 <li> <tt>ProtectSystem=</tt> </li> 1308 <li> <tt>ProtectHome=</tt> </li> 1309 <li> All <a href="https://man7.org/linux/man-pages/man5/systemd.exec.5.html#CREDENTIALS">credentials-related</a> directives </li> 1310 <li> <tt>SocketBindAllow=</tt> </li> 1311 <li> <tt>SocketBindDeny=</tt> </li> 1312 <li> <tt>DeviceAllow=</tt> </li> 1313 <li> <tt>DevicePolicy=</tt> </li> 1314 </ul> 1315 1316 <h3 id="difficulty-7"> 1317 Difficulty: 7 — requires a full independent implementation 1318 of a complex Linux subsystem and/or a significant part of the 1319 systemd architecture 1320 </h3> 1321 1322 <ul> 1323 <li> <tt>Type=notify</tt> </li> 1324 <li> <tt>TimeoutAbortSec=</tt> </li> 1325 <li> <tt>TimeoutStartFailureMode=abort</tt> </li> 1326 <li> <tt>TimeoutStopFailureMode=abort</tt> </li> 1327 <li> <tt>WatchdogSec=</tt> </li> 1328 <li> <tt>Restart=on-watchdog</tt> </li> 1329 <li> <tt>NotifyAccess=</tt> </li> 1330 <li> <tt>FileDescriptorStoreMax=</tt> </li> 1331 <li> <tt>ProtectClock=</tt> </li> 1332 <li> <tt>ProtectKernelTunables=</tt> </li> 1333 <li> <tt>ProtectKernelModules=</tt> </li> 1334 <li> <tt>ProtectKernelLogs=</tt> </li> 1335 <li> <tt>ProtectControlGroups=</tt> </li> 1336 <li> <tt>RestrictAddressFamilies=</tt> </li> 1337 <li> <tt>RestrictFilesystems=</tt> </li> 1338 <li> <tt>RestrictNamespaces=</tt> </li> 1339 <li> <tt>LockPersonality=</tt> </li> 1340 <li> <tt>MemoryDenyWriteExecute=</tt> </li> 1341 <li> <tt>RestrictRealtime=</tt> </li> 1342 <li> <tt>RestrictSUIDSGID=</tt> </li> 1343 <li> <tt>WatchdogSignal=</tt> </li> 1344 <li> <tt>IPAccounting=</tt> </li> 1345 <li> <tt>IPAddressAllow=</tt> </li> 1346 <li> <tt>IPAddressDeny=</tt> </li> 1347 </ul> 1348 1349 <h3 id="difficulty-8"> 1350 Difficulty: 8 — requires a complete implementation of complex 1351 Linux-specific tooling 1352 </h3> 1353 1354 <ul> 1355 <li> <tt>JoinsNamespaceOf=</tt> </li> 1356 <li> <tt>PrivateNetwork=</tt> </li> 1357 <li> <tt>NetworkNamespacePath=</tt> </li> 1358 <li> <tt>SystemCallFilter=</tt> </li> 1359 <li> <tt>SystemCallErrorNumber=</tt> </li> 1360 <li> <tt>SystemCallArchitectures=</tt> </li> 1361 <li> <tt>SystemCallLog=</tt> </li> 1362 <li> <tt>IPIngressFilterPath=</tt> </li> 1363 <li> <tt>IPEgressFilterPath=</tt> </li> 1364 <li> <tt>BPFProgram=</tt> </li> 1365 <li> <tt>ManagedOOMSwap=</tt> </li> 1366 <li> <tt>ManagedOOMMemoryPressure=</tt> </li> 1367 <li> <tt>ManagedOOMMemoryPressureLimit=</tt> </li> 1368 <li> <tt>ManagedOOMPreference=</tt> </li> 1369 </ul> 1370 1371 <h3 id="difficulty-9"> 1372 Difficulty: 9 — requires a full system analysis and remodelization 1373 </h3> 1374 1375 <ul> 1376 <li> <tt>JobTimeoutSec=</tt> </li> 1377 <li> <tt>JobRunningTimeoutSec=</tt> </li> 1378 <li> <tt>JobTimeoutAction=</tt> </li> 1379 <li> <tt>JobTimeoutRebootArgument=</tt> </li> 1380 <li> Conditions and Asserts </li> 1381 <li> <tt>USBFunctionDescriptors=</tt> </li> 1382 <li> <tt>USBFunctionStrings=</tt> </li> 1383 <li> <tt>OOMPolicy=</tt> </li> 1384 <li> <tt>RootHash=</tt> </li> 1385 <li> <tt>RootHashSignature=</tt> </li> 1386 <li> <tt>RootVerity=</tt> </li> 1387 <li> <tt>StartupCPUWeight=</tt> </li> 1388 <li> <tt>StartupAllowedCPUs=</tt> </li> 1389 <li> <tt>StartupAllowedMemoryNodes=</tt> </li> 1390 <li> <tt>StartupIOWeight=</tt> </li> 1391 <li> <tt>Slice=</tt> </li> 1392 </ul> 1393 1394 <h3 id="difficulty-10"> 1395 Difficulty: 10 — implementing this basically means reimplementing systemd 1396 </h3> 1397 1398 <ul> 1399 <li> <tt>StandardOutput=journal</tt> </li> 1400 <li> <tt>StandardError=journal</tt> </li> 1401 <li> <tt>LogExtraFields=</tt> </li> 1402 <li> <tt>LogRateLimitIntervalSec=</tt> </li> 1403 <li> <tt>LogRateLimitBurst=</tt> </li> 1404 <li> <tt>LogNamespace=</tt> </li> 1405 </ul> 1406 1407 </body> 1408 </html>