From 8b5d19e6b7cd9fbc23d776e69963d88b3c67910b Mon Sep 17 00:00:00 2001 From: Robert Helgesson Date: Sun, 25 Jun 2017 16:56:54 +0200 Subject: [PATCH 1/8] random-background: actually use image directory option --- modules/services/random-background.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/services/random-background.nix b/modules/services/random-background.nix index d0412310c..c221740ca 100644 --- a/modules/services/random-background.nix +++ b/modules/services/random-background.nix @@ -46,7 +46,7 @@ in Service = { Type = "oneshot"; - ExecStart = "${pkgs.feh}/bin/feh --randomize --bg-fill %h/backgrounds/"; + ExecStart = "${pkgs.feh}/bin/feh --randomize --bg-fill ${cfg.imageDirectory}"; IOSchedulingClass = "idle"; }; From a9343d81947e39cfbae3e4d9d39825c191587541 Mon Sep 17 00:00:00 2001 From: Robert Helgesson Date: Mon, 26 Jun 2017 16:55:28 +0200 Subject: [PATCH 2/8] udiskie: remove taffybar requirement It should be sufficient to have a graphical session going. --- modules/services/udiskie.nix | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/services/udiskie.nix b/modules/services/udiskie.nix index 3fb038a74..981400caa 100644 --- a/modules/services/udiskie.nix +++ b/modules/services/udiskie.nix @@ -13,8 +13,6 @@ with lib; systemd.user.services.udiskie = { Unit = { Description = "Udiskie mount daemon"; - Requires = [ "taffybar.service" ]; - After = [ "taffybar.service" ]; }; Service = { From acf8d4e985d1e31374a8d39239bd94cbf4fbde9f Mon Sep 17 00:00:00 2001 From: Robert Helgesson Date: Mon, 26 Jun 2017 18:26:54 +0200 Subject: [PATCH 3/8] xsession: use systemd graphical targets The systemd targets don't allow direct startup so we create our own target for graphical sessions managed by Home Environment. --- modules/xsession.nix | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/modules/xsession.nix b/modules/xsession.nix index e0dff4552..7f0991f1b 100644 --- a/modules/xsession.nix +++ b/modules/xsession.nix @@ -60,19 +60,12 @@ in }; }; - # For stuff that needs to start just before a graphical session - # starts. - systemd.user.targets.graphical-session-pre = { + # A basic graphical session target for Home Manager. + systemd.user.targets.he-graphical-session = { Unit = { - Description = "Pre-graphical session"; - }; - }; - - # A basic graphical session target. Apparently this will come - # standard in future Systemd versions. - systemd.user.targets.graphical-session = { - Unit = { - Description = "Graphical session"; + Description = "Home Manager X session"; + Requires = [ "graphical-session-pre.target" ]; + BindsTo = [ "graphical-session.target" ]; }; }; @@ -83,6 +76,9 @@ in . "$HOME/.profile" fi + # If there are any running services from a previous session. + systemctl --user stop graphical-session.target graphical-session-pre.target + systemctl --user import-environment DBUS_SESSION_BUS_ADDRESS systemctl --user import-environment DISPLAY systemctl --user import-environment SSH_AUTH_SOCK @@ -90,8 +86,7 @@ in systemctl --user import-environment XDG_DATA_DIRS systemctl --user import-environment XDG_RUNTIME_DIR - systemctl --user restart graphical-session-pre.target - systemctl --user restart graphical-session.target + systemctl --user start he-graphical-session.target ${cfg.initExtra} From 9c17c5ccbbf5626f684eecc2ce660086ac8e249c Mon Sep 17 00:00:00 2001 From: Robert Helgesson Date: Mon, 26 Jun 2017 18:34:09 +0200 Subject: [PATCH 4/8] Clean up systemd units for all graphical services --- modules/services/dunst.nix | 4 ++-- modules/services/gnome-keyring.nix | 3 ++- modules/services/keepassx.nix | 2 ++ modules/services/network-manager-applet.nix | 2 ++ modules/services/random-background.nix | 2 ++ modules/services/redshift.nix | 2 ++ modules/services/taffybar.nix | 2 ++ modules/services/udiskie.nix | 2 ++ modules/services/xscreensaver.nix | 2 ++ modules/xsession.nix | 2 ++ 10 files changed, 20 insertions(+), 3 deletions(-) diff --git a/modules/services/dunst.nix b/modules/services/dunst.nix index a70e8d311..c1f29d942 100644 --- a/modules/services/dunst.nix +++ b/modules/services/dunst.nix @@ -22,8 +22,8 @@ with lib; systemd.user.services.dunst = { Unit = { Description = "Dunst notification daemon"; - Requires = "graphical-session.target"; - After = "graphical-session.target"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; }; Service = { diff --git a/modules/services/gnome-keyring.nix b/modules/services/gnome-keyring.nix index b0edeaed4..b7097d7cd 100644 --- a/modules/services/gnome-keyring.nix +++ b/modules/services/gnome-keyring.nix @@ -28,6 +28,7 @@ in systemd.user.services.gnome-keyring = { Unit = { Description = "GNOME Keyring"; + PartOf = [ "graphical-session-pre.target" ]; }; Service = { @@ -45,7 +46,7 @@ in }; Install = { - WantedBy = [ "graphical-session.target" ]; + WantedBy = [ "graphical-session-pre.target" ]; }; }; }; diff --git a/modules/services/keepassx.nix b/modules/services/keepassx.nix index 0ed90dd04..ff875ee63 100644 --- a/modules/services/keepassx.nix +++ b/modules/services/keepassx.nix @@ -13,6 +13,8 @@ with lib; systemd.user.services.keepassx = { Unit = { Description = "KeePassX password manager"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; }; Install = { diff --git a/modules/services/network-manager-applet.nix b/modules/services/network-manager-applet.nix index a7a90b618..eca5515f2 100644 --- a/modules/services/network-manager-applet.nix +++ b/modules/services/network-manager-applet.nix @@ -13,6 +13,8 @@ with lib; systemd.user.services.network-manager-applet = { Unit = { Description = "Network Manager applet"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; }; Install = { diff --git a/modules/services/random-background.nix b/modules/services/random-background.nix index c221740ca..f1b8d39d1 100644 --- a/modules/services/random-background.nix +++ b/modules/services/random-background.nix @@ -42,6 +42,8 @@ in systemd.user.services.random-background = { Unit = { Description = "Set random desktop background using feh"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; }; Service = { diff --git a/modules/services/redshift.nix b/modules/services/redshift.nix index f89786134..ba9f3b1d3 100644 --- a/modules/services/redshift.nix +++ b/modules/services/redshift.nix @@ -99,6 +99,8 @@ in { systemd.user.services.redshift = { Unit = { Description = "Redshift colour temperature adjuster"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; }; Install = { diff --git a/modules/services/taffybar.nix b/modules/services/taffybar.nix index 87a840634..a452295f2 100644 --- a/modules/services/taffybar.nix +++ b/modules/services/taffybar.nix @@ -27,6 +27,8 @@ in systemd.user.services.taffybar = { Unit = { Description = "Taffybar desktop bar"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; }; Service = { diff --git a/modules/services/udiskie.nix b/modules/services/udiskie.nix index 981400caa..b2a2b4072 100644 --- a/modules/services/udiskie.nix +++ b/modules/services/udiskie.nix @@ -13,6 +13,8 @@ with lib; systemd.user.services.udiskie = { Unit = { Description = "Udiskie mount daemon"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; }; Service = { diff --git a/modules/services/xscreensaver.nix b/modules/services/xscreensaver.nix index 0b1a4573a..b27e5b73a 100644 --- a/modules/services/xscreensaver.nix +++ b/modules/services/xscreensaver.nix @@ -13,6 +13,8 @@ with lib; systemd.user.services.xscreensaver = { Unit = { Description = "XScreenSaver"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; }; Service = { diff --git a/modules/xsession.nix b/modules/xsession.nix index 7f0991f1b..6afb17ba1 100644 --- a/modules/xsession.nix +++ b/modules/xsession.nix @@ -38,6 +38,8 @@ in systemd.user.services.setxkbmap = { Unit = { Description = "Set up keyboard in X"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; }; Install = { From 4c85ff7ff297b784df5c2fed2f65e37e6436a385 Mon Sep 17 00:00:00 2001 From: Robert Helgesson Date: Thu, 29 Jun 2017 00:24:29 +0200 Subject: [PATCH 5/8] xsession: rename graphical session target name The `he` in `he-graphical-session` doesn't make much sense, change it to `hm` for Home Manager. --- modules/xsession.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/xsession.nix b/modules/xsession.nix index 6afb17ba1..0ec95ffe6 100644 --- a/modules/xsession.nix +++ b/modules/xsession.nix @@ -63,7 +63,7 @@ in }; # A basic graphical session target for Home Manager. - systemd.user.targets.he-graphical-session = { + systemd.user.targets.hm-graphical-session = { Unit = { Description = "Home Manager X session"; Requires = [ "graphical-session-pre.target" ]; @@ -88,7 +88,7 @@ in systemctl --user import-environment XDG_DATA_DIRS systemctl --user import-environment XDG_RUNTIME_DIR - systemctl --user start he-graphical-session.target + systemctl --user start hm-graphical-session.target ${cfg.initExtra} From 8af68388699185227295a077a4dd3a50440f5d88 Mon Sep 17 00:00:00 2001 From: Robert Helgesson Date: Thu, 29 Jun 2017 01:03:39 +0200 Subject: [PATCH 6/8] home-environment: prevent delete of non-managed files When a file has disappeared between the previous and the next generations then its symlink in `$HOME` is typically deleted. With this commit we refuse to delete the path unless we are reasonably certain it is a symlink into a Home Manager generation. --- modules/home-environment.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/home-environment.nix b/modules/home-environment.nix index f665833f1..79b4f3444 100644 --- a/modules/home-environment.nix +++ b/modules/home-environment.nix @@ -286,6 +286,8 @@ in home.activation.linkGeneration = dagEntryAfter ["writeBoundary"] ( let + pattern = "-home-manager-files/"; + link = pkgs.writeText "link" '' newGenFiles="$1" shift @@ -298,6 +300,8 @@ in ''; cleanup = pkgs.writeText "cleanup" '' + . ${./lib-bash/color-echo.sh} + newGenFiles="$1" oldGenFiles="$2" shift 2 @@ -306,6 +310,8 @@ in targetPath="$HOME/$relativePath" if [[ -e "$newGenFiles/$relativePath" ]] ; then $VERBOSE_ECHO "Checking $targetPath exists" + elif [[ ! "$(readlink -e "$targetPath")" =~ "${pattern}" ]] ; then + warnEcho "Path '$targetPath' not link into Home Manager generation. Skipping delete." else echo "Checking $targetPath gone (deleting)" $DRY_RUN_CMD rm $VERBOSE_ARG "$targetPath" From acf813cadc33b339cd1d575aba44fdc283717dd7 Mon Sep 17 00:00:00 2001 From: Robert Helgesson Date: Thu, 29 Jun 2017 01:06:08 +0200 Subject: [PATCH 7/8] systemd: add support for socket units --- modules/systemd.nix | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/modules/systemd.nix b/modules/systemd.nix index ef68b6d64..edc89ab0c 100644 --- a/modules/systemd.nix +++ b/modules/systemd.nix @@ -7,7 +7,10 @@ let cfg = config.systemd.user; - enabled = cfg.services != {} || cfg.targets != {} || cfg.timers != {}; + enabled = cfg.services != {} + || cfg.sockets != {} + || cfg.targets != {} + || cfg.timers != {}; toSystemdIni = (import lib/generators.nix).toINI { mkKeyValue = key: value: @@ -50,6 +53,12 @@ in description = "Definition of systemd per-user service units."; }; + sockets = mkOption { + default = {}; + type = types.attrs; + description = "Definition of systemd per-user sockets"; + }; + targets = mkOption { default = {}; type = types.attrs; @@ -72,7 +81,9 @@ in message = let names = concatStringsSep ", " ( - attrNames (cfg.services // cfg.targets // cfg.timers) + attrNames ( + cfg.services // cfg.sockets // cfg.targets // cfg.timers + ) ); in "Must use Linux for modules that require systemd: " + names; @@ -87,6 +98,8 @@ in listToAttrs ( (buildServices "service" cfg.services) ++ + (buildServices "socket" cfg.sockets) + ++ (buildServices "target" cfg.targets) ++ (buildServices "timer" cfg.timers) From 196db18f5bab22c431b57d6763c4b262f504ccbe Mon Sep 17 00:00:00 2001 From: Robert Helgesson Date: Thu, 29 Jun 2017 23:33:28 +0200 Subject: [PATCH 8/8] gpg-agent: use systemd socket activation --- modules/services/gpg-agent.nix | 106 ++++++++++++++++++++++++--------- 1 file changed, 77 insertions(+), 29 deletions(-) diff --git a/modules/services/gpg-agent.nix b/modules/services/gpg-agent.nix index 872b69b20..1d015397c 100644 --- a/modules/services/gpg-agent.nix +++ b/modules/services/gpg-agent.nix @@ -29,41 +29,89 @@ in }; }; - config = mkIf cfg.enable { - home.file.".gnupg/gpg-agent.conf".text = concatStringsSep "\n" ( - optional cfg.enableSshSupport - "enable-ssh-support" - ++ - optional (cfg.defaultCacheTtl != null) - "default-cache-ttl ${toString cfg.defaultCacheTtl}" - ); + config = mkIf cfg.enable (mkMerge [ + { + home.file.".gnupg/gpg-agent.conf".text = concatStringsSep "\n" ( + optional cfg.enableSshSupport + "enable-ssh-support" + ++ + optional (cfg.defaultCacheTtl != null) + "default-cache-ttl ${toString cfg.defaultCacheTtl}" + ); - home.sessionVariables = - optionalAttrs cfg.enableSshSupport { - SSH_AUTH_SOCK = "\${XDG_RUNTIME_DIR}/gnupg/S.gpg-agent.ssh"; + home.sessionVariables = + optionalAttrs cfg.enableSshSupport { + SSH_AUTH_SOCK = "\${XDG_RUNTIME_DIR}/gnupg/S.gpg-agent.ssh"; + }; + + programs.bash.initExtra = '' + GPG_TTY="$(tty)" + export GPG_TTY + gpg-connect-agent updatestartuptty /bye > /dev/null + ''; + } + + # The systemd units below are direct translations of the + # descriptions in the + # + # ${pkgs.gnupg}/share/doc/gnupg/examples/systemd-user + # + # directory. + { + systemd.user.services.gpg-agent = { + Unit = { + Description = "GnuPG cryptographic agent and passphrase cache"; + Documentation = "man:gpg-agent(1)"; + Requires = "gpg-agent.socket"; + After = "gpg-agent.socket"; + # This is a socket-activated service: + RefuseManualStart = true; + }; + + Service = { + ExecStart = "${pkgs.gnupg}/bin/gpg-agent --supervised"; + ExecReload = "${pkgs.gnupg}/bin/gpgconf --reload gpg-agent"; + }; }; - programs.bash.initExtra = '' - GPG_TTY="$(tty)" - export GPG_TTY - gpg-connect-agent updatestartuptty /bye > /dev/null - ''; + systemd.user.sockets.gpg-agent = { + Unit = { + Description = "GnuPG cryptographic agent and passphrase cache"; + Documentation = "man:gpg-agent(1)"; + }; - systemd.user.services.gpg-agent = { - Unit = { - Description = "GnuPG private key agent"; - IgnoreOnIsolate = true; - }; + Socket = { + ListenStream = "%t/gnupg/S.gpg-agent"; + FileDescriptorName = "std"; + SocketMode = "0600"; + DirectoryMode = "0700"; + }; - Service = { - Type = "forking"; - ExecStart = "${pkgs.gnupg}/bin/gpg-agent --daemon"; - Restart = "on-abort"; + Install = { + WantedBy = [ "sockets.target" ]; + }; }; + } - Install = { - WantedBy = [ "default.target" ]; + (mkIf cfg.enableSshSupport { + systemd.user.sockets.gpg-agent-ssh = { + Unit = { + Description = "GnuPG cryptographic agent (ssh-agent emulation)"; + Documentation = "man:gpg-agent(1) man:ssh-add(1) man:ssh-agent(1) man:ssh(1)"; + }; + + Socket = { + ListenStream = "%t/gnupg/S.gpg-agent.ssh"; + FileDescriptorName = "ssh"; + Service = "gpg-agent.service"; + SocketMode = "0600"; + DirectoryMode = "0700"; + }; + + Install = { + WantedBy = [ "sockets.target" ]; + }; }; - }; - }; + }) + ]); }