Skip to main content

Creating SystemD services in Nix

This will show how to create a services in Nix that will execute upon login.

User services

  • Get executed upon user login
  • Key importance is the service_name tag that should be changed per service.
{config, pkgs, lib, ...}:

let
  cfg = config.services.service_name; # Change service_name to your servcice name.
  name = "service_name"; # Call this what you want, but don't put spaces in it
in

with lib;

{
 options.services.service_name = with types; {
   enable = mkEnableOption "A description of your service";
 };

 config =
   let
     mkStartScript = name: pkgs.writeShellScript "${name}.sh" ''
       set -uo pipefail
       ## Do a bunch of stuff in your script .. 
       ## Alternatively you don't need this let statement and can just have the command run in the ExecStart declaration below
       ...
     '';
   in
   mkIf cfg.enable {
     systemd.user.services.service_name = {
       Unit = {
         Description = "A description of your service";
       };
       Install = {
         WantedBy = [ "default.target" ];
       };
       Service = {
         ExecStart = "${mkStartScript name}";
       };
     };
  };
}

After, import it into your configuration and also enable it.

# home.nix

{ config, lib, pkgs, ... }: {
  
  imports = [
    ./services/service_name.nix
  ];

  services.service_name.enable = true ;
}

Timers

  • Add a timer and let it schedule itself. Addontop the above User service underneath cfg.enable
     systemd.user.timers.service_name = {
       Install = {
         WantedBy = [ "timers.target" ];
       };
       Timer = {
         OnBootSec = "10m";       # first run 10min after login
         #OnUnitActiveSec = "1w"; # run weekly
       };	
     };

System Services

As above, there are a few changes..

      systemd.services.service_name = {
        enable = true;
        description = "Description of the Service";
        after = [ "network.service" ];
        serviceConfig = {
          Type = "oneshot";
          ExecStart = "Do something";
          ExecStop = "Do something again";
          RemainAfterExit = "no";
          TimeoutSec = 900;
        };