I’m trying to set up a systemd service to run a package. It needs to have a directory in which it can write to persistent files on disk. I have a ReadWritePaths
key set, and I’m using preStart
to ensure the directory exists. But when I start it up, I get this error:
× my-app.service
Loaded: loaded (/etc/systemd/system/my-app.service; enabled; preset: enabled)
Active: failed (Result: exit-code) since Tue 2023-11-14 05:42:47 UTC; 731ms ago
Duration: 8ms
Process: 11248 ExecStartPre=/nix/store/6l2vbwidanfi0y8ybkk8v9qcrljrq08y-unit-script-my-app-pre-start/bin/my-app-pre-start (code=exited, status=226/NAMESPACE)
IP: 0B in, 0B out
CPU: 2ms
Nov 14 05:42:47 cloud systemd[1]: Starting my-app.service...
Nov 14 05:42:47 cloud (re-start)[11248]: my-app.service: Failed to set up mount namespacing: /run/systemd/unit-root/var/lib/my-app: No such file or directory
Nov 14 05:42:47 cloud (re-start)[11248]: my-app.service: Failed at step NAMESPACE spawning /nix/store/6l2vbwidanfi0y8ybkk8v9qcrljrq08y-unit-script-my-app-pre-start/bin/my-app-pre-start: No such file or directory
Nov 14 05:42:47 cloud systemd[1]: my-app.service: Control process exited, code=exited, status=226/NAMESPACE
There seems to be something I’m missing here, since it’s complaining about the path not existing, even though I’m specifically trying to make sure it does exist. I even tried disabling PrivateTmp, ProtectHome, and ProtectSystem, but it still fails in the same way. Here’s the module that defines the service.
nixosModules.default = { lib, config, ... }: let
cfg = config.services.jonah-id-app;
mkEnableOption = lib.mkEnableOption;
mkOption = lib.mkOption;
mkIf = lib.mkIf;
types = lib.types;
in {
options.services.my-app = {
enable = mkEnableOption "my app service";
writableDir = mkOption {
type = types.str;
default = "/var/lib/my-app/";
};
};
config = mkIf cfg.enable {
systemd.services.my-app = {
wantedBy = ["multi-user.target"];
preStart = "mkdir -p ${cfg.writableDir}";
serviceConfig = {
ExecStart = "${self.packages.x86_64-linux.my-app}/bin/my-app ${cfg.writableDir}";
ReadWritePaths = [cfg.writableDir];
};
};
};
};