Dynamic systemd services

I would like to add some systemd services dynamically to a NixOS system (as opposed to configuring them statically through the systemd.services option).

Unfortunately the /etc/systemd/system directory points into the read-only nix store. What I’ve done so far is make the nix store mutable (by disabling nix.readOnlyStore ) so that I can write the service files dynamically to /etc/systemd/system.

However, besides being hacky it also means that any activation of a new NixOS configuration that changes a systemd service replaces the /etc/systemd/system symlink which means my dynamic services are no longer visible.

Is there a way of having both static, NixOS-managed services as well having dynamic services?

that’s an interesting use case? What exactly are you trying to do with ‘dynamic’ systemd scripts?

making the nixstore writable… probably not the greatest idea for many reasons…

What about something like

monitoring a file called

mydynamicsystemdservices.nix

if the file get changed, then a ‘nixos-rebuild switch’ get triggered,updating your systemd services?

You might even be get a systemd to monitor the file for changes, and enact a nixos-rebuild from systemd, but i’ve never tried, that, there maybe trouble running it via systemd.

just idea’s…

Keeping everything in nix files probably is a good idea, letting you rebuild the entire system if something ‘happens’, also the side effect of managing systemd services with nix, is that as long you don’t nix-collect-garbage , then you can see a history of how they have changed over the lifetime of the system.

If your tracking you /etc/nixos/*.nix files in a source code management system like git, even better for change management?

If you don’t need the services to have root permissions, you can also just add systemd files to $HOME/.config/systemd/user. This is what home-manager does for user services. Also, home-manger just links individual files, it does not link against the directory, so you can have your unit files co-exist with the managed services.

1 Like

There’s a bunch of different options but it all depends on what you mean by “dynamic”.

  1. in case you mean “I know what I want to run, I just don’t always want it running”, you can define the services as normal but without a wantedBy. This way you have to manually start it.
  2. alternatively create some nixos containers with the bits you need and only run those when you need them (that’s what I do for various databases for dev purposes).
  3. if what you are running is dynamic, your best bet is systemd-run

Maybe if you explain your use-case(s) we would be able to help you better.

Thanks for all the ideas already! Let me explain my use case in a bit more detail:

The base part of my system is configured with NixOS. However I use ansible to deploy my application. I’m using ansible because I may need to switch from NixOS to some other OS in the future and I don’t want to lock myself in too tightly by having everything in NixOS.

One of the ansible tasks is to copy the systemd service file of my application to /etc/systemd/system, reload systemd and activate the service.

I was hoping systemd could be configured to monitor an additional directory for service files (like /etc/systemd/system-mutable) where ansible could write the service files.

I just remembered that we patch systemd to also search for service files in /etc/systemd-mutable/system. So that’s probably the simplest solution to use.

I also thought about a potential other solution:
mounting an overlayfs at /etc/systemd/system with the read-only nix store directory as its lowerdir and a writable directory as its upperdir.

I am responding here three years later since /etc/systemd-mutable/{user,system} was removed and this was the primary resource I found. If you can define the dynamic units in the nixos configuration (and not via a mutable process), then systemd.generators are a nice solution that nixos supports.

1 Like