Systemctl service environment setup

How do I correctly make a package available to a systemd service. I tried this but the service failed with an error saying “postgres not found in service path”:

    db = {
      description = "db";
      wantedBy = [ "multi-user.target" ];
      path = [ pkgs.postgresql_12 ];
      serviceConfig = {
        Type = "exec";
        User = "pg_user";
        WorkingDirectory = "/home/pg_user/db";
        ExecStart = "postgres -D pgdata";
      };
    };

Yes, that’s correct. That’s also what the official postgres module is doing: https://github.com/NixOS/nixpkgs/blob/cba5ac76a2be3228635528273bf2162e7b4b1586/nixos/modules/services/databases/postgresql.nix#L328-L335

A few things you can try:

  • systemctl cat db to see how it has been rendered
  • Add echo $PATH to ExecStart to find out what it used. Then look at the entries in the PATH.
  • Use "${pkgs.postgresql_12}/bin/postgres -D pgdata" for the ExecStart as a workaround.
2 Likes

This is the output of cat db:

# /nix/store/a5a5ypd7da5psp2djgk65fn34lqplji7-unit-db.service/db.service
[Unit]
Description=db

[Service]
Environment="LOCALE_ARCHIVE=/nix/store/1xpr86xg998h5acn4zqrx58xjdjqnnds-glibc-locales-2.31/lib/locale/locale-archive"
Environment="PATH=/nix/store/6kj9xn2db0zxagy7kjvd83wfz5r01vx5-postgresql-12.4/bin:/nix/store/w9wc0d31p4z93cbgxijws03j5s2c4gyf-coreutils-8.31/bin:/nix/store/aja0dimyn0sg5b9zf1cav4k43p8h5xqc-findutils-4.7.0/bin:/nix/store/xhvk95cjr2dk339airq>
Environment="TZDIR=/nix/store/xg8nmhp28a5xf6ifgg8n93nrwbp8ghvm-tzdata-2019c/share/zoneinfo"



ExecStart=postgres -D pgdata
Type=exec
User=pg_user
WorkingDirectory=/home/pg_user/db
● db.service - db
     Loaded: bad-setting (Reason: Unit db.service has a bad unit file setting.)
     Active: inactive (dead)

May 02 15:26:25 server systemd[1]: /nix/store/a5a5ypd7da5psp2djgk65fn34lqplji7-unit-db.service/db.service:11: Executable "postgres" not found in path "/nix/store/3ri1jzc32mdlywwwxpj4lzzc0b1w9awf-systemd-246.4/bin/"
May 02 15:26:25 server systemd[1]: db.service: Unit configuration has fatal error, unit will not be started.
May 02 15:26:25 server systemd[1]: db.service: Cannot add dependency job, ignoring: Unit db.service has a bad unit file setting.
May 02 21:51:19 server systemd[1]: /nix/store/a5a5ypd7da5psp2djgk65fn34lqplji7-unit-db.service/db.service:11: Executable "postgres" not found in path "/nix/store/3ri1jzc32mdlywwwxpj4lzzc0b1w9awf-systemd-246.4/bin/"
May 02 21:51:19 server systemd[1]: db.service: Unit configuration has fatal error, unit will not be started.
May 02 21:51:19 server systemd[1]: db.service: Cannot add dependency job, ignoring: Unit db.service has a bad unit file setting.
May 02 21:51:52 server systemd[1]: /nix/store/yvzcqd62mxckkvhmkvbyrsgjpmh4qnl9-unit-db.service/db.service:11: Executable "echo" not found in path "/nix/store/3ri1jzc32mdlywwwxpj4lzzc0b1w9awf-systemd-246.4/bin/"
May 02 21:51:52 server systemd[1]: db.service: Unit configuration has fatal error, unit will not be started.
May 02 21:51:53 server systemd[1]: db.service: Cannot add dependency job, ignoring: Unit db.service has a bad unit file setting.

Thanks for the workaround, it works.

I don’t remember the systemd semantic exactly. It looks like ExecStart doesn’t use the Environment to resolve the path to the executable. Using /bin/sh -c "postgres ..." instead might work. There is also systemd.services.<name>.script which is another abstraction on top of it.

1 Like