typioca: 2.7.0 -> 2.8.0
[NixPkgs.git] / nixos / modules / programs / gnupg.nix
blobaa1a536247ce4f09f3fc4d953b5c8a28d6f63011
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
7   cfg = config.programs.gnupg;
9   agentSettingsFormat = pkgs.formats.keyValue {
10     mkKeyValue = lib.generators.mkKeyValueDefault { } " ";
11   };
13   xserverCfg = config.services.xserver;
15   defaultPinentryFlavor =
16     if xserverCfg.desktopManager.lxqt.enable
17     || xserverCfg.desktopManager.plasma5.enable
18     || xserverCfg.desktopManager.deepin.enable then
19       "qt"
20     else if xserverCfg.desktopManager.xfce.enable then
21       "gtk2"
22     else if xserverCfg.enable || config.programs.sway.enable then
23       "gnome3"
24     else
25       "curses";
31   options.programs.gnupg = {
32     package = mkOption {
33       type = types.package;
34       default = pkgs.gnupg;
35       defaultText = literalExpression "pkgs.gnupg";
36       description = lib.mdDoc ''
37         The gpg package that should be used.
38       '';
39     };
41     agent.enable = mkOption {
42       type = types.bool;
43       default = false;
44       description = lib.mdDoc ''
45         Enables GnuPG agent with socket-activation for every user session.
46       '';
47     };
49     agent.enableSSHSupport = mkOption {
50       type = types.bool;
51       default = false;
52       description = lib.mdDoc ''
53         Enable SSH agent support in GnuPG agent. Also sets SSH_AUTH_SOCK
54         environment variable correctly. This will disable socket-activation
55         and thus always start a GnuPG agent per user session.
56       '';
57     };
59     agent.enableExtraSocket = mkOption {
60       type = types.bool;
61       default = false;
62       description = lib.mdDoc ''
63         Enable extra socket for GnuPG agent.
64       '';
65     };
67     agent.enableBrowserSocket = mkOption {
68       type = types.bool;
69       default = false;
70       description = lib.mdDoc ''
71         Enable browser socket for GnuPG agent.
72       '';
73     };
75     agent.pinentryFlavor = mkOption {
76       type = types.nullOr (types.enum pkgs.pinentry.flavors);
77       example = "gnome3";
78       default = defaultPinentryFlavor;
79       defaultText = literalMD ''matching the configured desktop environment'';
80       description = lib.mdDoc ''
81         Which pinentry interface to use. If not null, the path to the
82         pinentry binary will be set in /etc/gnupg/gpg-agent.conf.
83         If not set at all, it'll pick an appropriate flavor depending on the
84         system configuration (qt flavor for lxqt and plasma5, gtk2 for xfce
85         4.12, gnome3 on all other systems with X enabled, ncurses otherwise).
86       '';
87     };
89     agent.settings = mkOption {
90       type = agentSettingsFormat.type;
91       default = { };
92       example = {
93         default-cache-ttl = 600;
94       };
95       description = lib.mdDoc ''
96         Configuration for /etc/gnupg/gpg-agent.conf.
97         See {manpage}`gpg-agent(1)` for supported options.
98       '';
99     };
101     dirmngr.enable = mkOption {
102       type = types.bool;
103       default = false;
104       description = lib.mdDoc ''
105         Enables GnuPG network certificate management daemon with socket-activation for every user session.
106       '';
107     };
108   };
110   config = mkIf cfg.agent.enable {
111     programs.gnupg.agent.settings = {
112       pinentry-program = lib.mkIf (cfg.agent.pinentryFlavor != null)
113         "${pkgs.pinentry.${cfg.agent.pinentryFlavor}}/bin/pinentry";
114     };
116     environment.etc."gnupg/gpg-agent.conf".source =
117       agentSettingsFormat.generate "gpg-agent.conf" cfg.agent.settings;
119     # This overrides the systemd user unit shipped with the gnupg package
120     systemd.user.services.gpg-agent = {
121       unitConfig = {
122         Description = "GnuPG cryptographic agent and passphrase cache";
123         Documentation = "man:gpg-agent(1)";
124         Requires = [ "sockets.target" ];
125       };
126       serviceConfig = {
127         ExecStart = "${cfg.package}/bin/gpg-agent --supervised";
128         ExecReload = "${cfg.package}/bin/gpgconf --reload gpg-agent";
129       };
130     };
132     systemd.user.sockets.gpg-agent = {
133       unitConfig = {
134         Description = "GnuPG cryptographic agent and passphrase cache";
135         Documentation = "man:gpg-agent(1)";
136       };
137       socketConfig = {
138         ListenStream = "%t/gnupg/S.gpg-agent";
139         FileDescriptorName = "std";
140         SocketMode = "0600";
141         DirectoryMode = "0700";
142       };
143       wantedBy = [ "sockets.target" ];
144     };
146     systemd.user.sockets.gpg-agent-ssh = mkIf cfg.agent.enableSSHSupport {
147       unitConfig = {
148         Description = "GnuPG cryptographic agent (ssh-agent emulation)";
149         Documentation = "man:gpg-agent(1) man:ssh-add(1) man:ssh-agent(1) man:ssh(1)";
150       };
151       socketConfig = {
152         ListenStream = "%t/gnupg/S.gpg-agent.ssh";
153         FileDescriptorName = "ssh";
154         Service = "gpg-agent.service";
155         SocketMode = "0600";
156         DirectoryMode = "0700";
157       };
158       wantedBy = [ "sockets.target" ];
159     };
161     systemd.user.sockets.gpg-agent-extra = mkIf cfg.agent.enableExtraSocket {
162       unitConfig = {
163         Description = "GnuPG cryptographic agent and passphrase cache (restricted)";
164         Documentation = "man:gpg-agent(1)";
165       };
166       socketConfig = {
167         ListenStream = "%t/gnupg/S.gpg-agent.extra";
168         FileDescriptorName = "extra";
169         Service = "gpg-agent.service";
170         SocketMode = "0600";
171         DirectoryMode = "0700";
172       };
173       wantedBy = [ "sockets.target" ];
174     };
176     systemd.user.sockets.gpg-agent-browser = mkIf cfg.agent.enableBrowserSocket {
177       unitConfig = {
178         Description = "GnuPG cryptographic agent and passphrase cache (access for web browsers)";
179         Documentation = "man:gpg-agent(1)";
180       };
181       socketConfig = {
182         ListenStream = "%t/gnupg/S.gpg-agent.browser";
183         FileDescriptorName = "browser";
184         Service = "gpg-agent.service";
185         SocketMode = "0600";
186         DirectoryMode = "0700";
187       };
188       wantedBy = [ "sockets.target" ];
189     };
191     systemd.user.services.dirmngr = mkIf cfg.dirmngr.enable {
192       unitConfig = {
193         Description = "GnuPG network certificate management daemon";
194         Documentation = "man:dirmngr(8)";
195         Requires = "dirmngr.socket";
196       };
197       serviceConfig = {
198         ExecStart = "${cfg.package}/bin/dirmngr --supervised";
199         ExecReload = "${cfg.package}/bin/gpgconf --reload dirmngr";
200       };
201     };
203     systemd.user.sockets.dirmngr = mkIf cfg.dirmngr.enable {
204       unitConfig = {
205         Description = "GnuPG network certificate management daemon";
206         Documentation = "man:dirmngr(8)";
207       };
208       socketConfig = {
209         ListenStream = "%t/gnupg/S.dirmngr";
210         SocketMode = "0600";
211         DirectoryMode = "0700";
212       };
213       wantedBy = [ "sockets.target" ];
214     };
216     services.dbus.packages = mkIf (cfg.agent.pinentryFlavor == "gnome3") [ pkgs.gcr ];
218     environment.systemPackages = with pkgs; [ cfg.package ];
220     environment.interactiveShellInit = ''
221       # Bind gpg-agent to this TTY if gpg commands are used.
222       export GPG_TTY=$(tty)
223     '';
225     programs.ssh.extraConfig = optionalString cfg.agent.enableSSHSupport ''
226       # The SSH agent protocol doesn't have support for changing TTYs; however we
227       # can simulate this with the `exec` feature of openssh (see ssh_config(5))
228       # that hooks a command to the shell currently running the ssh program.
229       Match host * exec "${pkgs.runtimeShell} -c '${cfg.package}/bin/gpg-connect-agent --quiet updatestartuptty /bye >/dev/null 2>&1'"
230     '';
232     environment.extraInit = mkIf cfg.agent.enableSSHSupport ''
233       if [ -z "$SSH_AUTH_SOCK" ]; then
234         export SSH_AUTH_SOCK=$(${cfg.package}/bin/gpgconf --list-dirs agent-ssh-socket)
235       fi
236     '';
238     assertions = [
239       { assertion = cfg.agent.enableSSHSupport -> !config.programs.ssh.startAgent;
240         message = "You can't use ssh-agent and GnuPG agent with SSH support enabled at the same time!";
241       }
242     ];
243   };
245   # uses attributes of the linked package
246   meta.buildDocsInSandbox = false;