summary refs log blame commit diff
path: root/nixos/modules/system/boot/systemd/user.nix
blob: 3200a58d73c9cbe306f6a687833a696aa4e40b5f (plain) (tree)
1
2
3
4
5
6
7
8
9


                                  
         
 



                                   




                      

                 
               

                
               

















                                  

                                  
                                                  





                                           
                                





                                                                                      
                                                                      
                   
                                      



                                   
                                      
                                                                           



                                      
                                         
                                                                              



                                    
                                       
                                                                            



                                     
                                        
                                                                             



                                     
                                        
                                                                             



                                    
                                       
                                                                            
      





                                                    
                                                                                                    
         
                      
      







                                             





                                             


                                   
                          



                        





                                                                                        






                                                                            
                                                                        






                                                                      



                                                                             






                                                                                                         
{ config, lib, pkgs, utils, ... }:
with utils;
with systemdUtils.unitOptions;
with lib;

let
  cfg = config.systemd.user;

  systemd = config.systemd.package;

  inherit
    (systemdUtils.lib)
    makeUnit
    generateUnits
    targetToUnit
    serviceToUnit
    sliceToUnit
    socketToUnit
    timerToUnit
    pathToUnit;

  upstreamUserUnits = [
    "app.slice"
    "background.slice"
    "basic.target"
    "bluetooth.target"
    "default.target"
    "exit.target"
    "graphical-session-pre.target"
    "graphical-session.target"
    "paths.target"
    "printer.target"
    "session.slice"
    "shutdown.target"
    "smartcard.target"
    "sockets.target"
    "sound.target"
    "systemd-exit.service"
    "timers.target"
    "xdg-desktop-autostart.target"
  ] ++ config.systemd.additionalUpstreamUserUnits;
in {
  options = {
    systemd.user.extraConfig = mkOption {
      default = "";
      type = types.lines;
      example = "DefaultCPUAccounting=yes";
      description = lib.mdDoc ''
        Extra config options for systemd user instances. See man systemd-user.conf for
        available options.
      '';
    };

    systemd.user.units = mkOption {
      description = lib.mdDoc "Definition of systemd per-user units.";
      default = {};
      type = systemdUtils.types.units;
    };

    systemd.user.paths = mkOption {
      default = {};
      type = systemdUtils.types.paths;
      description = lib.mdDoc "Definition of systemd per-user path units.";
    };

    systemd.user.services = mkOption {
      default = {};
      type = systemdUtils.types.services;
      description = lib.mdDoc "Definition of systemd per-user service units.";
    };

    systemd.user.slices = mkOption {
      default = {};
      type = systemdUtils.types.slices;
      description = lib.mdDoc "Definition of systemd per-user slice units.";
    };

    systemd.user.sockets = mkOption {
      default = {};
      type = systemdUtils.types.sockets;
      description = lib.mdDoc "Definition of systemd per-user socket units.";
    };

    systemd.user.targets = mkOption {
      default = {};
      type = systemdUtils.types.targets;
      description = lib.mdDoc "Definition of systemd per-user target units.";
    };

    systemd.user.timers = mkOption {
      default = {};
      type = systemdUtils.types.timers;
      description = lib.mdDoc "Definition of systemd per-user timer units.";
    };

    systemd.additionalUpstreamUserUnits = mkOption {
      default = [];
      type = types.listOf types.str;
      example = [];
      description = ''
        Additional units shipped with systemd that should be enabled for per-user systemd instances.
      '';
      internal = true;
    };
  };

  config = {
    systemd.additionalUpstreamSystemUnits = [
      "user.slice"
    ];

    environment.etc = {
      "systemd/user".source = generateUnits {
        type = "user";
        inherit (cfg) units;
        upstreamUnits = upstreamUserUnits;
        upstreamWants = [];
      };

      "systemd/user.conf".text = ''
        [Manager]
        ${cfg.extraConfig}
      '';
    };

    systemd.user.units =
         mapAttrs' (n: v: nameValuePair "${n}.path"    (pathToUnit    n v)) cfg.paths
      // mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.services
      // mapAttrs' (n: v: nameValuePair "${n}.slice"   (sliceToUnit   n v)) cfg.slices
      // mapAttrs' (n: v: nameValuePair "${n}.socket"  (socketToUnit  n v)) cfg.sockets
      // mapAttrs' (n: v: nameValuePair "${n}.target"  (targetToUnit  n v)) cfg.targets
      // mapAttrs' (n: v: nameValuePair "${n}.timer"   (timerToUnit   n v)) cfg.timers;

    # Generate timer units for all services that have a ‘startAt’ value.
    systemd.user.timers =
      mapAttrs (name: service: {
        wantedBy = ["timers.target"];
        timerConfig.OnCalendar = service.startAt;
      })
      (filterAttrs (name: service: service.startAt != []) cfg.services);

    # Provide the systemd-user PAM service, required to run systemd
    # user instances.
    security.pam.services.systemd-user =
      { # Ensure that pam_systemd gets included. This is special-cased
        # in systemd to provide XDG_RUNTIME_DIR.
        startSession = true;
        # Disable pam_mount in systemd-user to prevent it from being called
        # multiple times during login, because it will prevent pam_mount from
        # unmounting the previously mounted volumes.
        pamMount = false;
      };

    # Some overrides to upstream units.
    systemd.services."user@".restartIfChanged = false;
    systemd.services.systemd-user-sessions.restartIfChanged = false; # Restart kills all active sessions.
  };
}