l0b0
l0b0

Reputation: 58808

How to create a systemd service template in NixOS?

I tried creating a trivial template service:

systemd.services."myuser@" = {
  script = "echo Hi, %u";
};

Unfortunately the %u template is not expanded:

$ sudo systemctl start myuser@foo
$ journalctl --catalog --output=cat --unit myuser@foo
Started [email protected].
Hi, %u
[email protected]: Succeeded.

This is because Nix wraps the template string within a script:

$ systemctl status --lines=0 myuser@foo
● [email protected]
     Loaded: loaded (/nix/store/wiq9v9kgj78yd3h4dc1rgx0jgdxizrp4-unit-myuser-.service/[email protected]; static)
     Active: inactive (dead)
$ systemctl show --property ExecStart [email protected]
ExecStart={ path=/nix/store/d6n5gj0llxi2sqhsb87rz7rl0l2rs4x7-unit-script-myuser_-start/bin/myuser_-start ; argv[]=/nix/store/d6n5gj0llxi2sqhsb87rz7rl0l2rs4x7-unit-script-myuser_-start/bin/myuser_-start ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
$ cat /nix/store/d6n5gj0llxi2sqhsb87rz7rl0l2rs4x7-unit-script-myuser_-start/bin/myuser_-start
#!/nix/store/wv35g5lff84rray15zlzarcqi9fxzz84-bash-4.4-p23/bin/bash -e
echo Hi, %u

What is the canonical way to create a template service in NixOS? Do I need to override ExecStart, or is there a more elegant solution?

Upvotes: 3

Views: 6398

Answers (1)

Robert Hensing
Robert Hensing

Reputation: 7369

systemd.services.<name>.script is only a convenience for otherwise simple services that need a script instead of a command to start. Defining ExecStart is perfectly fine.

systemd.services."myuser@" = {
  serviceConfig.ExecStart = "echo Hi, %u";
};

or pass %u as an argument:

systemd.services."myuser@" = {
  serviceConfig.ExecStart = 
    let
      script = pkgs.writeScript "myuser-start" ''
        #!${pkgs.runtimeShell}
        user="$1"
        echo Hi, $user";
      '';
    in "${script} %u";
};

or is there a more elegant solution?

There's no elegance in configuration.

The way I see it, elegance comes from intrinsic simplicity, whereas abstraction comes from hiding complexity.

Configuration is what emerges when software needs to support more use cases than it can elegantly support. NixOS modules are an effort to both model these configurations and build higher-level modules and options on top of them, forming abstractions that are optional. (Fun fact: your own configuration is also a module and is equally powerful)

If you're looking for something to appreciate, it's the fact that you sometimes get to choose which abstractions you use within NixOS, giving you choice. That's the next best thing after intrinsic simplicity, which is rare in configuration, and better than forced abstraction.

Upvotes: 5

Related Questions