--- /dev/null
+{ lib, pkgs, config, myconfig, mylibs, ... }:
+{
+ options.mySecrets = {
+ keys = lib.mkOption {
+ type = lib.types.listOf lib.types.unspecified;
+ default = {};
+ description = "Keys to upload to server";
+ };
+ };
+ config = let
+ oldkeys = lib.attrsets.filterAttrs (n: v: n != "secrets.tar") config.deployment.keys;
+ keys = config.mySecrets.keys;
+ empty = pkgs.runCommand "empty" { preferLocalBuild = true; } "mkdir -p $out && touch $out/done";
+ dumpOldKey = k: v: let
+ dest = if v.destDir == "/run/keys"
+ then k
+ else (builtins.replaceStrings ["/run/keys/"] [""] v.destDir) + "/" + k;
+ in ''
+ mkdir -p secrets/$(dirname ${dest})
+ echo -n ${lib.strings.escapeShellArg v.text} > secrets/${dest}
+ cat >> mods <<EOF
+ ${v.user or "root"} ${v.group or "root"} ${v.permissions or "0600"} secrets/${dest}
+ EOF
+ '';
+ dumpKey = v: ''
+ mkdir -p secrets/$(dirname ${v.dest})
+ echo -n ${lib.strings.escapeShellArg v.text} > secrets/${v.dest}
+ cat >> mods <<EOF
+ ${v.user or "root"} ${v.group or "root"} ${v.permissions or "0600"} secrets/${v.dest}
+ EOF
+ '';
+ secrets = pkgs.runCommand "secrets.tar" {} ''
+ touch mods
+ tar --format=ustar --mtime='1970-01-01' -P --transform="s@${empty}@secrets@" -cf $out ${empty}/done
+ ${builtins.concatStringsSep "\n" (lib.attrsets.mapAttrsToList dumpOldKey oldkeys)}
+ ${builtins.concatStringsSep "\n" (map dumpKey keys)}
+ cat mods | while read u g p k; do
+ tar --format=ustar --mtime='1970-01-01' --owner="$u" --group="$g" --mode="$p" --append -f $out "$k"
+ done
+ '';
+ in {
+ system.activationScripts.secrets = {
+ deps = [ "users" "wrappers" ];
+ text = ''
+ install -m0750 -o root -g keys -d /var/secrets
+ if [ -f /run/keys/secrets.tar ]; then
+ if [ ! -f /var/secrets/currentSecrets ] || ! sha512sum -c --status "/var/secrets/currentSecrets"; then
+ echo "rebuilding secrets"
+ rm -rf /var/secrets
+ install -m0750 -o root -g keys -d /var/secrets
+ ${pkgs.gnutar}/bin/tar --strip-components 1 -C /var/secrets -xf /run/keys/secrets.tar
+ sha512sum /run/keys/secrets.tar > /var/secrets/currentSecrets
+ find /var/secrets -type d -exec chown root:keys {} \; -exec chmod o-rx {} \;
+ fi
+ fi
+ '';
+ };
+ deployment.keys."secrets.tar" = {
+ permissions = "0400";
+ # keyFile below is not evaluated at build time by nixops, so the
+ # `secrets` path doesn’t necessarily exist when uploading the
+ # keys, and nixops is unhappy.
+ user = "root${builtins.substring 10000 1 secrets}";
+ group = "root";
+ keyFile = "${secrets}";
+ };
+ };
+}