Overhaul secrets management

pull/30/head
Simon Bruder 2021-01-06 13:09:29 +01:00
parent 826e196891
commit 7b2da0349c
Signed by: simon
GPG Key ID: 8D3C82F9F309F8EC
6 changed files with 126 additions and 89 deletions

View File

@ -20,12 +20,12 @@
./locales.nix ./locales.nix
./media-proxy.nix ./media-proxy.nix
./network-manager.nix ./network-manager.nix
./nginx.nix
./office.nix ./office.nix
./prometheus/node_exporter.nix ./prometheus/node_exporter.nix
./pubkeys.nix ./pubkeys.nix
./pulseaudio.nix ./pulseaudio.nix
./restic.nix ./restic.nix
./secrets.nix
./ssd.nix ./ssd.nix
./ssh.nix ./ssh.nix
./tools.nix ./tools.nix

View File

@ -2,41 +2,48 @@
let let
port = 8888; port = 8888;
services = { services = {
"media" = <secrets/media-proxy-auth>; "media" = config.krops.secrets.media-proxy-auth.path;
"scan" = <secrets/media-proxy-auth>; "scan" = config.krops.secrets.media-proxy-auth.path;
"torrent" = <secrets/torrent-proxy-auth>; "torrent" = config.krops.secrets.torrent-proxy-auth.path;
}; };
in in
{ {
options.sbruder.media-proxy.enable = lib.mkEnableOption "media proxy"; options.sbruder.media-proxy.enable = lib.mkEnableOption "media proxy";
config.services.nginx = lib.mkIf config.sbruder.media-proxy.enable { config = lib.mkIf config.sbruder.media-proxy.enable {
enable = true; krops.secrets = {
secrets = builtins.attrValues services; torrent-proxy-auth.group = "nginx";
virtualHosts.media-proxy = { media-proxy-auth.group = "nginx";
serverName = "localhost"; };
listen = [ users.users.nginx.extraGroups = [ "keys" ];
{ inherit port; addr = "127.0.0.1"; }
{ inherit port; addr = "[::1]"; } services.nginx = {
]; enable = true;
locations = { virtualHosts.media-proxy = {
"/".extraConfig = '' serverName = "localhost";
rewrite ^/__assets/(.*)$ /media/__assets/$1; listen = [
''; { inherit port; addr = "127.0.0.1"; }
} // lib.mapAttrs' { inherit port; addr = "[::1]"; }
(name: secret: { ];
name = "/${name}/"; locations = {
value = { "/".extraConfig = ''
proxyPass = "https://${name}.sbruder.de/"; rewrite ^/__assets/(.*)$ /media/__assets/$1;
proxyWebsockets = true; '';
extraConfig = '' } // lib.mapAttrs'
proxy_buffering off; (name: secret: {
include /run/nginx/secrets/${lib.last (lib.splitString "/" (toString secret))}; name = "/${name}/";
charset utf-8; value = {
''; proxyPass = "https://${name}.sbruder.de/";
}; proxyWebsockets = true;
}) extraConfig = ''
services; proxy_buffering off;
include ${secret};
charset utf-8;
'';
};
})
services;
};
}; };
}; };
} }

View File

@ -1,40 +0,0 @@
{ config, lib, ... }:
let
cfg = config.services.nginx;
in
{
options.services.nginx.secrets = lib.mkOption {
type = with lib.types; listOf (either str path);
default = [ ];
description = "Secrets to be copied to `/run/nginx/secrets/`";
};
config.systemd = lib.mkIf (lib.length cfg.secrets != 0) {
services = {
nginx-secrets = {
description = "Secrets for nginx";
wantedBy = [ "nginx.service" ];
partOf = [ "nginx.service" ];
serviceConfig.Type = "oneshot";
script = ''
rm -rf /run/nginx/secrets
install -o ${cfg.user} -g ${cfg.group} -m 700 -d /run/nginx/secrets
'' + lib.concatStrings (map
(secret: ''
install -o ${cfg.user} -g ${cfg.group} -m 600 ${toString secret} /run/nginx/secrets
'')
cfg.secrets);
};
nginx.after = [ "nginx-secrets.service" ];
};
paths.nginx-secrets = {
wantedBy = [ "nginx-secrets.service" ];
partOf = [ "nginx-secrets.service" ];
pathConfig = {
PathModified = "/var/src/secrets";
Unit = "nginx-secrets.service";
};
};
};
}

View File

@ -68,10 +68,15 @@ in
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
krops.secrets = {
restic-password = { };
restic-s3 = { };
};
services.restic.backups."${name}" = { services.restic.backups."${name}" = {
inherit repository; inherit repository;
passwordFile = toString <secrets/restic-password>; passwordFile = config.krops.secrets.restic-password.path;
s3CredentialsFile = toString <secrets/restic-s3>; s3CredentialsFile = config.krops.secrets.restic-s3.path;
paths = [ paths = [
"/home" "/home"
"/srv" "/srv"

66
modules/secrets.nix Normal file
View File

@ -0,0 +1,66 @@
# Adapted from https://github.com/Mic92/dotfiles/blob/23f163cae52545d44a7e379dc204010b013d679a/nixos/vms/modules/secrets.nix
#
# All of the users wanting to access any key under /run/keys have to be a
# member of the keys group (or be root). This is a hard coded limitation of
# NixOS and I havent found a way to allow everyone to access /run/keys/ (not a
# security problem since the keys themselves are given the right permissions).
{ config, lib, pkgs, ... }:
let
secret = lib.types.submodule ({ config, ... }: {
options = {
name = lib.mkOption {
type = lib.types.str;
default = config._module.args.name;
};
path = lib.mkOption {
type = lib.types.str;
default = "/run/keys/${config.name}";
};
mode = lib.mkOption {
type = lib.types.str;
default = "0440";
};
owner = lib.mkOption {
type = lib.types.str;
default = "root";
};
group = lib.mkOption {
type = lib.types.str;
default = "root";
};
source = lib.mkOption {
type = lib.types.str;
default = toString <secrets> + "/${config.name}";
};
};
});
in
{
options.krops.secrets = lib.mkOption {
type = lib.types.attrsOf secret;
default = { };
};
config = lib.mkIf (config.krops.secrets != { }) {
system.activationScripts.setup-secrets =
let
script = ''
echo "setting up secrets"
'' + lib.concatMapStringsSep
"\n"
(secret: ''
${pkgs.coreutils}/bin/install \
-D \
--compare \
--verbose \
--mode=${lib.escapeShellArg secret.mode} \
--owner=${lib.escapeShellArg secret.owner} \
--group=${lib.escapeShellArg secret.group} \
${lib.escapeShellArg secret.source} \
${lib.escapeShellArg secret.path} \
|| echo "failed to copy ${secret.source} to ${secret.path}"
'')
(lib.attrValues config.krops.secrets);
in
lib.stringAfter [ "users" "groups" ] "source ${pkgs.writeText "setup-secrets.sh" script}";
};
}

View File

@ -11,24 +11,23 @@ in
description = "IP(v4) address of the host"; description = "IP(v4) address of the host";
example = "10.80.0.1"; example = "10.80.0.1";
}; };
privateKeyFile = lib.mkOption {
type = lib.types.str;
description = "Private key file";
default = toString <secrets/wg-home-private-key>;
};
}; };
}; };
config.networking.wireguard.interfaces.wg-home = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
privateKeyFile = cfg.privateKeyFile; krops.secrets.wg-home-private-key = { };
ips = [ "${cfg.address}/24" ];
peers = [ networking.wireguard.interfaces.wg-home = {
{ privateKeyFile = config.krops.secrets.wg-home-private-key.path;
allowedIPs = [ "10.80.0.0/24" ]; ips = [ "${cfg.address}/24" ];
publicKey = "UyZRAVTIc/RMs/J+591wrA8lHU0e8dwDJJwcpRb3xQA="; peers = [
endpoint = "87.140.16.73:51820"; # IPv6 is tunneled so legacy is preferred {
persistentKeepalive = 25; allowedIPs = [ "10.80.0.0/24" ];
} publicKey = "UyZRAVTIc/RMs/J+591wrA8lHU0e8dwDJJwcpRb3xQA=";
]; endpoint = "87.140.16.73:51820"; # IPv6 is tunneled so legacy is preferred
persistentKeepalive = 25;
}
];
};
}; };
} }