secrets module overhaul, moving back to bitwarden, removed glauca dyndns

This commit is contained in:
kat witch 2021-09-01 05:44:04 +01:00
parent 1391eabee4
commit 57b35ead89
No known key found for this signature in database
GPG key ID: 1B477797DCA5EC72
26 changed files with 190 additions and 192 deletions

View file

@ -22,6 +22,7 @@ These are the NixOS configurations for my systems. I run nothing other than NixO
## To-do
- [ ] Write my own Dynamic DNS updater to replace the removed Glauca one using [knsupdate][].
- [ ] Consider reworking [kittywitch/nixexprs][] and [kittywitch/nixfiles-base][].
- [x] In-housed [kittywitch/nixexprs][] as [exprs][].
- [x] Merged my local changes with [exprs][].
@ -134,7 +135,6 @@ They are available within this repo as [exprs][].
| nixfiles/secrets | Meta + NixOS + home-manager | Helper for tf-nixs secrets. |
| nixfiles/deploy | Meta + NixOS + home-manager | tf-nix deployment integration |
| nixfiles/network | Meta | Enables node to host config assignment & NixOS module. |
| nixfiles/dyndns | NixOS | Dynamic DNS using [glauca.digital][]. |
| nixfiles/monitoring | NixOS | Grafana, Prometheus, Loki, node-exporter, netdata, promtail, … |
| nixfiles/theme | home-manager | Abstractions for themes. SASS templating. |
| hexchen/yggdrasil | NixOS | Yggdrasil ease of use module. |
@ -196,6 +196,7 @@ Please use `nix-shell` or [direnv/direnv][]. The shell is not compatible with [n
[CI]: #ci
[Dependencies]: #dependencies
[Commands]: #commands
[knsupdate]: https://www.knot-dns.cz/docs/2.4/html/man_knsupdate.html
[kittywitch/nixexprs]: https://github.com/kittywitch/nixexprs
[kittywitch/nixfiles-base]: https://github.com/kittywitch/nixfiles-base
[exprs]: overlays/exprs
@ -254,7 +255,6 @@ Please use `nix-shell` or [direnv/direnv][]. The shell is not compatible with [n
[znc]: config/services/znc/default.nix
[arcnmx/tf-nix]: https://github.com/arcnmx/tf-nix
[nix-community/impermanence]: https://github.com/nix-community/impermanence
[glauca.digital]: https://glauca.digital
[arcnmx/ci]: https://github.com/arcnmx/ci
[6]: ci/nodes.nix
[niv-cron]: ci/niv-cron.nix

View file

@ -104,7 +104,6 @@ with lib;
};
network = {
dns.dynamic = true;
addresses = {
private = {
enable = true;

View file

@ -1,10 +1,18 @@
{ config, lib, nixos, ... }:
{ config, nixos, lib, ... }:
with lib;
let
secretType = types.submodule ({ name, ... }: {
options = {
path = mkOption { type = types.str; };
field = mkOption {
type = types.str;
default = "";
};
};
});
repoSecretType = types.submodule ({ name, ... }: {
options = {
source = mkOption {
type = types.path;
@ -14,20 +22,22 @@ let
};
};
});
cfg = config.kw.secrets;
in
{
options.kw = {
secrets = mkOption {
type = types.nullOr (types.listOf types.str);
default = null;
};
repoSecrets = mkOption {
type = types.nullOr (types.attrsOf secretType);
default = null;
secrets = {
variables = mkOption {
type = types.attrsOf secretType;
default = {};
};
repo = mkOption {
type = types.attrsOf repoSecretType;
default = {};
};
};
};
config = mkIf (config.kw.secrets != null) {
deploy.tf.variables = genAttrs config.kw.secrets (n: { externalSecret = true; });
kw.repoSecrets = nixos.kw.repoSecrets;
config = {
kw.secrets.repo = nixos.kw.secrets.repo;
};
}

View file

@ -22,7 +22,6 @@ let
modules = [
tfModule
"${toString sources.tf-nix}/modules"
./secrets.nix
];
};
in

View file

@ -1,31 +0,0 @@
{ config, lib, ... }:
with lib;
{
options = let tf = config; in
{
variables = mkOption {
type = types.attrsOf (types.submodule ({ name, config, ... }: {
options.externalSecret = mkEnableOption "Is ths secret to be templated into a command provided?";
config = mkIf config.externalSecret {
type = "string";
value.shellCommand = "${tf.commandPrefix} ${tf.folderPrefix}${tf.folderDivider}${escapeShellArg name}";
sensitive = true;
};
}));
};
commandPrefix = mkOption {
type = types.nullOr types.str;
default = null;
};
folderPrefix = mkOption {
type = types.str;
default = "";
};
folderDivider = mkOption {
type = types.str;
default = "";
};
};
}

View file

@ -9,7 +9,6 @@
(import sources.anicca).modules.nixos
./deploy.nix
./monitoring.nix
./dyndns.nix
./secrets.nix
(sources.tf-nix + "/modules/nixos/secrets.nix")
(sources.tf-nix + "/modules/nixos/secrets-users.nix")

View file

@ -1,55 +0,0 @@
{ config, pkgs, lib, tf, ... }:
with lib;
{
options = {
network.dns.dynamic = mkEnableOption "Enable Glauca Dynamic DNS Updater";
};
config = mkIf (false) {
kw.secrets = [
"hexdns-key"
"hexdns-secret"
"hexdns-host"
];
secrets.files.kat-glauca-dns = {
text = ''
user="${tf.variables.hexdns-key.ref}"
pass="${tf.variables.hexdns-secret.ref}"
hostname="${tf.variables.hexdns-host.ref}"
'';
};
systemd.services.kat-glauca-dns =
let updater = pkgs.writeShellScriptBin "glauca-dyndns" ''
#!/usr/bin/env bash
set -eu
ip4=$(${pkgs.curl}/bin/curl -s --ipv4 https://dns.glauca.digital/checkip)
ip6=$(${pkgs.curl}/bin/curl -s --ipv6 https://dns.glauca.digital/checkip)
source $passFile
echo "$ip4, $ip6"
${pkgs.curl}/bin/curl -u ''${user}:''${pass} --data-urlencode "hostname=''${hostname}" --data-urlencode "myip=''${ip4}" "https://dns.glauca.digital/nic/update"
echo ""
${pkgs.curl}/bin/curl -u ''${user}:''${pass} --data-urlencode "hostname=''${hostname}" --data-urlencode "myip=''${ip6}" "https://dns.glauca.digital/nic/update"
''; in
{
serviceConfig = {
ExecStart = "${updater}/bin/glauca-dyndns";
};
environment = { passFile = config.secrets.files.kat-glauca-dns.path; };
wantedBy = [ "default.target" ];
};
systemd.timers.kat-glauca-dns = {
timerConfig = {
Unit = "kat-glauca-dns.service";
OnBootSec = "5m";
OnUnitActiveSec = "1h";
};
wantedBy = [ "default.target" ];
};
};
}

View file

@ -91,9 +91,12 @@ in
(mkIf cfg.server.enable {
network.firewall.private.tcp.ports = [ 9090 ];
kw.secrets = [
"grafana-admin-pass"
];
kw.secrets.variables = {
grafana-admin-pass = {
path = "services/grafana";
field = "admin";
};
};
secrets.files.grafana-admin-pass = {
text = "${tf.variables.grafana-admin-pass.ref}";

View file

@ -4,6 +4,15 @@ with lib;
let
secretType = types.submodule ({ name, ... }: {
options = {
path = mkOption { type = types.str; };
field = mkOption {
type = types.str;
default = "";
};
};
});
repoSecretType = types.submodule ({ name, ... }: {
options = {
source = mkOption {
type = types.path;
@ -13,19 +22,36 @@ let
};
};
});
cfg = config.kw.secrets;
in
{
options.kw = {
secrets = mkOption {
type = types.nullOr (types.listOf types.str);
default = null;
};
repoSecrets = mkOption {
type = types.nullOr (types.attrsOf secretType);
default = null;
secrets = {
command = mkOption {
type = types.str;
};
variables = mkOption {
type = types.attrsOf secretType;
default = {};
};
repo = mkOption {
type = types.attrsOf repoSecretType;
default = {};
};
};
};
config = mkIf (config.kw.secrets != null) {
deploy.tf.variables = genAttrs config.kw.secrets (n: { externalSecret = true; });
};
config = lib.mkMerge [
{
kw.secrets.variables = lib.mkMerge (mapAttrsToList (username: user: user.kw.secrets.variables) config.home-manager.users);
}
(mkIf (cfg.variables != {}) {
deploy.tf.variables = mapAttrs' (name: content:
nameValuePair name ({
value.shellCommand = "${cfg.command} ${content.path}" + optionalString (content.field != "") " -f ${content.field}";
type = "string";
sensitive = true;
})
) cfg.variables;
})
];
}

View file

@ -6,4 +6,8 @@
persistentRoot = "/var/lib/kat/secrets";
external = true;
};
kw.secrets.command = let
bitw = pkgs.writeShellScriptBin "bitw" ''${pkgs.rbw-bitw}/bin/bitw -p gpg://${config.kw.secrets.repo.bitw.source} "$@"'';
in "${bitw}/bin/bitw get";
}

View file

@ -1,4 +1,4 @@
{ config, pkgs, tf, ... }:
{ config, pkgs, tf, lib, ... }: with lib;
{
deploy.tf.dns.records.services_fusionpbx = {
@ -7,10 +7,11 @@
cname.target = "${config.network.addresses.private.domain}.";
};
kw.secrets = [
"fusionpbx-username"
"fusionpbx-password"
];
kw.secrets.variables = mapListToAttrs (field:
nameValuePair "fusionpbx-${field}" {
path = "services/fusionpbx";
inherit field;
}) ["username" "password"];
secrets.files.fusionpbx_env = {
text = ''

View file

@ -1,9 +1,12 @@
{ config, lib, pkgs, tf, ... }:
{
kw.secrets = [
"gitea-mail-pass"
];
kw.secrets.variables = {
gitea-mail-pass = {
path = "secrets/mail-kittywitch";
field = "gitea-pass";
};
};
secrets.files.gitea-mail-passfile = {
text = ''

View file

@ -1,28 +1,29 @@
{ config, lib, tf, pkgs, ... }:
{
kw.secrets = [ "knot-dnsupdate" ];
kw.secrets.variables = {
katdns-key = {
path = "secrets/katdns";
field = "notes";
};
};
network.firewall.public = {
tcp.ports = [ 53 ];
udp.ports = [ 53 ];
};
secrets.files.knot-dnsupdate = {
text = "${tf.variables.knot-dnsupdate.ref}";
secrets.files.katdns-keyfile = {
text = "${tf.variables.katdns-key.ref}";
owner = "knot";
group = "knot";
};
/* environment.etc."katdns/zones/kittywit.ch.zone".text = let
dns = pkgs.dns;
in dns.lib.toString "kittywit.ch" (import ./kittywit.ch.nix { inherit dns lib; }); */
services.knot = {
enable = true;
extraConfig = builtins.readFile ./knot.yaml;
keyFiles = [
config.secrets.files.knot-dnsupdate.path
config.secrets.files.katdns-keyfile.path
];
};
}

View file

@ -5,11 +5,17 @@ with lib;
{
imports = [ sources.nixos-mailserver.outPath ];
kw.secrets = [
"mail-domainkey-kitty"
"mail-kat-hash"
"mail-gitea-hash"
];
kw.secrets.variables = (mapListToAttrs (field:
nameValuePair "mail-${field}-hash" {
path = "secrets/mail-kittywitch";
field = "${field}-hash";
}) ["gitea" "kat"]
// {
mail-domainkey-kitty = {
path = "secrets/mail-kittywitch";
field = "notes";
};
});
deploy.tf.dns.records.services_mail_mx = {
tld = config.network.dns.tld;

View file

@ -13,13 +13,14 @@ with lib;
LC_CTYPE = "C";
'';
kw.secrets = [
"matrix-registration"
"mautrix-telegram-api-hash"
"mautrix-telegram-api-id"
"mautrix-telegram-as-token"
"mautrix-telegram-hs-token"
];
kw.secrets.variables = (mapListToAttrs (field:
nameValuePair "mautrix-telegram-${field}" {
path = "secrets/mautrix-telegram";
inherit field;
}) ["api-hash" "api-id" "as-token" "hs-token"]
// { matrix-registration = {
path = "secrets/matrix-registration";
}; });
secrets.files.mautrix-telegram-env = {
text = ''

View file

@ -14,9 +14,12 @@ in
};
};
kw.secrets = [
"murmur-password"
];
kw.secrets.variables = {
murmur-password = {
path = "social/mumble";
field = "password";
};
};
secrets.files.murmur-config = {
text = ''

View file

@ -5,7 +5,7 @@ with lib;
{
secrets.files.dns_creds = {
text = ''
RFC2136_NAMESERVER='${tf.variables.katdns-addr.ref}'
RFC2136_NAMESERVER='${tf.variables.katdns-address.ref}'
RFC2136_TSIG_ALGORITHM='hmac-sha512.'
RFC2136_TSIG_KEY='${tf.variables.katdns-name.ref}'
RFC2136_TSIG_SECRET='${tf.variables.katdns-key.ref}'

View file

@ -3,10 +3,14 @@
with lib;
{
kw.secrets = [
"syncplay-pass"
"syncplay-salt"
];
kw.secrets.variables = let
fieldAdapt = field: if field == "pass" then "password" else field;
in mapListToAttrs (field:
nameValuePair "syncplay-${field}" {
path = "services/media/syncplay";
field = fieldAdapt field;
}) ["pass" "salt"];
users.users.syncplay = { isSystemUser = true; };

View file

@ -1,7 +1,11 @@
{ config, pkgs, lib, tf, ... }:
{
kw.secrets = lib.singleton "vaultwarden-admin-token";
kw.secrets.variables = {
vaultwarden-admin-token = {
path = "secrets/vaultwarden";
};
};
secrets.files.vaultwarden-env = {
text = ''

View file

@ -50,7 +50,25 @@ in
{
network.firewall.public.tcp.ports = singleton 5001;
kw.secrets = [ "znc-softnet-address" "znc-espernet-pass" "znc-liberachat-pass" "znc-savebuff-pass" "znc-espernet-cert" "znc-liberachat-cert" "znc-softnet-cert" ];
kw.secrets.variables = let
fieldAdapt = field: if field == "cert" then "notes" else if field == "pass" then "password" else field;
in listToAttrs (concatMap (network:
map (field:
nameValuePair "znc-${network}-${field}" {
path = "social/irc/${network}";
field = fieldAdapt field;
}) ["cert" "pass"]
) ["liberachat" "espernet"]
++ map (field:
nameValuePair "znc-softnet-${field}" {
path = "social/irc/softnet";
field = fieldAdapt field;
}) ["cert" "address"]
++ singleton (nameValuePair "znc-savebuff-pass" {
path = "social/irc/znc";
field = "savebuff";
})
);
secrets.files.softnet-cert = {
text = tf.variables.znc-softnet-cert.ref;
@ -141,7 +159,7 @@ in
AltNick = "katrin";
AutoClearChanBuffer = false;
AutoClearQueryBuffer = false;
LoadModule = [ "clientbuffer autoadd" "clientaway" "savebuff ${tf.variables.znc-savebuff-pass.ref}" ];
LoadModule = [ "clientbuffer autoadd" "buffextras" "clientaway" "savebuff ${tf.variables.znc-savebuff-pass.ref}" ];
Network.softnet = {
Server = "${tf.variables.znc-softnet-address.ref}";
Nick = "kat";
@ -166,7 +184,7 @@ in
};
};
})
(mkIf config.deploy.profile.trusted (import config.kw.repoSecrets.znc.source))
(mkIf config.deploy.profile.trusted (import config.kw.secrets.repo.znc.source))
];
configFile = config.secrets.files.znc-config.path;
};

View file

@ -1,31 +1,26 @@
{ config, ... }:
{
commandPrefix = "pass";
folderPrefix = "secrets";
folderDivider = "/";
variables.rfc2136-key = {
externalSecret = true;
};
variables.rfc2136-secret = {
externalSecret = true;
};
variables.katdns-addr = {
externalSecret = true;
variables.katdns-address = {
value.shellCommand = "bitw get secrets/katdns -f address";
type = "string";
sensitive = true;
};
variables.katdns-name = {
externalSecret = true;
value.shellCommand = "bitw get secrets/katdns -f username";
type = "string";
sensitive = true;
};
variables.katdns-key = {
externalSecret = true;
value.shellCommand = "bitw get secrets/katdns -f password";
type = "string";
sensitive = true;
};
providers.katdns = {
type = "dns";
inputs.update = {
server = config.variables.katdns-addr.ref;
server = config.variables.katdns-address.ref;
key_name = config.variables.katdns-name.ref;
key_secret = config.variables.katdns-key.ref;
key_algorithm = "hmac-sha512";
@ -33,13 +28,4 @@
};
dns.zones."kittywit.ch." = { provider = "dns.katdns"; };
providers.dns = {
inputs.update = {
server = "ns1.as207960.net";
key_name = config.variables.rfc2136-key.ref;
key_secret = config.variables.rfc2136-secret.ref;
key_algorithm = "hmac-sha512";
};
};
}

View file

@ -3,9 +3,12 @@
with lib;
{
kw.secrets = [
"syncplay-pass"
];
kw.secrets.variables = {
syncplay-pass = {
path = "services/media/syncplay";
field = "password";
};
};
programs.syncplay = {
enable = true;

View file

@ -1,7 +1,7 @@
{ config, pkgs, lib, ... }: with lib; {
programs.rbw = {
enable = true;
package = mkIf config.deploy.profile.trusted (pkgs.writeShellScriptBin "bitw" ''${pkgs.rbw-bitw}/bin/bitw -p gpg://${config.kw.repoSecrets.bitw.source} "$@"'');
package = mkIf config.deploy.profile.trusted (pkgs.writeShellScriptBin "bitw" ''${pkgs.rbw-bitw}/bin/bitw -p gpg://${config.kw.secrets.repo.bitw.source} "$@"'');
settings = {
email = "kat@kittywit.ch";
base_url = "https://vault.kittywit.ch";

View file

@ -1,7 +1,15 @@
{ config, pkgs, tf, lib, ... }:
with lib;
{
kw.secrets = [ "taskwarrior-key" "taskwarrior-creds" ];
kw.secrets.variables = let
fieldAdapt = field: if field == "key" then "notes" else field;
in mapListToAttrs (field:
nameValuePair "taskwarrior-${field}" {
path = "services/taskwarrior";
field = fieldAdapt field;
}) ["key" "credentials"];
secrets.files = {
taskw_key = {
@ -11,7 +19,7 @@
};
taskw_config = {
text = ''
taskd.credentials=${tf.variables.taskwarrior-creds.ref}
taskd.credentials=${tf.variables.taskwarrior-credentials.ref}
'';
owner = "kat";
group = "users";

View file

@ -3,7 +3,7 @@
{
home.file = lib.mkIf config.deploy.profile.trusted (
let
bitw = pkgs.writeShellScriptBin "bitw" ''${pkgs.rbw-bitw}/bin/bitw -p gpg://${config.kw.repoSecrets.bitw.source} "$@"'';
bitw = pkgs.writeShellScriptBin "bitw" ''${pkgs.rbw-bitw}/bin/bitw -p gpg://${config.kw.secrets.repo.bitw.source} "$@"'';
in
{
".local/share/weechat/sec.conf".text = ''

View file

@ -1,10 +1,16 @@
{ config, lib, nixos, pkgs, tf, ... }:
{
kw.secrets = [
"matrix-pass"
"znc-pass"
];
kw.secrets.variables = {
matrix-pass = {
path = "social/matrix";
field = "password";
};
znc-pass = {
path = "social/irc/znc";
field = "password";
};
};
secrets.files.weechat-sec = {
text = ''