Invoke nixos-rebuild command from python script

Highly respected community,

I’m working on a management API for the NixOS and I need to make an endpoint, that will allow to rebuild NixOS configuration by sending request to it. I’ve used subprocess library to invoke shell command nixos-rebuild, but I eventually bumped into the following error:

FileNotFoundError: [Errno 2] No such file or directory: 'nixos-rebuild': 'nixos-rebuild'

I’m packaging my python code as a Nix package and running it using systemd service, so in the systemd unit configuration section, I’ve added nixos-rebuild location on a system to the PATH:

systemd.services.selfprivacy-api = {
      description = "API Server used to control system from the mobile application";
      environment = {
        PYTHONUNBUFFERED = "1";
      };
      path = [ config.nix.package.out ];
      after = [ "network-online.target" ];
      wantedBy = [ "network-online.target" ];
      serviceConfig = {
        User = "root";
        PrivateDevices = "true";
        ProtectKernelTunables = "true";
        ProtectKernelModules = "true";
        LockPersonality = "true";
        RestrictRealtime = "true";
        SystemCallFilter = "@system-service @network-io @signal";
        SystemCallErrorNumber = "EPERM";
        ExecStart = "${selfprivacy-api}/bin/main.py";
        Restart = "always";
        RestartSec = "5";
      };

but it didn’t gave any results.

Could someone please advice, how to correctly configure systemd service, to actually add nixos-rebuild into a PATH?

You want a different package, I think: nixos-rebuild.

nixos-rebuild isn’t part of nix :slight_smile:

1 Like

Yeah, thanks. That seem to solve the issue, but may I please ask you one more question in this thread, related to the strange behavior of nixos-rebuild after adding it to the PATH?

I’ve modified my PATH to include the script:

path = [ config.nix.package.out pkgs.nixos-rebuild  ];

which eventually allowed me to invoke the script, but with strange execution result:

Jul 07 15:55:55 ilchub main.py[230144]: error: remounting /nix/store writable: Operation not permitted
Jul 07 15:55:55 ilchub main.py[230143]: building Nix...
Jul 07 15:55:55 ilchub main.py[230151]: error: remounting /nix/store writable: Operation not permitted
Jul 07 15:55:55 ilchub main.py[230154]: error: remounting /nix/store writable: Operation not permitted
Jul 07 15:55:56 ilchub main.py[230158]: error: remounting /nix/store writable: Operation not permitted
Jul 07 15:55:56 ilchub main.py[230168]: error: remounting /nix/store writable: Operation not permitted
Jul 07 15:55:56 ilchub main.py[230143]: warning: don't know how to get latest Nix
Jul 07 15:55:56 ilchub main.py[230172]: error: remounting /nix/store writable: Operation not permitted
Jul 07 15:55:56 ilchub main.py[230143]: building the system configuration...
Jul 07 15:55:56 ilchub main.py[230176]: error: remounting /nix/store writable: Operation not permitted
Jul 07 15:55:56 ilchub main.py[229397]: 127.0.0.1 - - [07/Jul/2021 15:55:56] "GET /apply HTTP/1.1" 200 -

As can be seen from the serviceConfig snippet, previously provided by me, service is running from the root user, so there shouldn’t be any permissions related problems:

serviceConfig = {
  User = "root";
  ...
};

Do you have an idea of what can be wrong?

I will be very grateful for any hint.

Not sure without a closer look.

Maybe the upstream autoUpgrade unit can help figure out how to do this correctly: nixpkgs/auto-upgrade.nix at 9d1350d9d56411b685ff3de5839ed6728b1bf808 · NixOS/nixpkgs · GitHub

Ah, on closer inspection:

        PrivateDevices = "true";

How exactly are you expecting nix to write to the read-only nix store if it’s not allowed to access that? :slight_smile: You might want to look a bit more closely into what cgroups settings nix needs to function (I imagine it might need to access kernel modules and such too).

1 Like