Overhaul secrets management
This commit is contained in:
parent
826e196891
commit
7b2da0349c
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -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
66
modules/secrets.nix
Normal 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 haven’t 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}";
|
||||||
|
};
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue