summary refs log tree commit diff
path: root/nixos/doc/manual/from_md/development/writing-modules.chapter.xml
diff options
context:
space:
mode:
authorpennae <github@quasiparticle.net>2022-01-09 08:46:55 +0100
committerpennae <github@quasiparticle.net>2022-03-12 00:48:52 +0100
commit40a35299fa30421de85a56f084f6c59d05ea883e (patch)
tree563048cbb3cb7b4fdc870e1e3406b1738d0ec43a /nixos/doc/manual/from_md/development/writing-modules.chapter.xml
parent74f542c42e5bca4f74f53cf7054c8a93d4736f51 (diff)
downloadnixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.tar
nixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.tar.gz
nixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.tar.bz2
nixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.tar.lz
nixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.tar.xz
nixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.tar.zst
nixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.zip
nixos: add functions and documentation for escaping systemd Exec* directives
it's really easy to accidentally write the wrong systemd Exec* directive, ones
that works most of the time but fails when users include systemd metacharacters
in arguments that are interpolated into an Exec* directive. add a few functions
analogous to escapeShellArg{,s} and some documentation on how and when to use them.
Diffstat (limited to 'nixos/doc/manual/from_md/development/writing-modules.chapter.xml')
-rw-r--r--nixos/doc/manual/from_md/development/writing-modules.chapter.xml49
1 files changed, 49 insertions, 0 deletions
diff --git a/nixos/doc/manual/from_md/development/writing-modules.chapter.xml b/nixos/doc/manual/from_md/development/writing-modules.chapter.xml
index e33c24f4f12..367731eda09 100644
--- a/nixos/doc/manual/from_md/development/writing-modules.chapter.xml
+++ b/nixos/doc/manual/from_md/development/writing-modules.chapter.xml
@@ -122,6 +122,25 @@
     services) and <literal>systemd.timers</literal> (the list of
     commands to be executed periodically by <literal>systemd</literal>).
   </para>
+  <para>
+    Care must be taken when writing systemd services using
+    <literal>Exec*</literal> directives. By default systemd performs
+    substitution on <literal>%&lt;char&gt;</literal> specifiers in these
+    directives, expands environment variables from
+    <literal>$FOO</literal> and <literal>${FOO}</literal>, splits
+    arguments on whitespace, and splits commands on
+    <literal>;</literal>. All of these must be escaped to avoid
+    unexpected substitution or splitting when interpolating into an
+    <literal>Exec*</literal> directive, e.g. when using an
+    <literal>extraArgs</literal> option to pass additional arguments to
+    the service. The functions
+    <literal>utils.escapeSystemdExecArg</literal> and
+    <literal>utils.escapeSystemdExecArgs</literal> are provided for
+    this, see <link linkend="exec-escaping-example">Example: Escaping in
+    Exec directives</link> for an example. When using these functions
+    system environment substitution should <emphasis>not</emphasis> be
+    disabled explicitly.
+  </para>
   <anchor xml:id="locate-example" />
   <para>
     <emphasis role="strong">Example: NixOS Module for the
@@ -184,6 +203,36 @@ in {
   };
 }
 </programlisting>
+  <anchor xml:id="exec-escaping-example" />
+  <para>
+    <emphasis role="strong">Example: Escaping in Exec
+    directives</emphasis>
+  </para>
+  <programlisting language="bash">
+{ config, lib, pkgs, utils, ... }:
+
+with lib;
+
+let
+  cfg = config.services.echo;
+  echoAll = pkgs.writeScript &quot;echo-all&quot; ''
+    #! ${pkgs.runtimeShell}
+    for s in &quot;$@&quot;; do
+      printf '%s\n' &quot;$s&quot;
+    done
+  '';
+  args = [ &quot;a%Nything&quot; &quot;lang=\${LANG}&quot; &quot;;&quot; &quot;/bin/sh -c date&quot; ];
+in {
+  systemd.services.echo =
+    { description = &quot;Echo to the journal&quot;;
+      wantedBy = [ &quot;multi-user.target&quot; ];
+      serviceConfig.Type = &quot;oneshot&quot;;
+      serviceConfig.ExecStart = ''
+        ${echoAll} ${utils.escapeSystemdExecArgs args}
+      '';
+    };
+}
+</programlisting>
   <xi:include href="option-declarations.section.xml" />
   <xi:include href="option-types.section.xml" />
   <xi:include href="option-def.section.xml" />