From 96f18a0163b7b880fda1d0e73acb92d6ca03d661 Mon Sep 17 00:00:00 2001
From: Julien Moutinho <julm@autogeree.net>
Date: Mon, 13 Jan 2020 05:17:41 +0000
Subject: [PATCH] nix: improve shell.nix's modules system
---
shell.nix | 84 +++---
shell/configuration.nix | 8 -
shell/configuration/gnupg.nix | 24 --
shell/gnupg/keys.nix | 15 ++
.../development/libraries/nix-plugins.nix | 133 ++++-----
shell/modules/shells/nix-shell.nix | 21 ++
shell/modules/tools/networking/openssh.nix | 26 ++
.../modules/tools/package-management/nix.nix | 37 +++
shell/modules/tools/security/gnupg.nix | 254 +++++++++---------
9 files changed, 311 insertions(+), 291 deletions(-)
delete mode 100644 shell/configuration.nix
delete mode 100644 shell/configuration/gnupg.nix
create mode 100644 shell/gnupg/keys.nix
create mode 100644 shell/modules/shells/nix-shell.nix
create mode 100644 shell/modules/tools/networking/openssh.nix
create mode 100644 shell/modules/tools/package-management/nix.nix
diff --git a/shell.nix b/shell.nix
index 0830b72..8d63df7 100644
--- a/shell.nix
+++ b/shell.nix
@@ -4,51 +4,47 @@ let
config = {}; # Make the config pure, ignoring user's config.
overlays = import ./overlays.nix;
};
- # Using modules enables to separate specific configurations in shell/configuration.nix
- # from reusable code in shell/modules.nix
+ nixos = pkgs.nixos {};
+
+ # Configuration of shell/modules/
+ configuration = {config, ...}: {
+ imports = [
+ ];
+ nix-plugins = {
+ enable = true;
+ };
+ gnupg = {
+ enable = true;
+ gnupgHome = toString ../sec/gnupg;
+ keys = import shell/gnupg/keys.nix;
+ };
+ openssh = {
+ enable = true;
+ sshConf = ''
+ '';
+ };
+ };
+
+ # Using modules enables to separate specific configurations
+ # from reusable code in shell/modules.nix and shell/modules/
# which may find its way in another git repository one day.
modules =
(import shell/modules.nix {
inherit pkgs;
inherit (pkgs) lib;
- modules = [ ( import shell/configuration.nix ) ];
+ modules = [ configuration ];
}).config;
- /*
- sourcephile-nix-build =
- pkgs.stdenv.mkDerivation {
- name = "sourcephile-nix-build";
- preferLocalBuild = true;
- allowSubstitutes = false;
- inherit (pkgs) coreutils;
- builder = pkgs.writeText "builder.sh" modules.init.builder;
- };
- */
- sourcephile-nix-build =
- pkgs.buildEnv {
- name = "sourcephile-nix-build";
- pathsToLink = [ "/bin" ];
- paths = with modules; [
- gnupg.init
- #gnupg.gpg-fingerprint
- #nix-plugins.nix-with-extra-builtins
- ];
- };
- nixos = pkgs.nixos {};
- nixos-generate-config = nixos.nixos-generate-config;
- nixos-install = nixos.nixos-install;
- nixos-enter = nixos.nixos-enter;
in
pkgs.stdenv.mkDerivation {
name = "sourcephile-nix";
src = null;
#preferLocalBuild = true;
#allowSubstitutes = false;
- buildInputs = [
- sourcephile-nix-build
+ buildInputs = modules.nix-shell.buildInputs ++ [
nixpkgs
- nixos-generate-config
- nixos-install
- nixos-enter
+ nixos.nixos-generate-config
+ nixos.nixos-install
+ nixos.nixos-enter
#pkgs.binutils
pkgs.coreutils
pkgs.cryptsetup
@@ -97,8 +93,10 @@ pkgs.stdenv.mkDerivation {
shellHook = ''
echo >&2 "nix: running shellHook"
+ ${modules.nix-shell.shellHook}
+
# nix
- export NIX_PATH="nixpkgs=${nixpkgs}:nixpkgs-sourcephile=$PWD/.lib/nixpkgs-sourcephile"
+ export NIX_PATH="nixpkgs=${nixpkgs}"
NIX_PATH+=":nixpkgs-overlays="$PWD"/overlays"
#NIX_PATH+=""
@@ -108,15 +106,6 @@ pkgs.stdenv.mkDerivation {
PATH_FHS="$PWD"/.lib/nix/fhs-bin
PATH_FHS_VBOX="$PWD"/.lib/fhs-vbox-bin
export PATH="$PATH_NIXOS:$PATH_FHS_VBOX:$PATH_FHS:$PATH:$PATH_NIX"
- ln -sfn ${sourcephile-nix-build}/bin "$PWD"/.bin
-
- # nix.conf
- export NIX_CONF_DIR="$PWD"/.config/nix
- install -D /dev/stdin "$PWD"/.config/nix/nix.conf <<-EOF
- auto-optimise-store = true
- plugin-files = ${pkgs.nix-plugins}/lib/nix/plugins/libnix-extra-builtins.so
- extra-builtins-file = ${modules.nix-plugins.extra-builtins}
- EOF
# NOTE: sudo needs to be own by root with the setuid bit,
# but this won't be the case for the sudo provided by Nix outside NixOS,
@@ -129,20 +118,9 @@ pkgs.stdenv.mkDerivation {
export LANG=fr_FR.UTF-8
export LC_CTYPE=fr_FR.UTF-8
- # gnupg
- export GNUPGHOME="$PWD"/../sec/gnupg
- install -dm700 "$GNUPGHOME"
- export GPG_TTY=$(tty)
- gpgconf --launch gpg-agent
- export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
-
# password-store
export PASSWORD_STORE_DIR="$PWD"/../sec/pass
- # openssl
- export NIX_SSL_CERT_FILE="${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
- export SSL_CERT_FILE="${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
-
# git
gitdir="$PWD"/.git
test ! -f "$gitdir" || while IFS=" :" read -r hdr gitdir; do [ "$hdr" != gitdir ] || break; done <"$gitdir"
diff --git a/shell/configuration.nix b/shell/configuration.nix
deleted file mode 100644
index d8dacfd..0000000
--- a/shell/configuration.nix
+++ /dev/null
@@ -1,8 +0,0 @@
-{config, ...}:
-{
- imports = [
- configuration/gnupg.nix
- ];
- config = {
- };
-}
diff --git a/shell/configuration/gnupg.nix b/shell/configuration/gnupg.nix
deleted file mode 100644
index be5e798..0000000
--- a/shell/configuration/gnupg.nix
+++ /dev/null
@@ -1,24 +0,0 @@
-{config, ...}:
-{
- config = {
- gnupg = {
- enable = true;
- dir.var = toString ../../../sec/gnupg;
- keys = {
- "Julien Moutinho <julm@sourcephile.fr>" = {
- uid = "Julien Moutinho <julm@sourcephile.fr>";
- algo = "rsa4096";
- expire = "3y";
- usage = ["cert" "sign"];
- passPath = "members/julm/gpg/password";
- subKeys = [
- { algo = "rsa4096"; expire = "3y"; usage = ["sign"];}
- { algo = "rsa4096"; expire = "3y"; usage = ["encrypt"];}
- { algo = "rsa4096"; expire = "3y"; usage = ["auth"];}
- ];
- backupRecipients = [""];
- };
- };
- };
- };
-}
diff --git a/shell/gnupg/keys.nix b/shell/gnupg/keys.nix
new file mode 100644
index 0000000..91c22d9
--- /dev/null
+++ b/shell/gnupg/keys.nix
@@ -0,0 +1,15 @@
+{
+ "Julien Moutinho <julm@sourcephile.fr>" = {
+ uid = "Julien Moutinho <julm@sourcephile.fr>";
+ algo = "rsa4096";
+ expire = "3y";
+ usage = ["cert" "sign"];
+ passPath = "members/julm/gpg/password";
+ subKeys = [
+ { algo = "rsa4096"; expire = "3y"; usage = ["sign"];}
+ { algo = "rsa4096"; expire = "3y"; usage = ["encrypt"];}
+ { algo = "rsa4096"; expire = "3y"; usage = ["auth"];}
+ ];
+ backupRecipients = [""];
+ };
+}
diff --git a/shell/modules/development/libraries/nix-plugins.nix b/shell/modules/development/libraries/nix-plugins.nix
index 3a1b182..a1a2798 100644
--- a/shell/modules/development/libraries/nix-plugins.nix
+++ b/shell/modules/development/libraries/nix-plugins.nix
@@ -1,17 +1,61 @@
{ config, lib, pkgs, ... }:
-with lib;
let cfg = config.nix-plugins;
+ inherit (lib) types;
+
+ # Wrapper around nix to load extra-builtins.nix with nix-plugins.
+ nix-with-extra-builtins = pkgs.writeShellScriptBin "nix-with-extra-builtins" ''
+ ${pkgs.nix}/bin/nix \
+ --option plugin-files ${pkgs.nix-plugins}/lib/nix/plugins/libnix-extra-builtins.so \
+ --option extra-builtins-file ${cfg.extra-builtins} \
+ "$@"
+ '';
+
+ # Wrapper around pass to call it with exec in extra-builtins.nix.
+ # Unfortunately it can only load secrets which can be represented as a Nix string,
+ # hence without null-byte and such special characters.
+ nix-pass = pkgs.writeShellScriptBin "nix-pass" ''
+ set -e
+ f=$(mktemp)
+ trap "shred -u $f" EXIT
+ ${pkgs.pass}/bin/pass show "$1" >$f
+ nix-instantiate --eval -E "builtins.readFile $f"
+ '';
+ /*
+ nix-store --add $f
+ */
+ /*
+ set -o pipefail
+ ${pkgs.pass}/bin/pass show "$1" |
+ ${pkgs.gnused}/bin/sed \
+ -e 's:\n:\\n:g;s:\r:\\r:g;s:\t:\\t:g;s:":\\":g;1s:^:":;$s:$:":;'
+ */
+
+ # Wrapper around pass to call it with exec in extra-builtins.nix and put the output in a file.
+ # Needed for boot.initrd.network.ssh.host*Key.
+ nix-pass-to-file = pkgs.writeShellScriptBin "nix-pass-to-file" ''
+ set -e
+ set -o pipefail
+ ${pkgs.pass}/bin/pass show "$1" |
+ install -D -m 400 /dev/stdin "$2"
+ printf '%s\n' "$PWD/$2"
+ '';
+
+ # Wrapper around git to call it with exec in extra-builtins.nix.
+ nix-git = pkgs.writeShellScriptBin "nix-git" ''
+ cd "$1"; shift
+ ${pkgs.git}/bin/git "$@"
+ '';
in
{
options.nix-plugins = {
enable = lib.mkEnableOption "nix-plugins";
- extra-builtins = mkOption {
+ extra-builtins = lib.mkOption {
type = types.lines;
default = ''
- pass = path: exec [ "${config.nix-plugins.nix-pass}/bin/nix-pass" path ];
- pass-to-file = path: file: exec [ "${config.nix-plugins.nix-pass-to-file}/bin/nix-pass-to-file" path file ];
- git = dir: args: exec ([ "${config.nix-plugins.nix-git}/bin/nix-git" (builtins.toPath dir) ] ++ args);
- git-time = dir: path: exec [ "${config.nix-plugins.nix-git}/bin/nix-git" (builtins.toPath dir) "log" "-1" "--format=%ct" "--" path ];
+ pass = path: exec [ "${nix-pass}/bin/nix-pass" path ];
+ pass-to-file = path: file: exec [ "${nix-pass-to-file}/bin/nix-pass-to-file" path file ];
+ git = dir: args: exec ([ "${nix-git}/bin/nix-git" (builtins.toPath dir) ] ++ args);
+ git-time = dir: path: exec [ "${nix-git}/bin/nix-git" (builtins.toPath dir) "log" "-1" "--format=%ct" "--" path ];
'';
description = ''
Content put in extra-builtins.nix for nix-plugins.
@@ -21,75 +65,14 @@ in
{
'' + lines + ''
}
- '');
- };
-
- nix-with-extra-builtins = mkOption {
- type = types.str;
- apply = pkgs.writeShellScriptBin "nix-with-extra-builtins";
- default = ''
- ${pkgs.nix}/bin/nix \
- --option plugin-files ${pkgs.nix-plugins}/lib/nix/plugins/libnix-extra-builtins.so \
- --option extra-builtins-file ${cfg.extra-builtins} \
- "$@"
- '';
- description = ''
- Wrapper around nix to load extra-builtins.nix with nix-plugins.
- '';
- };
-
- nix-pass = mkOption {
- type = types.str;
- apply = pkgs.writeShellScriptBin "nix-pass";
- default = ''
- set -e
- f=$(mktemp)
- trap "shred -u $f" EXIT
- ${pkgs.pass}/bin/pass show "$1" >$f
- nix-instantiate --eval -E "builtins.readFile $f"
- '';
- /*
- nix-store --add $f
- */
- /*
- set -o pipefail
- ${pkgs.pass}/bin/pass show "$1" |
- ${pkgs.gnused}/bin/sed \
- -e 's:\n:\\n:g;s:\r:\\r:g;s:\t:\\t:g;s:":\\":g;1s:^:":;$s:$:":;'
- */
- description = ''
- Wrapper around pass to call it with exec in extra-builtins.nix.
- Unfortunately it can only load secrets which can be represented as a Nix string,
- hence without null-byte and such special characters.
- '';
- };
-
- nix-pass-to-file = mkOption {
- type = types.str;
- apply = pkgs.writeShellScriptBin "nix-pass-to-file";
- default = ''
- set -e
- set -o pipefail
- ${pkgs.pass}/bin/pass show "$1" |
- install -D -m 400 /dev/stdin "$2"
- printf '%s\n' "$PWD/$2"
- '';
- description = ''
- Wrapper around pass to call it with exec in extra-builtins.nix and put the output in a file.
- Needed for boot.initrd.network.ssh.host*Key.
- '';
- };
-
- nix-git = mkOption {
- type = types.str;
- apply = pkgs.writeShellScriptBin "nix-git";
- default = ''
- cd "$1"; shift
- ${pkgs.git}/bin/git "$@"
- '';
- description = ''
- Wrapper around git to call it with exec in extra-builtins.nix.
- '';
+ '');
};
};
+ config = lib.mkIf cfg.enable {
+ nix.enable = true;
+ nix.nixConf = ''
+ plugin-files = ${pkgs.nix-plugins}/lib/nix/plugins/libnix-extra-builtins.so
+ extra-builtins-file = ${cfg.extra-builtins}
+ '';
+ };
}
diff --git a/shell/modules/shells/nix-shell.nix b/shell/modules/shells/nix-shell.nix
new file mode 100644
index 0000000..5ee6860
--- /dev/null
+++ b/shell/modules/shells/nix-shell.nix
@@ -0,0 +1,21 @@
+{ pkgs, lib, config, ... }:
+let inherit (lib) types;
+in
+{
+ options = {
+ nix-shell.buildInputs = lib.mkOption {
+ type = types.listOf types.package;
+ default = [];
+ description = ''
+ To be prepended to the shell.nix's buildInputs.
+ '';
+ };
+ nix-shell.shellHook = lib.mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ To be prepended to the shell.nix's shellHook.
+ '';
+ };
+ };
+}
diff --git a/shell/modules/tools/networking/openssh.nix b/shell/modules/tools/networking/openssh.nix
new file mode 100644
index 0000000..4322edc
--- /dev/null
+++ b/shell/modules/tools/networking/openssh.nix
@@ -0,0 +1,26 @@
+{ pkgs, lib, config, ... }:
+let cfg = config.openssh;
+ inherit (lib) types;
+in
+{
+ options.openssh = {
+ enable = lib.mkEnableOption "OpenSSH shell utilities";
+ sshConf = lib.mkOption {
+ type = types.lines;
+ apply = s: pkgs.writeText "ssh_config" s;
+ default = ''
+ '';
+ description = ''
+ OpenSSH's ssh_config content.
+ '';
+ };
+ };
+ config = lib.mkIf cfg.enable {
+ nix-shell.buildInputs =
+ let ssh = pkgs.writeShellScriptBin "ssh" ''
+ ${pkgs.openssh}/bin/ssh -F ${cfg.sshConf} "$@"
+ '';
+ in
+ [ ssh ];
+ };
+}
diff --git a/shell/modules/tools/package-management/nix.nix b/shell/modules/tools/package-management/nix.nix
new file mode 100644
index 0000000..88c0da6
--- /dev/null
+++ b/shell/modules/tools/package-management/nix.nix
@@ -0,0 +1,37 @@
+{ config, lib, pkgs, ... }:
+let cfg = config.nix;
+ inherit (lib) types;
+ /* Alternative which does not need to re-export envvars when called via sudo.
+ But this is maybe more clear to just (re-)export envvars.
+ nix = pkgs.writeShellScriptBin "nix" ''
+ NIX_CONF_DIR=${cfg.nixConf} \
+ NIX_SSL_CERT_FILE="${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt" \
+ SSL_CERT_FILE="${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt" \
+ ${pkgs.nix}/bin/nix "$@"
+ '';
+ */
+in
+{
+ options.nix = {
+ enable = lib.mkEnableOption "nix";
+ nixConf = lib.mkOption {
+ type = types.lines;
+ apply = s: pkgs.writeText "nix.conf" s;
+ default = ''
+ auto-optimise-store = true
+ '';
+ description = ''
+ Nix's nix.conf content.
+ '';
+ };
+ };
+ config = lib.mkIf cfg.enable {
+ #shell.buildInputs = [ nix ];
+ nix-shell.shellHook = ''
+ # nix
+ export NIX_CONF_DIR=${cfg.nixConf}
+ export NIX_SSL_CERT_FILE="${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
+ export SSL_CERT_FILE="${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
+ '';
+ };
+}
diff --git a/shell/modules/tools/security/gnupg.nix b/shell/modules/tools/security/gnupg.nix
index 083e704..c582ec0 100644
--- a/shell/modules/tools/security/gnupg.nix
+++ b/shell/modules/tools/security/gnupg.nix
@@ -17,16 +17,16 @@ let cfg = config.gnupg;
}@primary:
''
info " generateKey uid=\"${uid}\""
- if ! ${cfg.gpg-with-home}/bin/gpg-with-home --list-secret-keys -- "=${uid}" >/dev/null 2>/dev/null
+ if ! ${gpg-with-home}/bin/gpg-with-home --list-secret-keys -- "=${uid}" >/dev/null 2>/dev/null
then
${pkgs.pass}/bin/pass "${passPath}" |
- ${cfg.gpg-with-home}/bin/gpg-with-home \
+ ${gpg-with-home}/bin/gpg-with-home \
--batch --pinentry-mode loopback --passphrase-fd 0 \
--quick-generate-key "${uid}" "${algo}" "${unwords usage}" "${expire}"
fi
${head1}
- fpr=$(${cfg.gpg-fingerprint}/bin/gpg-fingerprint -- "=${uid}" | head1)
- caps=$(${cfg.gpg-with-home}/bin/gpg-with-home \
+ fpr=$(${gpg-fingerprint}/bin/gpg-fingerprint -- "=${uid}" | head1)
+ caps=$(${gpg-with-home}/bin/gpg-with-home \
--with-colons --fixed-list-mode --with-fingerprint \
--list-secret-keys -- "=${uid}" |
${pkgs.gnugrep}/bin/grep '^ssb:' |
@@ -47,7 +47,7 @@ let cfg = config.gnupg;
if ! printf '%s\n' "$caps" | ${pkgs.gnugrep}/bin/grep -Fqx "${lettersKeyUsage usage}"
then
${pkgs.pass}/bin/pass "${primary.passPath}" |
- ${cfg.gpg-with-home}/bin/gpg-with-home \
+ ${gpg-with-home}/bin/gpg-with-home \
--batch --pinentry-mode loopback --passphrase-fd 0 \
--quick-add-key "$fpr" "${algo}" "${unwords usage}" "${expire}"
fi
@@ -62,72 +62,72 @@ let cfg = config.gnupg;
lib.optionalString (backupRecipients != [])
''
info " generateBackupKey backupRecipients=[${unwords (map (s: "\\\"${s}\\\"") backupRecipients)}]"
- mkdir -p "${cfg.dir.var}/backup/${uid}/"
- if ! test -s "${cfg.dir.var}/backup/${uid}/${fpr}.pubkey.asc"
+ mkdir -p "${cfg.gnupgHome}/backup/${uid}/"
+ if ! test -s "${cfg.gnupgHome}/backup/${uid}/${fpr}.pubkey.asc"
then
- ${cfg.gpg-with-home}/bin/gpg-with-home \
+ ${gpg-with-home}/bin/gpg-with-home \
--batch \
- --armor --yes --output "${cfg.dir.var}/backup/${uid}/${fpr}.pubkey.asc" \
+ --armor --yes --output "${cfg.gnupgHome}/backup/${uid}/${fpr}.pubkey.asc" \
--export-options export-backup \
--export "${fpr}"
fi
'' + (if backupRecipients == [""] then
''
- if ! test -s "${cfg.dir.var}/backup/${uid}/${fpr}.revoke.asc"
+ if ! test -s "${cfg.gnupgHome}/backup/${uid}/${fpr}.revoke.asc"
then
${pkgs.pass}/bin/pass "${passPath}" |
- ${cfg.gpg-with-home}/bin/gpg-with-home \
+ ${gpg-with-home}/bin/gpg-with-home \
--pinentry-mode loopback --passphrase-fd 0 \
- --armor --yes --output "${cfg.dir.var}/backup/${uid}/${fpr}.revoke.asc" \
+ --armor --yes --output "${cfg.gnupgHome}/backup/${uid}/${fpr}.revoke.asc" \
--gen-revoke "${fpr}"
fi
- if ! test -s "${cfg.dir.var}/backup/${uid}/${fpr}.privkey.sec"
+ if ! test -s "${cfg.gnupgHome}/backup/${uid}/${fpr}.privkey.sec"
then
${pkgs.pass}/bin/pass "${passPath}" |
- ${cfg.gpg-with-home}/bin/gpg-with-home \
+ ${gpg-with-home}/bin/gpg-with-home \
--batch --pinentry-mode loopback --passphrase-fd 0 \
- --armor --yes --output "${cfg.dir.var}/backup/${uid}/${fpr}.privkey.sec" \
+ --armor --yes --output "${cfg.gnupgHome}/backup/${uid}/${fpr}.privkey.sec" \
--export-options export-backup \
--export-secret-key "${fpr}"
fi
- if ! test -s "${cfg.dir.var}/backup/${uid}/${fpr}.subkeys.sec"
+ if ! test -s "${cfg.gnupgHome}/backup/${uid}/${fpr}.subkeys.sec"
then
${pkgs.pass}/bin/pass "${passPath}" |
- ${cfg.gpg-with-home}/bin/gpg-with-home \
+ ${gpg-with-home}/bin/gpg-with-home \
--batch --pinentry-mode loopback --passphrase-fd 0 \
- --armor --yes --output "${cfg.dir.var}/backup/${uid}/${fpr}.subkeys.sec" \
+ --armor --yes --output "${cfg.gnupgHome}/backup/${uid}/${fpr}.subkeys.sec" \
--export-options export-backup \
--export-secret-subkeys "${fpr}"
fi
'' else ''
- if ! test -s "${cfg.dir.var}/backup/${uid}/${fpr}.revoke.asc.gpg"
+ if ! test -s "${cfg.gnupgHome}/backup/${uid}/${fpr}.revoke.asc.gpg"
then
${pkgs.pass}/bin/pass "${passPath}" |
- ${cfg.gpg-with-home}/bin/gpg-with-home \
+ ${gpg-with-home}/bin/gpg-with-home \
--pinentry-mode loopback --passphrase-fd 0 \
--armor --gen-revoke "${fpr}" |
gpg --encrypt ${recipients backupRecipients} \
- --armor --yes --output "${cfg.dir.var}/backup/${uid}/${fpr}.revoke.asc.gpg"
+ --armor --yes --output "${cfg.gnupgHome}/backup/${uid}/${fpr}.revoke.asc.gpg"
fi
- if ! test -s "${cfg.dir.var}/backup/${uid}/${fpr}.privkey.sec.gpg"
+ if ! test -s "${cfg.gnupgHome}/backup/${uid}/${fpr}.privkey.sec.gpg"
then
${pkgs.pass}/bin/pass "${passPath}" |
- ${cfg.gpg-with-home}/bin/gpg-with-home \
+ ${gpg-with-home}/bin/gpg-with-home \
--batch --pinentry-mode loopback --passphrase-fd 0 \
--armor --export-options export-backup \
--export-secret-key "${fpr}" |
gpg --encrypt ${recipients backupRecipients} \
- --armor --yes --output "${cfg.dir.var}/backup/${uid}/${fpr}.privkey.sec.gpg"
+ --armor --yes --output "${cfg.gnupgHome}/backup/${uid}/${fpr}.privkey.sec.gpg"
fi
- if ! test -s "${cfg.dir.var}/backup/${uid}/${fpr}.subkeys.sec.gpg"
+ if ! test -s "${cfg.gnupgHome}/backup/${uid}/${fpr}.subkeys.sec.gpg"
then
${pkgs.pass}/bin/pass "${passPath}" |
- ${cfg.gpg-with-home}/bin/gpg-with-home \
+ ${gpg-with-home}/bin/gpg-with-home \
--batch --pinentry-mode loopback --passphrase-fd 0 \
--armor --export-options export-backup \
--export-secret-subkeys "${fpr}" |
gpg --encrypt ${recipients backupRecipients} \
- --armor --yes --output "${cfg.dir.var}/backup/${uid}/${fpr}.subkeys.sec.gpg"
+ --armor --yes --output "${cfg.gnupgHome}/backup/${uid}/${fpr}.subkeys.sec.gpg"
fi
'');
recipients = rs: unwords (map (r: ''--recipient "${refKey r}"'') rs);
@@ -147,7 +147,7 @@ let cfg = config.gnupg;
# to its password file.
''
# shell.gnupg.pass.passOfFingerprint
- for fpr in $(${cfg.gpg-fingerprint}/bin/gpg-fingerprint -- "=${key.uid}")
+ for fpr in $(${gpg-fingerprint}/bin/gpg-fingerprint -- "=${key.uid}")
do eval "pass_$fpr=\"${key.passPath}\""
done
'';
@@ -163,7 +163,7 @@ let cfg = config.gnupg;
for keygrip in $keygrips
do
echo >&2 "gpg: forget: keygrip=$keygrip"
- GNUPGHOME=${cfg.dir.var} \
+ GNUPGHOME=${cfg.gnupgHome} \
${pkgs.gnupg}/bin/gpg-connect-agent </dev/null >&2 "CLEAR_PASSPHRASE $keygrip" ||
true
done
@@ -178,10 +178,10 @@ let cfg = config.gnupg;
''
${unlines (map passOfFingerprint keys)}
# presetPass
- GNUPGHOME=${cfg.dir.var} \
+ GNUPGHOME=${cfg.gnupgHome} \
${pkgs.gnupg}/bin/gpgconf --launch gpg-agent
${head1}
- fpr="$(${cfg.gpg-fingerprint}/bin/fingerprint -- "${uid}" | head1)"
+ fpr="$(${gpg-fingerprint}/bin/fingerprint -- "${uid}" | head1)"
eval pass="\''${pass_$fpr}"
if test -n "$pass"
then
@@ -190,7 +190,7 @@ let cfg = config.gnupg;
keygrips="$keygrips $keygrip"
echo >&2 "gpg: preset: keygrip=$keygrip pass=$pass"
${pkgs.pass}/bin/pass "$pass" |
- GNUPGHOME=${cfg.dir.var} \
+ GNUPGHOME=${cfg.gnupgHome} \
${pkgs.gnupg}/libexec/gpg-preset-passphrase --preset ''${XTRACE:+--verbose} $keygrip
done
fi
@@ -208,108 +208,83 @@ let cfg = config.gnupg;
echo >&2 "INFO: $*"
}
'';
+
+ # A wrapper around gpg to set GNUPGHOME.
+ gpg-with-home = pkgs.writeScriptBin "gpg-with-home" ''
+ GNUPGHOME=${cfg.gnupgHome} \
+ exec ${pkgs.gnupg}/bin/gpg "$@"
+ '';
+
+ # A wrapper around gpg to get fingerprints.
+ gpg-fingerprint = pkgs.writeScriptBin "gpg-fingerprint" ''
+ set -eu
+ ${gpg-with-home}/bin/gpg-with-home \
+ --with-colons --fixed-list-mode --with-fingerprint --with-subkey-fingerprint \
+ --list-public-keys "$@" |
+ while IFS=: read -r t x x x key x x x x uid x
+ do case $t in
+ (pub|sub|sec|ssb)
+ while IFS=: read -r t x x x x x x x x fpr x
+ do case $t in (fpr) printf '%s\n' "$fpr"; break;;
+ esac done
+ ;;
+ esac done
+ '';
+
+ # A wrapper around gpg to get keygrips.
+ gpg-keygrip = pkgs.writeScriptBin "gpg-keygrip" ''
+ set -eu
+ ${gpg-with-home}/bin/gpg-with-home \
+ --with-colons --fixed-list-mode --with-keygrip \
+ --list-public-keys "$@" |
+ while IFS=: read -r t x x x key x x x x uid x
+ do case $t in
+ (pub|sub|sec|ssb)
+ while IFS=: read -r t x x x x x x x x grp x
+ do case $t in (grp) printf '%s\n' "$grp"; break;;
+ esac done
+ ;;
+ esac done
+ '';
+
+ # A wrapper around gpg to get uids.
+ gpg-uid = pkgs.writeScriptBin "gpg-uid" ''
+ set -eu
+ ${gpg-with-home}/bin/gpg-with-home \
+ --with-colons --fixed-list-mode \
+ --list-public-keys "$@" |
+ while IFS=: read -r t st x x x x x id x uid x
+ do case $t in
+ (uid)
+ case $st in
+ (u) printf '%s\n' "$uid";;
+ esac
+ ;;
+ esac done
+ '';
+
+ # Initialize the keyring according to cfg.keys.
+ gpg-init = pkgs.writeShellScriptBin "gpg-init" (''
+ set -eu
+ set -o pipefail
+ ${info}
+ info "Init GnuPG"
+ ${pkgs.coreutils}/bin/install -dm0700 -D ${cfg.gnupgHome}
+ ${pkgs.coreutils}/bin/ln -snf ${cfg.gpgConf} ${cfg.gnupgHome}/gpg.conf
+ ${pkgs.coreutils}/bin/ln -snf ${cfg.gpgAgentConf} ${cfg.gnupgHome}/gpg-agent.conf
+ ${pkgs.coreutils}/bin/ln -snf ${cfg.dirmngrConf} ${cfg.gnupgHome}/dirmngr.conf
+ '' +
+ generateKeys cfg.keys);
in
{
options.gnupg = {
- enable = lib.mkEnableOption "GnuPG admin utilities";
- dir.var = lib.mkOption {
+ enable = lib.mkEnableOption "GnuPG shell utilities";
+ gnupgHome = lib.mkOption {
type = types.path;
default = "sec/gnupg";
description = ''
'';
};
- gpg-with-home = lib.mkOption {
- type = types.str;
- apply = pkgs.writeScriptBin "gpg-with-home";
- default = ''
- GNUPGHOME=${cfg.dir.var} \
- exec ${pkgs.gnupg}/bin/gpg "$@"
- '';
- description = ''
- A wrapper around gpg to set GNUPGHOME.
- '';
- };
- gpg-fingerprint = lib.mkOption {
- type = types.str;
- apply = pkgs.writeScriptBin "gpg-fingerprint";
- default = ''
- set -eu
- ${cfg.gpg-with-home}/bin/gpg-with-home \
- --with-colons --fixed-list-mode --with-fingerprint --with-subkey-fingerprint \
- --list-public-keys "$@" |
- while IFS=: read -r t x x x key x x x x uid x
- do case $t in
- (pub|sub|sec|ssb)
- while IFS=: read -r t x x x x x x x x fpr x
- do case $t in (fpr) printf '%s\n' "$fpr"; break;;
- esac done
- ;;
- esac done
- '';
- description = ''
- A wrapper around gpg to get fingerprints.
- '';
- };
- gpg-keygrip = lib.mkOption {
- type = types.str;
- apply = pkgs.writeScriptBin "gpg-keygrip";
- default = ''
- set -eu
- ${cfg.gpg-with-home}/bin/gpg-with-home \
- --with-colons --fixed-list-mode --with-keygrip \
- --list-public-keys "$@" |
- while IFS=: read -r t x x x key x x x x uid x
- do case $t in
- (pub|sub|sec|ssb)
- while IFS=: read -r t x x x x x x x x grp x
- do case $t in (grp) printf '%s\n' "$grp"; break;;
- esac done
- ;;
- esac done
- '';
- description = ''
- A wrapper around gpg to get keygrips.
- '';
- };
- gpg-uid = lib.mkOption {
- type = types.str;
- apply = pkgs.writeScriptBin "gpg-uid";
- default = ''
- set -eu
- ${cfg.gpg-with-home}/bin/gpg-with-home \
- --with-colons --fixed-list-mode \
- --list-public-keys "$@" |
- while IFS=: read -r t st x x x x x id x uid x
- do case $t in
- (uid)
- case $st in
- (u) printf '%s\n' "$uid";;
- esac
- ;;
- esac done
- '';
- description = ''
- A wrapper around gpg to get uids.
- '';
- };
- init = lib.mkOption {
- type = types.str;
- apply = pkgs.writeShellScriptBin "init-gpg";
- default = ''
- set -eu
- set -o pipefail
- ${info}
- info "Init GnuPG"
- ${pkgs.coreutils}/bin/install -dm0700 -D ${cfg.dir.var}
- ${pkgs.coreutils}/bin/ln -snf ${cfg.gpgConf} ${cfg.dir.var}/gpg.conf
- ${pkgs.coreutils}/bin/ln -snf ${cfg.gpgAgentConf} ${cfg.dir.var}/gpg-agent.conf
- ${pkgs.coreutils}/bin/ln -snf ${cfg.dirmngrConf} ${cfg.dir.var}/dirmngr.conf
- '' +
- generateKeys cfg.keys;
- description = ''
- Setup gpg.
- '';
- };
keys = lib.mkOption {
default = {};
example =
@@ -410,14 +385,14 @@ in
}));
};
dirmngrConf = lib.mkOption {
- type = types.str;
+ type = types.lines;
apply = s: pkgs.writeText "dirmngr.conf" s;
default = ''
allow-ocsp
hkp-cacert ${cfg.keyserverPEM}
keyserver hkps://keys.mayfirst.org
use-tor
- #log-file ${cfg.dir.var}/dirmngr.log
+ #log-file ${cfg.gnupgHome}/dirmngr.log
#standard-resolver
'';
description = ''
@@ -425,7 +400,7 @@ in
'';
};
keyserverPEM = lib.mkOption {
- type = types.str;
+ type = types.lines;
apply = s: pkgs.writeText "keyserver.pem" s;
default = builtins.readFile gnupg/keyserver.pem;
description = ''
@@ -433,7 +408,7 @@ in
'';
};
gpgAgentConf = lib.mkOption {
- type = types.str;
+ type = types.lines;
apply = s: pkgs.writeText "gpg-agent.conf" s;
default = ''
allow-preset-passphrase
@@ -448,7 +423,7 @@ in
'';
};
gpgConf = lib.mkOption {
- type = types.str;
+ type = types.lines;
apply = s: pkgs.writeText "gpg.conf" s;
default = ''
auto-key-locate keyserver
@@ -478,4 +453,21 @@ in
'';
};
};
+ config = lib.mkIf cfg.enable {
+ nix-shell.buildInputs = [
+ gpg-with-home
+ gpg-fingerprint
+ gpg-keygrip
+ gpg-uid
+ gpg-init
+ ];
+ nix-shell.shellHook = ''
+ # gnupg
+ export GNUPGHOME=${cfg.gnupgHome}
+ install -dm700 "$GNUPGHOME"
+ export GPG_TTY=$(${pkgs.coreutils}/bin/tty)
+ ${pkgs.gnupg}/bin/gpgconf --launch gpg-agent
+ export SSH_AUTH_SOCK=$(${pkgs.gnupg}/bin/gpgconf --list-dirs agent-ssh-socket)
+ '';
+ };
}
--
2.49.0