Unverified Commit 24b41896 authored by Florian Klink's avatar Florian Klink Committed by GitHub
Browse files

Merge pull request #207468 from schnusch/systemd-user-tmpfiles-rules

nixos: systemd: add systemd.user.tmpfiles.rules, systemd.user.tmpfiles.users.<name>.rules
parents 11d29ac9 34ad8447
Loading
Loading
Loading
Loading
+75 −0
Original line number Diff line number Diff line
@@ -39,6 +39,20 @@ let
    "timers.target"
    "xdg-desktop-autostart.target"
  ] ++ config.systemd.additionalUpstreamUserUnits;

  writeTmpfiles = { rules, user ? null }:
    let
      suffix = if user == null then "" else "-${user}";
    in
    pkgs.writeTextFile {
      name = "nixos-user-tmpfiles.d${suffix}";
      destination = "/etc/xdg/user-tmpfiles.d/00-nixos${suffix}.conf";
      text = ''
        # This file is created automatically and should not be modified.
        # Please change the options ‘systemd.user.tmpfiles’ instead.
        ${concatStringsSep "\n" rules}
      '';
    };
in {
  options = {
    systemd.user.extraConfig = mkOption {
@@ -93,6 +107,42 @@ in {
      description = lib.mdDoc "Definition of systemd per-user timer units.";
    };

    systemd.user.tmpfiles = {
      rules = mkOption {
        type = types.listOf types.str;
        default = [];
        example = [ "D %C - - - 7d" ];
        description = lib.mdDoc ''
          Global user rules for creation, deletion and cleaning of volatile and
          temporary files automatically. See
          {manpage}`tmpfiles.d(5)`
          for the exact format.
        '';
      };

      users = mkOption {
        description = mdDoc ''
          Per-user rules for creation, deletion and cleaning of volatile and
          temporary files automatically.
        '';
        type = types.attrsOf (types.submodule {
          options = {
            rules = mkOption {
              type = types.listOf types.str;
              default = [];
              example = [ "D %C - - - 7d" ];
              description = mdDoc ''
                Per-user rules for creation, deletion and cleaning of volatile and
                temporary files automatically. See
                {manpage}`tmpfiles.d(5)`
                for the exact format.
              '';
            };
          };
        });
      };
    };

    systemd.additionalUpstreamUserUnits = mkOption {
      default = [];
      type = types.listOf types.str;
@@ -154,5 +204,30 @@ in {
    # Some overrides to upstream units.
    systemd.services."user@".restartIfChanged = false;
    systemd.services.systemd-user-sessions.restartIfChanged = false; # Restart kills all active sessions.

    # enable systemd user tmpfiles
    systemd.user.services.systemd-tmpfiles-setup.wantedBy =
      optional
        (cfg.tmpfiles.rules != [] || any (cfg': cfg'.rules != []) (attrValues cfg.tmpfiles.users))
        "basic.target";

    # /run/current-system/sw/etc/xdg is in systemd's $XDG_CONFIG_DIRS so we can
    # write the tmpfiles.d rules for everyone there
    environment.systemPackages =
      optional
        (cfg.tmpfiles.rules != [])
        (writeTmpfiles { inherit (cfg.tmpfiles) rules; });

    # /etc/profiles/per-user/$USER/etc/xdg is in systemd's $XDG_CONFIG_DIRS so
    # we can write a single user's tmpfiles.d rules there
    users.users =
      mapAttrs
        (user: cfg': {
          packages = optional (cfg'.rules != []) (writeTmpfiles {
            inherit (cfg') rules;
            inherit user;
          });
        })
        cfg.tmpfiles.users;
  };
}
+1 −0
Original line number Diff line number Diff line
@@ -658,6 +658,7 @@ in {
  systemd-portabled = handleTest ./systemd-portabled.nix {};
  systemd-shutdown = handleTest ./systemd-shutdown.nix {};
  systemd-timesyncd = handleTest ./systemd-timesyncd.nix {};
  systemd-user-tmpfiles-rules = handleTest ./systemd-user-tmpfiles-rules.nix {};
  systemd-misc = handleTest ./systemd-misc.nix {};
  systemd-userdbd = handleTest ./systemd-userdbd.nix {};
  systemd-homed = handleTest ./systemd-homed.nix {};
+35 −0
Original line number Diff line number Diff line
import ./make-test-python.nix ({ lib, ... }: {
  name = "systemd-user-tmpfiles-rules";

  meta = with lib.maintainers; {
    maintainers = [ schnusch ];
  };

  nodes.machine = { ... }: {
    users.users = {
      alice.isNormalUser = true;
      bob.isNormalUser = true;
    };

    systemd.user.tmpfiles = {
      rules = [
        "d %h/user_tmpfiles_created"
      ];
      users.alice.rules = [
        "d %h/only_alice"
      ];
    };
  };

  testScript = { ... }: ''
    machine.succeed("loginctl enable-linger alice bob")

    machine.wait_until_succeeds("systemctl --user --machine=alice@ is-active systemd-tmpfiles-setup.service")
    machine.succeed("[ -d ~alice/user_tmpfiles_created ]")
    machine.succeed("[ -d ~alice/only_alice ]")

    machine.wait_until_succeeds("systemctl --user --machine=bob@ is-active systemd-tmpfiles-setup.service")
    machine.succeed("[ -d ~bob/user_tmpfiles_created ]")
    machine.succeed("[ ! -e ~bob/only_alice ]")
  '';
})