s6

Mirror/fork of https://skarnet.org/software/s6/
git clone https://ccx.te2000.cz/git/s6
Log | Files | Refs | README | LICENSE

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 &mdash; 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>&nbsp;: <strong>0</strong>. </li>
    159  <p />
    160  <li> <tt>Documentation=</tt>&nbsp;: <strong>0</strong>. </li>
    161  <p />
    162  <li> <tt>Wants=</tt>&nbsp;: <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>&nbsp;: <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>&nbsp;: <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>&nbsp;: <strong>3</strong>. Same. </li>
    178  <p />
    179  <li> <tt>PartOf=</tt>&nbsp;: <strong>3</strong>. Same. </li>
    180  <p />
    181  <li> <tt>Upholds=</tt>&nbsp;: <strong>0</strong>. In s6, services are upheld by
    182 the supervisor, not by other services. </li>
    183  <p />
    184  <li> <tt>Conflicts=</tt>&nbsp;: <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>&nbsp;: <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>&nbsp;: <strong>2</strong>. </li>
    193  <p />
    194  <li> <tt>OnFailure=</tt>&nbsp;: <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>&nbsp;: <strong>2</strong>. These are oneshot
    199 dependencies. </li>
    200  <p />
    201  <li> <tt>PropagatesReloadTo=</tt>&nbsp;: <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>&nbsp;: <strong>0</strong>. Same. </li>
    206  <p />
    207  <li> <tt>PropagatesStopTo=</tt>&nbsp;: <strong>0</strong>. Same with stopping
    208 a single service or a dependency chain of services. </li>
    209  <p />
    210  <li> <tt>StopPropagatedFrom=</tt>&nbsp;: <strong>0</strong>. Same. </li>
    211  <p />
    212  <li> <tt>JoinsNamespaceOf=</tt>&nbsp;: <strong>8</strong>. There are no
    213 native s6 tools to manage namespaces. </li>
    214  <p />
    215  <li> <tt>RequiresMountsFor=</tt>&nbsp;: <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>&nbsp;: <strong>6</strong>. This is what
    220 happens when you mix layers. </li>
    221  <p />
    222  <li> <tt>IgnoreOnIsolate=</tt>&nbsp;: <strong>0</strong>. </li>
    223  <p />
    224  <li> <tt>StopWhenUnneeded=</tt>&nbsp;: <strong>0</strong>. </li>
    225  <p />
    226  <li> <tt>RefuseManualStart=</tt>&nbsp;: <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>&nbsp;: <strong>1</strong>. </li>
    230  <p />
    231  <li> <tt>AllowIsolate=</tt>&nbsp;: <strong>0</strong>. </li>
    232  <p />
    233  <li> <tt>DefaultDependencies=</tt>&nbsp;: <strong>2</strong>. </li>
    234  <p />
    235  <li> <tt>CollectMode=</tt>&nbsp;: <strong>0</strong>. </li>
    236  <p />
    237  <li> <tt>FailureAction=</tt>&nbsp;: <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>&nbsp;: <strong>3</strong>. That's a oneshot
    243 dependency, but systemd doesn't realize that. </li>
    244  <p />
    245  <li> <tt>FailureActionExitStatus=</tt>&nbsp;: <strong>1</strong>. </li>
    246  <p />
    247  <li> <tt>SuccessActionExitStatus=</tt>&nbsp;: <strong>1</strong>. </li>
    248  <p />
    249  <li> <tt>JobTimeoutSec=</tt>&nbsp;: <strong>9</strong>. s6 has no
    250 concept of jobs. </li>
    251  <p />
    252  <li> <tt>JobRunningTimeoutSec=</tt>&nbsp;: <strong>9</strong>. Same. </li>
    253  <p />
    254  <li> <tt>JobTimeoutAction=</tt>&nbsp;: <strong>9</strong>. Same. </li>
    255  <p />
    256  <li> <tt>JobTimeoutRebootArgument=</tt>&nbsp;: <strong>9</strong>. Same. </li>
    257  <p />
    258  <li> <tt>StartLimitIntervalSec=</tt>&nbsp;: <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>&nbsp;: <strong>3</strong>. Same. </li>
    264  <p />
    265  <li> <tt>StartLimitAction=</tt>&nbsp;: <strong>3</strong>. Same. </li>
    266  <p />
    267  <li> <tt>RebootArgument=</tt>&nbsp;: <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>&nbsp;: <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 &mdash; 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>&nbsp;: depending on its type, a systemd "service"
    308 can translate to wildly different things under s6.
    309   <ul>
    310    <li> <tt>simple</tt>&nbsp;: <strong>1</strong>. </li>
    311    <li> <tt>exec</tt>&nbsp;: <strong>1</strong>. </li>
    312    <li> <tt>forking</tt>&nbsp;: <strong>2</strong>. This type is strongly discouraged. </li>
    313    <li> <tt>oneshot</tt>&nbsp;: <strong>1</strong>. </li>
    314    <li> <tt>dbus</tt>&nbsp;: <strong>5</strong>. This type requires implementing dbus
    315 management programs for s6. </li>
    316    <li> <tt>notify</tt>&nbsp;: <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>&nbsp;: <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>&nbsp;: again, it depends on the value.
    329   <ul>
    330    <li> <tt>main</tt>&nbsp;: <strong>1</strong>. </li>
    331    <li> <tt>cgroup</tt>&nbsp;: <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>&nbsp;: <strong>0</strong>. </li>
    337  <p />
    338  <li> <tt>GuessMainPid=</tt>&nbsp;: <strong>0</strong>. But don't use <tt>forking</tt>
    339 if you can avoid it. </li>
    340  <p />
    341  <li> <tt>PIDFile=</tt>&nbsp;: <strong>2</strong>. Same. </li>
    342  <p />
    343  <li> <tt>BusName=</tt>&nbsp;: <strong>5</strong>. Avoid type <tt>dbus</tt> if possible. </li>
    344  <p />
    345  <li> <tt>ExecStart=</tt>&nbsp;: <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>&nbsp;: <strong>1</strong>. </li>
    354    <li> <tt>-</tt>&nbsp;: <strong>1</strong>. </li>
    355    <li> <tt>:</tt>&nbsp;: <strong>2</strong>. </li>
    356    <li> <tt>+</tt>&nbsp;: <strong>5</strong>. </li>
    357    <li> <tt>!</tt>&nbsp;: <strong>3</strong>. </li>
    358    <li> <tt>!!</tt>&nbsp;: <strong>3</strong>. </li>
    359   </ul>
    360  </li>
    361  <p />
    362  <li> <tt>ExecStartPre=</tt>&nbsp;: <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>&nbsp;: <strong>2</strong>. Same. </li>
    368  <p />
    369  <li> <tt>ExecCondition=</tt>&nbsp;: <strong>2</strong>. </li>
    370  <p />
    371  <li> <tt>ExecReload=</tt>&nbsp;: <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>&nbsp;: <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>&nbsp;: <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>&nbsp;: <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>&nbsp;: <strong>1</strong>. </li>
    391  <p />
    392  <li> <tt>TimeoutStopSec=</tt>&nbsp;: <strong>1</strong>. </li>
    393  <p />
    394  <li> <tt>TimeoutAbortSec=</tt>&nbsp;: <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>&nbsp;: <strong>1</strong>. </li>
    398  <p />
    399  <li> <tt>TimeoutStartFailureMode=</tt>&nbsp;: <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>&nbsp;: <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>&nbsp;: <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>&nbsp;: <strong>4</strong>. Same. </li>
    411  <p />
    412  <li> <tt>WatchdogSec=</tt>&nbsp;: <strong>7</strong>. Requires a watchdog
    413 implementation in the very specific systemd way. </li>
    414  <p />
    415  <li> <tt>Restart=</tt>&nbsp;: depends on the value.
    416   <ul>
    417    <li> <tt>no</tt>&nbsp;: <strong>2</strong>, but why use a process supervisor
    418 in the first place? </li>
    419    <li> <tt>on-success</tt>&nbsp;: <strong>2</strong>. </li>
    420    <li> <tt>on-failure</tt>&nbsp;: <strong>2</strong>. </li>
    421    <li> <tt>on-abnormal</tt>&nbsp;: <strong>2</strong>. </li>
    422    <li> <tt>on-watchdog</tt>&nbsp;: <strong>7</strong>. Again, this requires
    423 a watchdog implementation. </li>
    424    <li> <tt>on-abort</tt>&nbsp;: <strong>2</strong>. </li>
    425    <li> <tt>always</tt>&nbsp;: <strong>1</strong>. </li>
    426   </ul>
    427  </li>
    428  <p />
    429  <li> <tt>SuccessExitStatus=</tt>&nbsp;: <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>&nbsp;: <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>&nbsp;: <strong>2</strong>. </li>
    437  <p />
    438  <li> <tt>RootDirectoryStartOnly=</tt>&nbsp;: <strong>2</strong>. </li>
    439  <p />
    440  <li> <tt>NonBlocking=</tt>&nbsp;: <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>&nbsp;: <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>&nbsp;: <strong>5</strong>. Requires an implementation
    451 of systemd's socket activation. </li>
    452  <p />
    453  <li> <tt>FileDescriptorStoreMax=</tt>&nbsp;: <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>&nbsp;: <strong>9</strong>. This is
    457 low-level machine management, not service management. </li>
    458  <p />
    459  <li> <tt>USBFunctionStrings=</tt>&nbsp;: <strong>9</strong>. Same. </li>
    460  <p />
    461  <li> <tt>OOMPolicy=</tt>&nbsp;: <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>&nbsp;: <strong>1</strong>. </li>
    474  <p />
    475  <li> <tt>WorkingDirectory=</tt>&nbsp;: <strong>2</strong>. </li>
    476  <p />
    477  <li> <tt>RootDirectory=</tt>&nbsp;: <strong>1</strong>. </li>
    478  <p />
    479  <li> <tt>RootImage=</tt>&nbsp;: <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>&nbsp;: <strong>6</strong>. Same. </li>
    486  <p />
    487  <li> <tt>RootHash=</tt>&nbsp;: <strong>9</strong>. Please. </li>
    488  <p />
    489  <li> <tt>RootHashSignature=</tt>&nbsp;: <strong>9</strong>. </li>
    490  <p />
    491  <li> <tt>RootVerity=</tt>&nbsp;: <strong>9</strong>. </li>
    492  <p />
    493  <li> <tt>MountAPIVFS=</tt>&nbsp;: <strong>6</strong>. </li>
    494  <p />
    495  <li> <tt>ProtectProc=</tt>&nbsp;: <strong>6</strong>. </li>
    496  <p />
    497  <li> <tt>ProcSubset=</tt>&nbsp;: <strong>6</strong>. </li>
    498  <p />
    499  <li> <tt>BindPaths=</tt>&nbsp;: <strong>6</strong>. </li>
    500  <p />
    501  <li> <tt>BindReadOnlyPaths=</tt>&nbsp;: <strong>6</strong>. </li>
    502  <p />
    503  <li> <tt>MountImages=</tt>&nbsp;: <strong>6</strong>. </li>
    504  <p />
    505  <li> <tt>ExtensionImages=</tt>&nbsp;: <strong>6</strong>. </li>
    506  <p />
    507  <li> <tt>ExtensionDirectories=</tt>&nbsp;: <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 &mdash; 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>&nbsp;: <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>&nbsp;: <strong>3</strong>. Same. </li>
    539  <p />
    540  <li> <tt>DynamicUser=</tt>&nbsp;: <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>&nbsp;: <strong>1</strong>. Same. </li>
    546  <p />
    547  <li> <tt>PAMName=</tt>&nbsp;: <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>&nbsp;: <strong>4</strong>. This requires
    557 command-line tools implementing capabilities. </li>
    558  <p />
    559  <li> <tt>AmbientCapabilities=</tt>&nbsp;: <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>&nbsp;: <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>&nbsp;: <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>&nbsp;: <strong>5</strong>. This requires
    581 command-line tools managing SELinux. </li>
    582  <p />
    583   <li> <tt>AppArmorProfile=</tt>&nbsp;: <strong>5</strong>. Same, with AppArmor. </li>
    584  <p />
    585   <li> <tt>SmackProcessLabel=</tt>&nbsp;: <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>&nbsp;: <strong>1</strong>. </li>
    598  <p />
    599   <li> <tt>LimitFSIZE=</tt>&nbsp;: <strong>1</strong>. </li>
    600  <p />
    601   <li> <tt>LimitDATA=</tt>&nbsp;: <strong>1</strong>. </li>
    602  <p />
    603   <li> <tt>LimitSTACK=</tt>&nbsp;: <strong>1</strong>. </li>
    604  <p />
    605   <li> <tt>LimitCORE=</tt>&nbsp;: <strong>1</strong>. </li>
    606  <p />
    607   <li> <tt>LimitRSS=</tt>&nbsp;: <strong>1</strong>. </li>
    608  <p />
    609   <li> <tt>LimitNOFILE=</tt>&nbsp;: <strong>1</strong>. </li>
    610  <p />
    611   <li> <tt>LimitAS=</tt>&nbsp;: <strong>1</strong>. </li>
    612  <p />
    613   <li> <tt>LimitNPROC=</tt>&nbsp;: <strong>1</strong>. </li>
    614  <p />
    615   <li> <tt>LimitMEMLOCK=</tt>&nbsp;: <strong>1</strong>. </li>
    616  <p />
    617   <li> <tt>LimitLOCKS=</tt>&nbsp;: <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>&nbsp;: <strong>2</strong>. Same. </li>
    623  <p />
    624   <li> <tt>LimitMSGQUEUE=</tt>&nbsp;: <strong>2</strong>. Same. </li>
    625  <p />
    626   <li> <tt>LimitNICE=</tt>&nbsp;: <strong>2</strong>. Same. </li>
    627  <p />
    628   <li> <tt>LimitRTPRIO=</tt>&nbsp;: <strong>2</strong>. Same. </li>
    629  <p />
    630   <li> <tt>LimitRTTIME=</tt>&nbsp;: <strong>2</strong>. Same. </li>
    631  <p />
    632   <li> <tt>UMask=</tt>&nbsp;: <strong>1</strong>. </li>
    633  <p />
    634   <li> <tt>CoredumpFilter=</tt>&nbsp;: <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>&nbsp;: <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>&nbsp;: <strong>2</strong>. </li>
    642  <p />
    643   <li> <tt>TimerSlackNSec=</tt>&nbsp;: <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>&nbsp;: <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>&nbsp;: <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>&nbsp;: <strong>1</strong>. </li>
    658  <p />
    659  <li> <tt>CPUSchedulingPolicy=</tt>&nbsp;: <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>&nbsp;: <strong>3</strong>. Same. </li>
    663  <p />
    664   <li> <tt>CPUSchedulingResetOnFork=</tt>&nbsp;: <strong>3</strong>. Same. </li>
    665  <p />
    666  <li> <tt>CPUAffinity=</tt>&nbsp;: <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>&nbsp;: <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>&nbsp;: <strong>3</strong>. Same. </li>
    673  <p />
    674  <li> <tt>IOSchedulingClass=</tt>&nbsp;: <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>&nbsp;: <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>&nbsp;: <strong>6</strong>. </li>
    700  <p />
    701  <li> <tt>ProtectHome=</tt>&nbsp;: <strong>6</strong>. </li>
    702  <p />
    703  <li> <tt>RuntimeDirectory=</tt>&nbsp;: <strong>1</strong>. </li>
    704  <p />
    705  <li> <tt>StateDirectory=</tt>&nbsp;: <strong>1</strong>. </li>
    706  <p />
    707  <li> <tt>CacheDirectory=</tt>&nbsp;: <strong>1</strong>. </li>
    708  <p />
    709  <li> <tt>LogsDirectory=</tt>&nbsp;: <strong>1</strong>. </li>
    710  <p />
    711  <li> <tt>ConfigurationDirectory=</tt>&nbsp;: <strong>1</strong>. </li>
    712  <p />
    713  <li> <tt>RuntimeDirectoryMode=</tt>&nbsp;: <strong>1</strong>. </li>
    714  <p />
    715  <li> <tt>StateDirectoryMode=</tt>&nbsp;: <strong>1</strong>. </li>
    716  <p />
    717  <li> <tt>CacheDirectoryMode=</tt>&nbsp;: <strong>1</strong>. </li>
    718  <p />
    719  <li> <tt>LogsDirectoryMode=</tt>&nbsp;: <strong>1</strong>. </li>
    720  <p />
    721  <li> <tt>ConfigurationDirectoryMode=</tt>&nbsp;: <strong>1</strong>. </li>
    722  <p />
    723  <li> <tt>RuntimeDirectoryPreserve=</tt>&nbsp;: <strong>3</strong>. </li>
    724  <p />
    725  <li> <tt>TimeoutCleanSec=</tt>&nbsp;: <strong>3</strong>. </li>
    726  <p />
    727  <li> <tt>ReadWritePaths=</tt>&nbsp;: <strong>5</strong>. </li>
    728  <p />
    729  <li> <tt>ReadOnlyPaths=</tt>&nbsp;: <strong>5</strong>. </li>
    730  <p />
    731  <li> <tt>InaccessiblePaths=</tt>&nbsp;: <strong>5</strong>. </li>
    732  <p />
    733  <li> <tt>ExecPaths=</tt>&nbsp;: <strong>5</strong>. </li>
    734  <p />
    735  <li> <tt>NoExecPaths=</tt>&nbsp;: <strong>5</strong>. </li>
    736  <p />
    737  <li> <tt>TemporaryFileSystem=</tt>&nbsp;: <strong>5</strong>. </li>
    738  <p />
    739  <li> <tt>PrivateTmp=</tt>&nbsp;: <strong>5</strong>. </li>
    740  <p />
    741  <li> <tt>PrivateDevices=</tt>&nbsp;: <strong>5</strong>. </li>
    742  <p />
    743  <li> <tt>PrivateNetwork=</tt>&nbsp;: <strong>8</strong>. </li>
    744  <p />
    745  <li> <tt>NetworkNamespacePath=</tt>&nbsp;: <strong>8</strong>. </li>
    746  <p />
    747  <li> <tt>PrivateIPC=</tt>&nbsp;: <strong>5</strong>. </li>
    748  <p />
    749  <li> <tt>IPCNamespacePath=</tt>&nbsp;: <strong>5</strong>. </li>
    750  <p />
    751  <li> <tt>PrivateUsers=</tt>&nbsp;: <strong>5</strong>. </li>
    752  <p />
    753  <li> <tt>ProtectHostname=</tt>&nbsp;: <strong>5</strong>. </li>
    754  <p />
    755  <li> <tt>ProtectClock=</tt>&nbsp;: <strong>7</strong>. </li>
    756  <p />
    757  <li> <tt>ProtectKernelTunables=</tt>&nbsp;: <strong>7</strong>. </li>
    758  <p />
    759  <li> <tt>ProtectKernelModules=</tt>&nbsp;: <strong>7</strong>. </li>
    760  <p />
    761  <li> <tt>ProtectKernelLogs=</tt>&nbsp;: <strong>7</strong>. </li>
    762  <p />
    763  <li> <tt>ProtectControlGroups=</tt>&nbsp;: <strong>7</strong>. </li>
    764  <p />
    765  <li> <tt>RestrictAddressFamilies=</tt>&nbsp;: <strong>7</strong>. </li>
    766  <p />
    767  <li> <tt>RestrictFilesystems=</tt>&nbsp;: <strong>7</strong>. </li>
    768  <p />
    769  <li> <tt>RestrictNamespaces=</tt>&nbsp;: <strong>7</strong>. </li>
    770  <p />
    771  <li> <tt>LockPersonality=</tt>&nbsp;: <strong>7</strong>. </li>
    772  <p />
    773  <li> <tt>MemoryDenyWriteExecute=</tt>&nbsp;: <strong>7</strong>. </li>
    774  <p />
    775  <li> <tt>RestrictRealtime=</tt>&nbsp;: <strong>7</strong>. </li>
    776  <p />
    777  <li> <tt>RestrictSUIDSGID=</tt>&nbsp;: <strong>7</strong>. </li>
    778  <p />
    779  <li> <tt>RemoveIPC=</tt>&nbsp;: <strong>5</strong>. </li>
    780  <p />
    781  <li> <tt>PrivateMounts=</tt>&nbsp;: <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>&nbsp;: <strong>8</strong>. </li>
    790  <p />
    791  <li> <tt>SystemCallErrorNumber=</tt>&nbsp;: <strong>8</strong>. </li>
    792  <p />
    793  <li> <tt>SystemCallArchitectures=</tt>&nbsp;: <strong>8</strong>. </li>
    794  <p />
    795  <li> <tt>SystemCallLog=</tt>&nbsp;: <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>&nbsp;: <strong>1</strong>. </li>
    804  <p />
    805  <li> <tt>EnvironmentFile=</tt>&nbsp;: <strong>1</strong>. </li>
    806  <p />
    807  <li> <tt>PassEnvironment=</tt>&nbsp;: <strong>1</strong>. </li>
    808  <p />
    809  <li> <tt>UnsetEnvironment=</tt>&nbsp;: <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>&nbsp;: <strong>1</strong>. </li>
    818  <p />
    819  <li> <tt>StandardOutput=</tt>&nbsp;: <strong>1</strong>, except
    820 for <tt>journal</tt> which cannot be supported (<strong>10</strong>). </li>
    821  <p />
    822  <li> <tt>StandardError=</tt>&nbsp;: same.  </li>
    823  <p />
    824  <li> <tt>StandardInputText=</tt>&nbsp;: <strong>2</strong>. </li>
    825  <p />
    826  <li> <tt>StandardInputData=</tt>&nbsp;: <strong>2</strong>. </li>
    827  <p />
    828  <li> <tt>LogLevelMax=</tt>&nbsp;: <strong>3</strong>. </li>
    829  <p />
    830  <li> <tt>LogExtraFields=</tt>&nbsp;: <strong>10</strong>. </li>
    831  <p />
    832  <li> <tt>LogRateLimitIntervalSec=</tt>&nbsp;: <strong>10</strong>. </li>
    833  <p />
    834  <li> <tt>LogRateLimitBurst=</tt>&nbsp;: <strong>10</strong>. </li>
    835  <p />
    836  <li> <tt>LogFilterPatterns=</tt>&nbsp;: <strong>4</strong>. </li>
    837  <p />
    838  <li> <tt>LogNamespace=</tt>&nbsp;: <strong>10</strong>. </li>
    839  <p />
    840  <li> <tt>SyslogIdentifier=</tt>&nbsp;: <strong>2</strong>. </li>
    841  <p />
    842  <li> <tt>SyslogFacility=</tt>&nbsp;: <strong>2</strong>. </li>
    843  <p />
    844  <li> <tt>SyslogLevel=</tt>&nbsp;: <strong>2</strong>. </li>
    845  <p />
    846  <li> <tt>SyslogLevelPrefix=</tt>&nbsp;: <strong>4</strong>. </li>
    847  <p />
    848  <li> <tt>TTYPath=</tt>&nbsp;: <strong>1</strong>. </li>
    849  <p />
    850  <li> <tt>TTYReset=</tt>&nbsp;: <strong>3</strong>. </li>
    851  <p />
    852  <li> <tt>TTYVHangup=</tt>&nbsp;: <strong>3</strong>. </li>
    853  <p />
    854  <li> <tt>TTYRows=</tt>&nbsp;: <strong>3</strong>. </li>
    855  <p />
    856  <li> <tt>TTYColumns=</tt>&nbsp;: <strong>3</strong>. </li>
    857  <p />
    858  <li> <tt>TTYDisallocate=</tt>&nbsp;: <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>&nbsp;: <strong>4</strong>. </li>
    888  <p />
    889  <li> <tt>UtmpMode=</tt>&nbsp;: <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>&nbsp;: 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>&nbsp;: <strong>1</strong>. </li>
    904  <p />
    905  <li> <tt>RestartKillSignal=</tt>&nbsp;: <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>&nbsp;: <strong>5</strong>. Same. </li>
    910  <p />
    911  <li> <tt>SendSIGKILL=</tt>&nbsp;: <strong>1</strong>. </li>
    912  <p />
    913  <li> <tt>FinalKillSignal=</tt>&nbsp;: <strong>5</strong>. (This
    914 is <em>absolute</em> overengineering.) </li>
    915  <p />
    916  <li> <tt>WatchdogSignal=</tt>&nbsp;: <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>&nbsp;: <strong>3</strong>. </li>
    937  <p />
    938  <li> <tt>CPUWeight=</tt>&nbsp;: <strong>4</strong>. </li>
    939  <p />
    940  <li> <tt>StartupCPUWeight=</tt>&nbsp;: <strong>9</strong>. Involves
    941 startup and shutdown. </li>
    942  <p />
    943  <li> <tt>CPUQuota=</tt>&nbsp;: <strong>4</strong>. </li>
    944  <p />
    945  <li> <tt>CPUQuotaPeriodSec=</tt>&nbsp;: <strong>4</strong>. </li>
    946  <p />
    947  <li> <tt>AllowedCPUs=</tt>&nbsp;: <strong>3</strong>. </li>
    948  <p />
    949  <li> <tt>StartupAllowedCPUs=</tt>&nbsp;: <strong>9</strong>. Involves
    950 startup and shutdown. </li>
    951  <p />
    952  <li> <tt>AllowedMemoryNodes=</tt>&nbsp;: <strong>3</strong>. </li>
    953  <p />
    954  <li> <tt>StartupAllowedMemoryNodes=</tt>&nbsp;: <strong>9</strong>.
    955 Involves startup and shutdown. </li>
    956  <p />
    957  <li> <tt>MemoryAccounting=</tt>&nbsp;: <strong>3</strong>. </li>
    958  <p />
    959  <li> <tt>MemoryMin=</tt>&nbsp;: <strong>3</strong>. </li>
    960  <p />
    961  <li> <tt>MemoryLow=</tt>&nbsp;: <strong>3</strong>. </li>
    962  <p />
    963  <li> <tt>MemoryHigh=</tt>&nbsp;: <strong>3</strong>. </li>
    964  <p />
    965  <li> <tt>MemoryMax=</tt>&nbsp;: <strong>3</strong>. </li>
    966  <p />
    967  <li> <tt>MemorySwapMax=</tt>&nbsp;: <strong>3</strong>. </li>
    968  <p />
    969  <li> <tt>MemoryZSwapMax=</tt>&nbsp;: <strong>3</strong>. </li>
    970  <p />
    971  <li> <tt>TasksAccounting=</tt>&nbsp;: <strong>3</strong>. </li>
    972  <p />
    973  <li> <tt>TasksMax=</tt>&nbsp;: <strong>3</strong>. </li>
    974  <p />
    975  <li> <tt>IOAccounting=</tt>&nbsp;: <strong>3</strong>. </li>
    976  <p />
    977  <li> <tt>IOWeight=</tt>&nbsp;: <strong>3</strong>. </li>
    978  <p />
    979  <li> <tt>StartupIOWeight=</tt>&nbsp;: <strong>9</strong>. Involves
    980 startup and shutdown. </li>
    981  <p />
    982  <li> <tt>IODeviceWeight=</tt>&nbsp;: <strong>5</strong>. </li>
    983  <p />
    984  <li> <tt>IOReadBandwidthMax=</tt>&nbsp;: <strong>5</strong>. </li>
    985  <p />
    986  <li> <tt>IOWriteBandwidthMax=</tt>&nbsp;: <strong>5</strong>. </li>
    987  <p />
    988  <li> <tt>IOReadIOPSMax=</tt>&nbsp;: <strong>5</strong>. </li>
    989  <p />
    990  <li> <tt>IOWriteIOPSMax=</tt>&nbsp;: <strong>5</strong>. </li>
    991  <p />
    992  <li> <tt>IODeviceLatencyTargetSec=</tt>&nbsp;: <strong>4</strong>. </li>
    993  <p />
    994  <li> <tt>IPAccounting=</tt>&nbsp;: <strong>7</strong>. </li>
    995  <p />
    996  <li> <tt>IPAddressAllow=</tt>&nbsp;: <strong>7</strong>. </li>
    997  <p />
    998  <li> <tt>IPAddressDeny=</tt>&nbsp;: <strong>7</strong>. </li>
    999  <p />
   1000  <li> <tt>IPIngressFilterPath=</tt>&nbsp;: <strong>8</strong>. </li>
   1001  <p />
   1002  <li> <tt>IPEgressFilterPath=</tt>&nbsp;: <strong>8</strong>. </li>
   1003  <p />
   1004  <li> <tt>BPFProgram=</tt>&nbsp;: <strong>8</strong>. </li>
   1005  <p />
   1006  <li> <tt>SocketBindAllow=</tt>&nbsp;: <strong>6</strong>. </li>
   1007  <p />
   1008  <li> <tt>SocketBindDeny=</tt>&nbsp;: <strong>6</strong>. </li>
   1009  <p />
   1010  <li> <tt>RestrictNetworkInterfaces=</tt>&nbsp;: <strong>4</strong>. </li>
   1011  <p />
   1012  <li> <tt>DeviceAllow=</tt>&nbsp;: <strong>6</strong>. </li>
   1013  <p />
   1014  <li> <tt>DevicePolicy=</tt>&nbsp;: <strong>6</strong>. </li>
   1015  <p />
   1016  <li> <tt>Slice=</tt>&nbsp;: <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>&nbsp;: <strong>4</strong>. </li>
   1020  <p />
   1021  <li> <tt>DisableControllers=</tt>&nbsp;: <strong>3</strong>. </li>
   1022  <p />
   1023  <li> <tt>ManagedOOMSwap=</tt>&nbsp;: <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>&nbsp;: <strong>8</strong>. </li>
   1029  <p />
   1030  <li> <tt>ManagedOOMMemoryPressureLimit=</tt>&nbsp;: <strong>8</strong>. </li>
   1031  <p />
   1032  <li> <tt>ManagedOOMPreference=</tt>&nbsp;: <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 &mdash; 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 &mdash; 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 &mdash; 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 &mdash; 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 &mdash; 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 &mdash; 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 &mdash; 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 &mdash; 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 &mdash; 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 &mdash; 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 &mdash; 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>