diff --git a/home/apps/rofi/default.nix b/home/apps/rofi/default.nix index c4f28a2..902f593 100644 --- a/home/apps/rofi/default.nix +++ b/home/apps/rofi/default.nix @@ -1,20 +1,5 @@ -{ - pkgs, - nixosConfig, - ... -}: let - gnomeConfig = nixosConfig.services.xserver.desktopManager.gnome; - gdmConfig = nixosConfig.services.xserver.displayManager.gdm; - - isGnome = gnomeConfig.enable; - isGDMWayland = gdmConfig.enable && gdmConfig.wayland; - - isWayland = isGnome && isGDMWayland; - - # rofi currently does not run on gnome - rofiPackage = pkgs.rofi; -in { - home.packages = [rofiPackage]; +{pkgs, ...}: { + home.packages = with pkgs; [rofi]; home.file.".local/share/rofi/themes/rofi-nord.rasi".source = ./rofi-nord.rasi; home.file.".config/rofi/config.rasi".source = ./config.rasi; diff --git a/home/programming/languages/nix.nix b/home/programming/languages/nix.nix index 0bf585a..b6f8712 100644 --- a/home/programming/languages/nix.nix +++ b/home/programming/languages/nix.nix @@ -1,5 +1,5 @@ {pkgs, ...}: { - home.packages = with pkgs; [alejandra]; + home.packages = with pkgs; [alejandra deadnix]; programs.vscode-mod.extensions = with pkgs; [ vscode-extensions.bbenoist.nix diff --git a/hosts/buildbox/buildbox.nix b/hosts/buildbox/buildbox.nix index d94c192..23a77a1 100644 --- a/hosts/buildbox/buildbox.nix +++ b/hosts/buildbox/buildbox.nix @@ -106,11 +106,11 @@ in { home-manager.users.root = { imports = with tree; [home.base home.dev.small]; - home.stateVersion = "22.05"; + home.stateVersion = "23.05"; }; networking.hostName = "buildbox"; time.timeZone = "Europe/London"; - system.stateVersion = "22.05"; + system.stateVersion = "23.05"; } diff --git a/hosts/buildbox/secrets.nix b/hosts/buildbox/secrets.nix index fd6e1c1..5781548 100644 --- a/hosts/buildbox/secrets.nix +++ b/hosts/buildbox/secrets.nix @@ -7,7 +7,7 @@ user = "root"; group = "root"; fetchScript = '' - simple_get "/api-keys/chaos_mail/system" .password > $secretFile + simple_get "/api-keys/chaos_mail/system" .password > "$secretFile" ''; }; }; diff --git a/hosts/hetzner-vm/containers/mail/mail.nix b/hosts/hetzner-vm/containers/mail/mail.nix index be1886b..ed16557 100644 --- a/hosts/hetzner-vm/containers/mail/mail.nix +++ b/hosts/hetzner-vm/containers/mail/mail.nix @@ -3,7 +3,6 @@ lib, inputs, config, - pkgs, ... }: let ports = [ @@ -54,11 +53,7 @@ in { }))) ]; - config = { - config, - pkgs, - ... - }: { + config = {config, ...}: { _module.args = { inherit inputs; inherit tree; diff --git a/hosts/hetzner-vm/containers/mail/profiles/mailserver.nix b/hosts/hetzner-vm/containers/mail/profiles/mailserver.nix index 3fd9bbf..e6268f2 100644 --- a/hosts/hetzner-vm/containers/mail/profiles/mailserver.nix +++ b/hosts/hetzner-vm/containers/mail/profiles/mailserver.nix @@ -69,7 +69,7 @@ in { ]; services.roundcube = { - package = pkgs.roundcube.withPlugins (plugins: + package = pkgs.roundcube.withPlugins (_plugins: with pkgs.roundcubePlugins; [ persistent_login ]); diff --git a/hosts/hetzner-vm/containers/mail/profiles/restic.nix b/hosts/hetzner-vm/containers/mail/profiles/restic.nix index d66cb66..a8d432c 100644 --- a/hosts/hetzner-vm/containers/mail/profiles/restic.nix +++ b/hosts/hetzner-vm/containers/mail/profiles/restic.nix @@ -1,7 +1,6 @@ { pkgs, config, - lib, host_secrets, ... }: let diff --git a/hosts/hetzner-vm/containers/music/music.nix b/hosts/hetzner-vm/containers/music/music.nix index 6019776..78bea41 100644 --- a/hosts/hetzner-vm/containers/music/music.nix +++ b/hosts/hetzner-vm/containers/music/music.nix @@ -83,13 +83,13 @@ in { home-manager.users.root = { imports = with tree; [home.base home.dev.small]; home.packages = with pkgs; [vault]; - home.stateVersion = "22.05"; + home.stateVersion = "23.05"; }; # Manually configure nameserver. Using resolved inside the container seems to fail # currently environment.etc."resolv.conf".text = "nameserver 8.8.8.8"; - system.stateVersion = "22.05"; + system.stateVersion = "23.05"; }; }; diff --git a/hosts/hetzner-vm/containers/piped/piped.nix b/hosts/hetzner-vm/containers/piped/piped.nix index 8d8b72c..fe3d66e 100644 --- a/hosts/hetzner-vm/containers/piped/piped.nix +++ b/hosts/hetzner-vm/containers/piped/piped.nix @@ -3,7 +3,6 @@ lib, inputs, config, - pkgs, ... }: let container-addresses = import ../../data/container-addresses.nix {}; @@ -37,11 +36,7 @@ in { }; })); - config = { - config, - pkgs, - ... - }: { + config = {config, ...}: { _module.args = { inherit inputs; inherit tree; diff --git a/hosts/hetzner-vm/containers/piped/profiles/restic.nix b/hosts/hetzner-vm/containers/piped/profiles/restic.nix index 9efc31d..4f8e020 100644 --- a/hosts/hetzner-vm/containers/piped/profiles/restic.nix +++ b/hosts/hetzner-vm/containers/piped/profiles/restic.nix @@ -1,7 +1,5 @@ { pkgs, - config, - lib, host_secrets, ... }: let diff --git a/hosts/hetzner-vm/containers/quassel/profiles/restic.nix b/hosts/hetzner-vm/containers/quassel/profiles/restic.nix index 2318f00..8fe7fed 100644 --- a/hosts/hetzner-vm/containers/quassel/profiles/restic.nix +++ b/hosts/hetzner-vm/containers/quassel/profiles/restic.nix @@ -1,7 +1,5 @@ { pkgs, - config, - lib, host_secrets, ... }: let diff --git a/hosts/hetzner-vm/containers/quassel/quassel.nix b/hosts/hetzner-vm/containers/quassel/quassel.nix index 9d42ff0..aa09a9a 100644 --- a/hosts/hetzner-vm/containers/quassel/quassel.nix +++ b/hosts/hetzner-vm/containers/quassel/quassel.nix @@ -36,11 +36,7 @@ in { }; })); - config = { - config, - pkgs, - ... - }: { + config = {config, ...}: { _module.args = { inherit inputs; inherit tree; diff --git a/hosts/hetzner-vm/containers/social/profiles/gotosocial.nix b/hosts/hetzner-vm/containers/social/profiles/gotosocial.nix index 5ffc957..c13ee0b 100644 --- a/hosts/hetzner-vm/containers/social/profiles/gotosocial.nix +++ b/hosts/hetzner-vm/containers/social/profiles/gotosocial.nix @@ -8,7 +8,7 @@ in { services.gotosocial = { enable = true; setupPostgresqlDB = true; - environmentFile = host_secrets.social_env_secrets.path; + environmentFile = secrets.social_env_secrets.path; settings = { application-name = "chaos-gts"; diff --git a/hosts/hetzner-vm/containers/social/social.nix b/hosts/hetzner-vm/containers/social/social.nix index ec35989..a2e97a9 100644 --- a/hosts/hetzner-vm/containers/social/social.nix +++ b/hosts/hetzner-vm/containers/social/social.nix @@ -73,13 +73,13 @@ in { home-manager.users.root = { imports = with tree; [home.base home.dev.small]; home.packages = with pkgs; [vault]; - home.stateVersion = "22.05"; + home.stateVersion = "23.05"; }; # Manually configure nameserver. Using resolved inside the container seems to fail # currently environment.etc."resolv.conf".text = "nameserver 8.8.8.8"; - system.stateVersion = "22.05"; + system.stateVersion = "23.05"; }; }; diff --git a/hosts/hetzner-vm/containers/storage/profiles/secrets.nix b/hosts/hetzner-vm/containers/storage/profiles/secrets.nix index a2bc3d0..1eec6e6 100644 --- a/hosts/hetzner-vm/containers/storage/profiles/secrets.nix +++ b/hosts/hetzner-vm/containers/storage/profiles/secrets.nix @@ -1,14 +1,26 @@ -{pkgs, ...}: { +{ + config, + pkgs, + ... +}: { services.secrets = { enable = true; - extraPackages = with pkgs; [ + packages = with pkgs; [ # for music & mail passwd files apacheHttpd # for rclone obscure config file rclone ]; + uidMap = { + "storage" = config.users.users."storage".uid; + }; + + gidMap = { + "storage" = config.users.groups."storage".gid; + }; + extraFunctions = '' replace_slash_for_sed() { sed "s#/#\\\/#" @@ -108,7 +120,7 @@ fetchScript = '' username=$(simple_get "/api-keys/storage/webdav/main" .username) password=$(simple_get "/api-keys/storage/webdav/main" .password) - htpasswd -bc "$secretFile" "$username" "$password" 2>&1 + htpasswd -bc "$secretFile" "$username" "$password" 2>/dev/null ''; }; webdav_media_htpasswd = { @@ -117,7 +129,7 @@ fetchScript = '' username=$(simple_get "/api-keys/storage/webdav/media" .username) password=$(simple_get "/api-keys/storage/webdav/media" .password) - htpasswd -bc "$secretFile" "$username" "$password" 2>&1 + htpasswd -bc "$secretFile" "$username" "$password" 2>/dev/null ''; }; @@ -129,7 +141,7 @@ cp ${./rclone_config.template} "$TMP_DIR/template" - pushd "$TMP_DIR" 2>/dev/null + pushd "$TMP_DIR" >/dev/null STORAGEBOX_PASSWORD=$(simple_get_obscure /api-keys/hetzner/storagebox .password) sed -i "s/STORAGEBOX_PASSWORD/$STORAGEBOX_PASSWORD/" ./template @@ -148,9 +160,9 @@ simple_get_replace_crypt "/private-public-keys/rclone/Chaos-Media-Crypt" "STORAGE_MEDIA_CRYPT" ./template - cp ./template $secretFile + cp ./template "$secretFile" - popd 2>/dev/null + popd >/dev/null rm -rf "$TMP_DIR" ''; diff --git a/hosts/hetzner-vm/containers/storage/profiles/users.nix b/hosts/hetzner-vm/containers/storage/profiles/users.nix index de425b5..26eb1dc 100644 --- a/hosts/hetzner-vm/containers/storage/profiles/users.nix +++ b/hosts/hetzner-vm/containers/storage/profiles/users.nix @@ -1,6 +1,9 @@ {...}: { - users.groups.storage = {}; + users.groups.storage = { + gid = 1000; + }; users.users.storage = { + uid = 1000; isNormalUser = true; extraGroups = ["storage"]; }; diff --git a/hosts/hetzner-vm/containers/storage/storage.nix b/hosts/hetzner-vm/containers/storage/storage.nix index 15af920..40efbe6 100644 --- a/hosts/hetzner-vm/containers/storage/storage.nix +++ b/hosts/hetzner-vm/containers/storage/storage.nix @@ -59,7 +59,7 @@ in { home-manager.users.root = { imports = with tree; [home.base home.dev.small]; home.packages = with pkgs; [vault]; - home.stateVersion = "22.05"; + home.stateVersion = "23.05"; }; networking.firewall = { @@ -70,7 +70,7 @@ in { # Manually configure nameserver. Using resolved inside the container seems to fail # currently environment.etc."resolv.conf".text = "nameserver 8.8.8.8"; - system.stateVersion = "22.05"; + system.stateVersion = "23.05"; }; }; diff --git a/hosts/hetzner-vm/hetzner-vm.nix b/hosts/hetzner-vm/hetzner-vm.nix index a45dc1f..7857235 100644 --- a/hosts/hetzner-vm/hetzner-vm.nix +++ b/hosts/hetzner-vm/hetzner-vm.nix @@ -72,11 +72,11 @@ home-manager.users.root = { imports = with tree; [home.base home.dev.small]; - home.stateVersion = "22.05"; + home.stateVersion = "23.05"; }; networking.hostName = "hetzner-vm"; time.timeZone = "Europe/London"; - system.stateVersion = "22.05"; + system.stateVersion = "23.05"; } diff --git a/hosts/hetzner-vm/profiles/gitlab-static-sites.nix b/hosts/hetzner-vm/profiles/gitlab-static-sites.nix index 5ed25a2..5f16317 100644 --- a/hosts/hetzner-vm/profiles/gitlab-static-sites.nix +++ b/hosts/hetzner-vm/profiles/gitlab-static-sites.nix @@ -1,6 +1,9 @@ {config, ...}: let secrets = config.services.secrets.secrets; in { + users.users.gitlab_artifacts_sync.uid = 2001; + users.groups.gitlab_artifacts_sync.gid = 2001; + services.gitlab_artifacts_sync = { enable = true; credentialsEnvironmentFile = "${secrets.gitlab_env.path}"; diff --git a/hosts/hetzner-vm/secrets.nix b/hosts/hetzner-vm/secrets.nix index 98a1ab4..c214884 100644 --- a/hosts/hetzner-vm/secrets.nix +++ b/hosts/hetzner-vm/secrets.nix @@ -1,12 +1,37 @@ -{pkgs, ...}: { +{ + pkgs, + lib, + config, + ... +}: let + inherit (lib.lists) forEach; + inherit (lib.modules) mkMerge; + + users = ["root" "dovecot2" "gitlab_artifacts_sync" "mpd" "nginx"]; + groups = users; +in { services.secrets = { enable = true; - extraPackages = with pkgs; [ + packages = with pkgs; [ # for music & mail passwd files apacheHttpd ]; + uidMap = let + getUID = name: config.users.users.${name}.uid; + in + mkMerge (forEach users (user: { + "${user}" = getUID user; + })); + + gidMap = let + getGID = name: config.users.groups.${name}.gid; + in + mkMerge (forEach groups (group: { + "${group}" = getGID group; + })); + secrets = { # Used directly by server # for fetching gitlab static sites @@ -15,31 +40,31 @@ group = "gitlab_artifacts_sync"; fetchScript = '' token=$(simple_get "/api-keys/gitlab/gitlab_pages_serve" .token) - echo "GITLAB_TOKEN=$token" > $secretFile + echo "GITLAB_TOKEN=$token" > "$secretFile" ''; }; # for wireguard wg_privkey = { fetchScript = '' - simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .private > $secretFile + simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .private > "$secretFile" ''; }; wg_preshared_vault = { path = "/secrets/wg_preshared_vault"; fetchScript = '' - simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.vault > $secretFile + simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.vault > "$secretFile" ''; }; wg_preshared_iphone8 = { path = "/secrets/wg_preshared_iphone8"; fetchScript = '' - simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.iphone8 > $secretFile + simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.iphone8 > "$secretFile" ''; }; wg_preshared_lappy-t495 = { path = "/secrets/wg_preshared_lappy-t495"; fetchScript = '' - simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" ".preshared_keys.lappy_t495" > $secretFile + simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" ".preshared_keys.lappy_t495" > "$secretFile" ''; }; @@ -48,7 +73,7 @@ user = "mpd"; group = "mpd"; fetchScript = '' - simple_get "/api-keys/mpd" .password > $secretFile + simple_get "/api-keys/mpd" .password > "$secretFile" ''; }; music_stream_passwd = { @@ -57,37 +82,37 @@ fetchScript = '' username=$(simple_get "/api-keys/music-stream" .username) password=$(simple_get "/api-keys/music-stream" .password) - htpasswd -bc $secretFile "$username" "$password" 2>/dev/null + htpasswd -bc "$secretFile" "$username" "$password" 2>/dev/null ''; }; slskd_env = { fetchScript = '' soulseek_password=$(simple_get "/passwords/soulseek" .password) slskd_password=$(simple_get "/passwords/slskd" .password) - echo > $secretFile - echo "SLSKD_SLSK_PASSWORD=$soulseek_password" >> $secretFile - echo "SLSKD_PASSWORD=$slskd_password" >> $secretFile + echo > "$secretFile" + echo "SLSKD_SLSK_PASSWORD=$soulseek_password" >> "$secretFile" + echo "SLSKD_PASSWORD=$slskd_password" >> "$secretFile" ''; }; # Container: mail mail_restic_password = { fetchScript = '' - simple_get "/private-public-keys/restic/Mail" .password > $secretFile + simple_get "/private-public-keys/restic/Mail" .password > "$secretFile" ''; }; mail_restic_env = { fetchScript = '' RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Mail" .username) RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Mail" .password) - echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Mail" > $secretFile + echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Mail" > "$secretFile" ''; }; private_mail_aliases = { user = "root"; group = "root"; fetchScript = '' - kv_get "/infra/private-mail-aliases" | jq .data.data | jq -r 'to_entries|map("\(.key) \(.value.to)")[]' > $secretFile + kv_get "/infra/private-mail-aliases" | jq .data.data | jq -r 'to_entries|map("\(.key) \(.value.to)")[]' > "$secretFile" ''; }; chaos_mail_passwd = { @@ -95,7 +120,7 @@ group = "dovecot2"; fetchScript = '' password=$(simple_get "/passwords/mail" .password) - htpasswd -nbB "" "$password" 2>/dev/null | cut -d: -f2 > $secretFile + htpasswd -nbB "" "$password" 2>/dev/null | cut -d: -f2 > "$secretFile" ''; }; system_mail_passwd = { @@ -103,7 +128,7 @@ group = "dovecot2"; fetchScript = '' password=$(simple_get "/api-keys/chaos_mail/system" .password) - htpasswd -nbB "" "$password" 2>/dev/null | cut -d: -f2 > $secretFile + htpasswd -nbB "" "$password" 2>/dev/null | cut -d: -f2 > "$secretFile" ''; }; gotosocial_mail_passwd = { @@ -111,21 +136,21 @@ group = "dovecot2"; fetchScript = '' password=$(simple_get "/api-keys/chaos_mail/gotosocial" .password) - htpasswd -nbB "" "$password" 2>/dev/null | cut -d: -f2 > $secretFile + htpasswd -nbB "" "$password" 2>/dev/null | cut -d: -f2 > "$secretFile" ''; }; # Container: social social_restic_password = { fetchScript = '' - simple_get "/private-public-keys/restic/Social" .password > $secretFile + simple_get "/private-public-keys/restic/Social" .password > "$secretFile" ''; }; social_restic_env = { fetchScript = '' RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Social" .username) RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Social" .password) - echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Social" > $secretFile + echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Social" > "$secretFile" ''; }; social_env_secrets = { @@ -133,35 +158,35 @@ group = "root"; fetchScript = '' smtp_password=$(simple_get "/api-keys/chaos_mail/gotosocial" .password) - echo "GTS_SMTP_PASSWORD=$smtp_password" > $secretFile + echo "GTS_SMTP_PASSWORD=$smtp_password" > "$secretFile" ''; }; # Container: quassel quassel_restic_password = { fetchScript = '' - simple_get "/private-public-keys/restic/Quassel" .password > $secretFile + simple_get "/private-public-keys/restic/Quassel" .password > "$secretFile" ''; }; quassel_restic_env = { fetchScript = '' RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Quassel" .username) RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Quassel" .password) - echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Quassel" > $secretFile + echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Quassel" > "$secretFile" ''; }; # Container: piped piped_restic_password = { fetchScript = '' - simple_get "/private-public-keys/restic/Piped" .password > $secretFile + simple_get "/private-public-keys/restic/Piped" .password > "$secretFile" ''; }; piped_restic_env = { fetchScript = '' RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Piped" .username) RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Piped" .password) - echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Piped" > $secretFile + echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Piped" > "$secretFile" ''; }; }; diff --git a/hosts/lappy-t495/secrets.nix b/hosts/lappy-t495/secrets.nix index 05a705e..9059f26 100644 --- a/hosts/lappy-t495/secrets.nix +++ b/hosts/lappy-t495/secrets.nix @@ -5,10 +5,10 @@ usb_encryption_passphrase = {manual = true;}; music_stream_password = { - user = "chaos"; + user = 1000; group = "users"; fetchScript = '' - simple_get "/api-keys/music-stream" .password > $secretFile + simple_get "/api-keys/music-stream" .password > "$secretFile" ''; }; @@ -18,7 +18,7 @@ group = "users"; fetchScript = '' - simple_get "/api-keys/gitlab/gitlab_archiver" .token > $secretFile + simple_get "/api-keys/gitlab/gitlab_archiver" .token > "$secretFile" ''; }; @@ -32,26 +32,26 @@ api_password=$(simple_get "/api-keys/storage/restic/Music" .password) restic_password=$(simple_get "/private-public-keys/restic/Music" .password) - echo > $secretFile - echo "RESTIC_REPOSITORY=rest:https://''${api_username}:''${api_password}@storage-restic.owo.monster/Music" >> $secretFile - echo "RESTIC_PASSWORD=''${restic_password}" >> $secretFile + echo > "$secretFile" + echo "RESTIC_REPOSITORY=rest:https://''${api_username}:''${api_password}@storage-restic.owo.monster/Music" >> "$secretFile" + echo "RESTIC_PASSWORD=''${restic_password}" >> "$secretFile" ''; }; # for internal wireguard VPN wg_priv = { fetchScript = '' - simple_get "/private-public-keys/wireguard/chaos-internal/lappy-t495" .private > $secretFile + simple_get "/private-public-keys/wireguard/chaos-internal/lappy-t495" .private > "$secretFile" ''; }; wg_preshared_hetzner-vm = { fetchScript = '' - simple_get "/private-public-keys/wireguard/chaos-internal/lappy-t495" .preshared_keys.hetzner_vm > $secretFile + simple_get "/private-public-keys/wireguard/chaos-internal/lappy-t495" .preshared_keys.hetzner_vm > "$secretFile" ''; }; wg_preshared_vault = { fetchScript = '' - simple_get "/private-public-keys/wireguard/chaos-internal/lappy-t495" .preshared_keys.vault > $secretFile + simple_get "/private-public-keys/wireguard/chaos-internal/lappy-t495" .preshared_keys.vault > "$secretFile" ''; }; }; diff --git a/hosts/nixos-live/nixos-live.nix b/hosts/nixos-live/nixos-live.nix index 3520965..5eb9647 100644 --- a/hosts/nixos-live/nixos-live.nix +++ b/hosts/nixos-live/nixos-live.nix @@ -1,9 +1,7 @@ { - self, config, tree, modulesPath, - pkgs, lib, ... }: { @@ -21,7 +19,7 @@ # disable zfs nixpkgs.overlays = [ - (final: super: { + (_final: super: { zfs = super.zfs.overrideAttrs (_: { meta.platforms = []; }); diff --git a/hosts/tablet/secrets.nix b/hosts/tablet/secrets.nix index d88433b..23d93a2 100644 --- a/hosts/tablet/secrets.nix +++ b/hosts/tablet/secrets.nix @@ -7,7 +7,7 @@ user = "chaos"; group = "users"; fetchScript = '' - simple_get "/api-keys/music-stream" .password > $secretFile + simple_get "/api-keys/music-stream" .password > "$secretFile" ''; }; # Required for home.apps.manual-backup-apps @@ -16,7 +16,7 @@ group = "users"; fetchScript = '' - simple_get "/api-keys/gitlab/gitlab_archiver" .token > $secretFile + simple_get "/api-keys/gitlab/gitlab_archiver" .token > "$secretFile" ''; }; @@ -30,9 +30,9 @@ api_password=$(simple_get "/api-keys/storage/restic/Music" .password) restic_password=$(simple_get "/private-public-keys/restic/Music" .password) - echo > $secretFile - echo "RESTIC_REPOSITORY=rest:https://''${api_username}:''${api_password}@storage-restic.owo.monster/Music" >> $secretFile - echo "RESTIC_PASSWORD=''${restic_password}" >> $secretFile + echo > "$secretFile" + echo "RESTIC_REPOSITORY=rest:https://''${api_username}:''${api_password}@storage-restic.owo.monster/Music" >> "$secretFile" + echo "RESTIC_PASSWORD=''${restic_password}" >> "$secretFile" ''; }; }; diff --git a/hosts/tablet/tablet.nix b/hosts/tablet/tablet.nix index 6e076eb..5d8ad16 100644 --- a/hosts/tablet/tablet.nix +++ b/hosts/tablet/tablet.nix @@ -14,7 +14,7 @@ home-manager.users.root = { imports = with tree; [home.base]; - home.stateVersion = "22.05"; + home.stateVersion = "23.05"; }; home-manager.users.chaos = { @@ -28,7 +28,7 @@ home.programming.languages.rust home.programming.languages.nix ]; - home.stateVersion = "22.05"; + home.stateVersion = "23.05"; }; networking.firewall.enable = true; @@ -39,5 +39,5 @@ networking.hostName = "tablet"; time.timeZone = "Europe/London"; - system.stateVersion = "22.05"; + system.stateVersion = "23.05"; } diff --git a/hosts/vault/secrets.nix b/hosts/vault/secrets.nix index 6b6cf73..dbb8893 100644 --- a/hosts/vault/secrets.nix +++ b/hosts/vault/secrets.nix @@ -4,34 +4,34 @@ secrets = { restic_password = { fetchScript = '' - simple_get "/private-public-keys/restic/Vault" .password > $secretFile + simple_get "/private-public-keys/restic/Vault" .password > "$secretFile" ''; }; restic_env = { fetchScript = '' RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Vault" .username) RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Vault" .password) - echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Vault" > $secretFile + echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Vault" > "$secretFile" ''; }; wg_priv = { fetchScript = '' - simple_get "/private-public-keys/wireguard/chaos-internal/vault" .private > $secretFile + simple_get "/private-public-keys/wireguard/chaos-internal/vault" .private > "$secretFile" ''; }; wg_preshared_hetzner-vm = { fetchScript = '' - simple_get "/private-public-keys/wireguard/chaos-internal/vault" .preshared_keys.hetzner_vm > $secretFile + simple_get "/private-public-keys/wireguard/chaos-internal/vault" .preshared_keys.hetzner_vm > "$secretFile" ''; }; wg_preshared_iphone8 = { fetchScript = '' - simple_get "/private-public-keys/wireguard/chaos-internal/vault" .preshared_keys.iphone8 > $secretFile + simple_get "/private-public-keys/wireguard/chaos-internal/vault" .preshared_keys.iphone8 > "$secretFile" ''; }; wg_preshared_lappy-t495 = { fetchScript = '' - simple_get "/private-public-keys/wireguard/chaos-internal/vault" ".preshared_keys.lappy_t495" > $secretFile + simple_get "/private-public-keys/wireguard/chaos-internal/vault" ".preshared_keys.lappy_t495" > "$secretFile" ''; }; }; diff --git a/hosts/vault/vault.nix b/hosts/vault/vault.nix index e273236..a17b069 100644 --- a/hosts/vault/vault.nix +++ b/hosts/vault/vault.nix @@ -19,11 +19,11 @@ home-manager.users.root = { imports = with tree; [home.base home.dev.small]; - home.stateVersion = "22.05"; + home.stateVersion = "23.05"; }; networking.hostName = "vault"; time.timeZone = "Europe/London"; - system.stateVersion = "22.05"; + system.stateVersion = "23.05"; } diff --git "a/ic\";" "b/ic\";" deleted file mode 100644 index 82f393f..0000000 --- "a/ic\";" +++ /dev/null @@ -1,392 +0,0 @@ -diff --git a/hosts/hetzner-vm/containers/mail/modules/mailserver/default.nix b/hosts/hetzner-vm/containers/mail/modules/mailserver/default.nix -index 0e9f1da..73979dd 100644 ---- a/hosts/hetzner-vm/containers/mail/modules/mailserver/default.nix -+++ b/hosts/hetzner-vm/containers/mail/modules/mailserver/default.nix -@@ -4,9 +4,9 @@ - ... - }: - with lib; let -- cfg = config.mailserver; -+ cfg = config.services.mailserver; - in { -- options.mailserver = { -+ options.services.mailserver = { - enable = mkEnableOption "mailserver"; -  - fqdn = mkOption {type = types.str;}; -diff --git a/hosts/hetzner-vm/containers/mail/modules/mailserver/dovecot.nix b/hosts/hetzner-vm/containers/mail/modules/mailserver/dovecot.nix -index ef5f01d..d306611 100644 ---- a/hosts/hetzner-vm/containers/mail/modules/mailserver/dovecot.nix -+++ b/hosts/hetzner-vm/containers/mail/modules/mailserver/dovecot.nix -@@ -4,7 +4,7 @@ - lib, - ... - }: let -- mail_config = config.mailserver; -+ mail_config = config.services.mailserver; -  - vmail_config = mail_config.vmail_config; -  -diff --git a/hosts/hetzner-vm/containers/mail/modules/mailserver/firewall.nix b/hosts/hetzner-vm/containers/mail/modules/mailserver/firewall.nix -index 6c69bb3..0602a9a 100644 ---- a/hosts/hetzner-vm/containers/mail/modules/mailserver/firewall.nix -+++ b/hosts/hetzner-vm/containers/mail/modules/mailserver/firewall.nix -@@ -3,7 +3,7 @@ - config, - ... - }: let -- mail_config = config.mailserver; -+ mail_config = config.services.mailserver; - in { - config = lib.mkIf mail_config.enable { - networking.firewall = { -diff --git a/hosts/hetzner-vm/containers/mail/modules/mailserver/opendkim.nix b/hosts/hetzner-vm/containers/mail/modules/mailserver/opendkim.nix -index 3297ee5..32e2481 100644 ---- a/hosts/hetzner-vm/containers/mail/modules/mailserver/opendkim.nix -+++ b/hosts/hetzner-vm/containers/mail/modules/mailserver/opendkim.nix -@@ -5,7 +5,7 @@ - ... - }: - with lib; let -- mail_config = config.mailserver; -+ mail_config = config.services.mailserver; - dkimUser = config.services.opendkim.user; - dkimGroup = config.services.opendkim.group; -  -diff --git a/hosts/hetzner-vm/containers/mail/modules/mailserver/postfix.nix b/hosts/hetzner-vm/containers/mail/modules/mailserver/postfix.nix -index 8599bbf..b795a26 100644 ---- a/hosts/hetzner-vm/containers/mail/modules/mailserver/postfix.nix -+++ b/hosts/hetzner-vm/containers/mail/modules/mailserver/postfix.nix -@@ -4,7 +4,7 @@ - lib, - ... - }: let -- mail_config = config.mailserver; -+ mail_config = config.services.mailserver; - submissionHeaderCleanupRules = pkgs.writeText "submission_header_cleanup_rules" '' - /^Received:/ IGNORE - /^X-Originating-IP:/ IGNORE -diff --git a/hosts/hetzner-vm/containers/mail/modules/mailserver/rspamd.nix b/hosts/hetzner-vm/containers/mail/modules/mailserver/rspamd.nix -index 5df6349..be9ae1e 100644 ---- a/hosts/hetzner-vm/containers/mail/modules/mailserver/rspamd.nix -+++ b/hosts/hetzner-vm/containers/mail/modules/mailserver/rspamd.nix -@@ -3,7 +3,7 @@ - lib, - ... - }: let -- mail_config = config.mailserver; -+ mail_config = config.services.mailserver; -  - postfixCfg = config.services.postfix; - rspamdCfg = config.services.rspamd; -diff --git a/hosts/hetzner-vm/containers/mail/modules/mailserver/ssl.nix b/hosts/hetzner-vm/containers/mail/modules/mailserver/ssl.nix -index f0f26bd..c7d7a61 100644 ---- a/hosts/hetzner-vm/containers/mail/modules/mailserver/ssl.nix -+++ b/hosts/hetzner-vm/containers/mail/modules/mailserver/ssl.nix -@@ -3,7 +3,7 @@ - lib, - ... - }: let -- mail_config = config.mailserver; -+ mail_config = config.services.mailserver; - acmeRoot = "/var/lib/acme/acme-challenge"; - in { - config = lib.mkIf (mail_config.enable && mail_config.ssl_config.useACME) { -diff --git a/hosts/hetzner-vm/containers/mail/modules/mailserver/vmail.nix b/hosts/hetzner-vm/containers/mail/modules/mailserver/vmail.nix -index 90ee44f..44a4e42 100644 ---- a/hosts/hetzner-vm/containers/mail/modules/mailserver/vmail.nix -+++ b/hosts/hetzner-vm/containers/mail/modules/mailserver/vmail.nix -@@ -4,7 +4,7 @@ - lib, - ... - }: let -- mail_config = config.mailserver; -+ mail_config = config.services.mailserver; -  - vmail_config = mail_config.vmail_config; - vmail_user = vmail_config.user; -diff --git a/hosts/hetzner-vm/containers/mail/modules/mailserver/webmail.nix b/hosts/hetzner-vm/containers/mail/modules/mailserver/webmail.nix -index 8230c64..e38e194 100644 ---- a/hosts/hetzner-vm/containers/mail/modules/mailserver/webmail.nix -+++ b/hosts/hetzner-vm/containers/mail/modules/mailserver/webmail.nix -@@ -3,7 +3,7 @@ - lib, - ... - }: let -- mail_config = config.mailserver; -+ mail_config = config.services.mailserver; - in { - config = lib.mkIf (mail_config.enable && mail_config.enable_roundcube) { - services.roundcube = { -diff --git a/hosts/hetzner-vm/containers/mail/profiles/mailserver.nix b/hosts/hetzner-vm/containers/mail/profiles/mailserver.nix -index bed2716..3fd9bbf 100644 ---- a/hosts/hetzner-vm/containers/mail/profiles/mailserver.nix -+++ b/hosts/hetzner-vm/containers/mail/profiles/mailserver.nix -@@ -1,7 +1,11 @@ --{host_secrets, ...}: let -+{ -+ pkgs, -+ host_secrets, -+ ... -+}: let - secrets = host_secrets; - in { -- config.mailserver = { -+ services.mailserver = { - enable = true; - fqdn = "mail.owo.monster"; - domains = ["owo.monster"]; -@@ -56,15 +60,23 @@ in { - }; - }; -  -- config.systemd.tmpfiles.rules = [ -+ systemd.tmpfiles.rules = [ - "d /var/sockets - nginx nginx" - ]; -  -- config.systemd.services.nginx.serviceConfig.ReadWritePaths = [ -+ systemd.services.nginx.serviceConfig.ReadWritePaths = [ - "/var/sockets" - ]; -  -- config.services.nginx.virtualHosts."mail.owo.monster" = { -+ services.roundcube = { -+ package = pkgs.roundcube.withPlugins (plugins: -+ with pkgs.roundcubePlugins; [ -+ persistent_login -+ ]); -+ plugins = ["persistent_login"]; -+ }; -+ -+ services.nginx.virtualHosts."mail.owo.monster" = { - listen = [ - { - addr = "127.0.0.1"; -diff --git a/hosts/hetzner-vm/containers/mail/profiles/restic.nix b/hosts/hetzner-vm/containers/mail/profiles/restic.nix -index 18ac0ef..d66cb66 100644 ---- a/hosts/hetzner-vm/containers/mail/profiles/restic.nix -+++ b/hosts/hetzner-vm/containers/mail/profiles/restic.nix -@@ -6,7 +6,7 @@ - ... - }: let - secrets = host_secrets; -- mail_config = config.mailserver; -+ mail_config = config.services.mailserver; - backupPrepareCommand = "${ - (pkgs.writeShellScriptBin "backupPrepareCommand" '' - systemctl start postgresqlBackup-roundcube --wait -diff --git a/hosts/hetzner-vm/containers/music/data/ports.nix b/hosts/hetzner-vm/containers/music/data/ports.nix -index 4fdaed1..4209c4b 100644 ---- a/hosts/hetzner-vm/containers/music/data/ports.nix -+++ b/hosts/hetzner-vm/containers/music/data/ports.nix -@@ -4,4 +4,5 @@ - mpd-opus-medium = 4243; - mpd-opus-high = 4244; - mpd-flac = 4245; -+ skskd = 5000; - } -diff --git a/hosts/hetzner-vm/containers/music/music.nix b/hosts/hetzner-vm/containers/music/music.nix -index b199191..44e403d 100644 ---- a/hosts/hetzner-vm/containers/music/music.nix -+++ b/hosts/hetzner-vm/containers/music/music.nix -@@ -11,13 +11,22 @@ -  - # Using secrets from Host - secrets = config.services.secrets.secrets; -+ containerName = "music"; -+ -+ socketPathFor = ( -+ name: "/var/lib/nixos-containers/${containerName}/var/sockets/${name}.sock" -+ ); -  - ports = import ./data/ports.nix {}; - in { - networking.nat.forwardPorts = [ - { -- sourcePort = 6600; -- destination = "${containerIP}\:6600"; -+ sourcePort = ports.mpd; -+ destination = "${containerIP}\:${toString ports.mpd}"; -+ } -+ { -+ sourcePort = ports.slskd; -+ destination = "${containerIP}\:${toString ports.slskd}"; - } - ]; -  -@@ -26,13 +35,16 @@ in { - privateNetwork = true; - hostAddress = hostIP; - localAddress = containerIP; -- bindMounts = lib.mkMerge (lib.forEach ["mpd_control_password"] (secret_name: let -- path = "${secrets.${secret_name}.path}"; -- in { -- "${path}" = { -- hostPath = "${path}"; -- }; -- })); -+ bindMounts = lib.mkMerge (lib.forEach [ -+ "mpd_control_password" -+ "slskd_env" -+ ] (secret_name: let -+ path = "${secrets.${secret_name}.path}"; -+ in { -+ "${path}" = { -+ hostPath = "${path}"; -+ }; -+ })); -  - config = { - config, -@@ -51,6 +63,7 @@ in { - inputs.home-manager-unstable.nixosModules.home-manager -  - profiles.sshd -+ profiles.nginx -  - modules.nixos.secrets -  -@@ -59,6 +72,7 @@ in { - ++ (with hosts.hetzner-vm.containers.music; [ - profiles.music-sync - profiles.mpd -+ profiles.soulseek - ]); -  - # For Shared Secrets -@@ -84,6 +98,14 @@ in { - }; - }; -  -+ services.nginx.virtualHosts."soulseek.owo.monster" = { -+ forceSSL = true; -+ enableACME = true; -+ locations."/" = { -+ proxyPass = "http://${containerIP}:80"; -+ }; -+ }; -+ - services.nginx.virtualHosts."stream.owo.monster" = let - extraConfig = '' - auth_basic "Music Password"; -@@ -117,5 +139,8 @@ in { - gid = config.ids.gids.mpd; - }; -  -- networking.firewall.allowedTCPPorts = [6600]; -+ networking.firewall.allowedTCPPorts = with ports; [ -+ mpd -+ slskd -+ ]; - } -diff --git a/hosts/hetzner-vm/containers/music/profiles/soulseek.nix b/hosts/hetzner-vm/containers/music/profiles/soulseek.nix -new file mode 100644 -index 0000000..d7906eb ---- /dev/null -+++ b/hosts/hetzner-vm/containers/music/profiles/soulseek.nix -@@ -0,0 +1,40 @@ -+{ -+ lib, -+ host_secrets, -+ ... -+}: let -+ ports = import ../data/ports.nix {}; -+ secrets = host_secrets; -+ -+ inherit (lib.modules) mkForce; -+in { -+ services.slskd = { -+ enable = true; -+ openFirewall = true; -+ environmentFile = secrets.slskd_env.path; -+ settings = { -+ remote_configuration = false; -+ remote_file_management = true; -+ soulseek = { -+ username = "chaoticryptidz"; -+ description = "chaos's soulseek"; -+ listen_port = ports.slskd; -+ }; -+ web.authentication = { -+ username = "chaos"; -+ }; -+ shares.directories = [ -+ "/Music" -+ ]; -+ }; -+ nginx = { -+ enable = true; # I don't think this is even cheked -+ domainName = "soulseek.owo.monster"; -+ }; -+ }; -+ -+ services.nginx.virtualHosts."soulseek.owo.monster" = { -+ forceSSL = mkForce false; -+ enableACME = mkForce false; -+ }; -+} -diff --git a/hosts/hetzner-vm/containers/social/profiles/backups.nix b/hosts/hetzner-vm/containers/social/profiles/backups.nix -index 4d5346b..5e70ca1 100644 ---- a/hosts/hetzner-vm/containers/social/profiles/backups.nix -+++ b/hosts/hetzner-vm/containers/social/profiles/backups.nix -@@ -38,7 +38,7 @@ - }/bin/backupPrepareCommand"; -  - backupCleanupCommand = "${(pkgs.writeShellScriptBin "backupCleanupCommand" '' -- rm /var/lib/gotosocial/gts-export.json -+ rm /var/lib/gotosocial/gts-export.json || true - '')}/bin/backupCleanupCommand"; - in { - environment.systemPackages = with pkgs; [ -diff --git a/hosts/hetzner-vm/hetzner-vm.nix b/hosts/hetzner-vm/hetzner-vm.nix -index 7924a9b..a45dc1f 100644 ---- a/hosts/hetzner-vm/hetzner-vm.nix -+++ b/hosts/hetzner-vm/hetzner-vm.nix -@@ -42,7 +42,7 @@ - echo "Host: " - systemctl --failed - ${lib.concatStringsSep "\n" (lib.forEach (lib.attrNames config.containers) (name: '' -- echo "Container: " -+ echo "Container: ${name}" - systemctl -M ${name} --failed - ''))} - '') -diff --git a/hosts/hetzner-vm/secrets.nix b/hosts/hetzner-vm/secrets.nix -index 30e3f97..98a1ab4 100644 ---- a/hosts/hetzner-vm/secrets.nix -+++ b/hosts/hetzner-vm/secrets.nix -@@ -60,6 +60,15 @@ - htpasswd -bc $secretFile "$username" "$password" 2>/dev/null - ''; - }; -+ slskd_env = { -+ fetchScript = '' -+ soulseek_password=$(simple_get "/passwords/soulseek" .password) -+ slskd_password=$(simple_get "/passwords/slskd" .password) -+ echo > $secretFile -+ echo "SLSKD_SLSK_PASSWORD=$soulseek_password" >> $secretFile -+ echo "SLSKD_PASSWORD=$slskd_password" >> $secretFile -+ ''; -+ }; -  - # Container: mail - mail_restic_password = { -diff --git a/profiles/gui/base/default.nix b/profiles/gui/base/default.nix -index 5563f5b..0786b5b 100644 ---- a/profiles/gui/base/default.nix -+++ b/profiles/gui/base/default.nix -@@ -1,6 +1,11 @@ --{pkgs, lib, config, ...}: let  -+{ -+ pkgs, -+ lib, -+ config, -+ ... -+}: let - inherit (lib.modules) mkIf; --  -+ - networkManagerEnabled = config.networking.networkmanager.enable; - in { - environment.systemPackages = with pkgs; [ diff --git a/modules/nixos/secrets-lib/lib.nix b/modules/nixos/secrets-lib/lib.nix new file mode 100644 index 0000000..7ca5a41 --- /dev/null +++ b/modules/nixos/secrets-lib/lib.nix @@ -0,0 +1,291 @@ +{ + pkgs, + lib, + ... +}: let + inherit (builtins) attrNames hasAttr isString; + inherit (lib.lists) forEach unique flatten; + inherit (lib.strings) concatStringsSep optionalString; + inherit (lib.attrsets) mapAttrsToList filterAttrs; + inherit (pkgs) writeShellApplication; + + genScripts = cfg: let + scriptBase = '' + set -e -o pipefail + ${optionalString cfg.debug "set -x"} + + set +u + # If sysroot is set then make sure it has trailing / + if [ -n "$SYSROOT" ]; then + if ! (echo "$SYSROOT" | grep -q "/$"); then + SYSROOT="$SYSROOT/" + fi + fi + # If sysroot is empty then make sure it is empty so it doesn't error + [ -z "$SYSROOT" ] && SYSROOT= + set -u + + if [ -n "$SYSROOT" ]; then + echo "Using sysroot: $SYSROOT" + fi + + ${optionalString cfg.createSecretsDir '' + if [ ! -d "$SYSROOT${cfg.secretsDir}" ]; then + mkdir -p "$SYSROOT${cfg.secretsDir}" + chown "${userOrMappedID cfg.secretsDirUser}:${groupOrMappedID cfg.secretsDirGroup}" "$SYSROOT${cfg.secretsDir}" + fi + + userLookupFailed=false + ${concatStringsSep "\n" (forEach allUsersNotMappedToUID (user: '' + if ! getent passwd ${user} >/dev/null; then + echo "User ${user} could not be found on the host system" + userLookupFailed=true + fi + ''))} + + groupLookupFailed=false + ${concatStringsSep "\n" (forEach allGroupsNotMappedToGID (group: '' + if ! getent group ${group} >/dev/null; then + echo "Group ${group} could not be found on the host system" + groupLookupFailed=true + fi + ''))} + + if $userLookupFailed; then + echo "Please add mappings in uidMap in order for this script to work" + fi + if $groupLookupFailed; then + echo "Please add mappings in gidMap in order for this script to work" + fi + + if $userLookupFailed ̣ || $groupLookupFailed; then + exit 1 + fi + ''} + ''; + + allUsers = unique ([cfg.secretsDirUser] + ++ flatten ( + forEach (attrNames cfg.secrets) (name: cfg.secrets.${name}.user) + )); + + allGroups = unique ([cfg.secretsDirGroup] + ++ flatten ( + forEach (attrNames cfg.secrets) (name: cfg.secrets.${name}.group) + )); + + allUsersByName = lib.filter isString allUsers; + allGroupsByName = lib.filter isString allGroups; + + allUsersNotMappedToUID = lib.filter (name: !(hasAttr name cfg.uidMap)) allUsersByName; + allGroupsNotMappedToGID = lib.filter (name: !(hasAttr name cfg.gidMap)) allGroupsByName; + + isUserMapped = name: (hasAttr name cfg.uidMap); + isGroupMapped = name: (hasAttr name cfg.gidMap); + + userOrMappedID = user: + if (isString user && (hasAttr user cfg.uidMap)) + then (toString cfg.uidMap.${user}) + else toString user; + groupOrMappedID = group: + if (isString group && (hasAttr group cfg.gidMap)) + then (toString cfg.gidMap.${group}) + else toString group; + + manualSecrets = filterAttrs (_: secret: secret.manual) cfg.secrets; + nonManualSecrets = filterAttrs (_: secret: !secret.manual) cfg.secrets; + in { + initScript = + '' + ${scriptBase} + + VAULT_ADDR_DEFAULT="${cfg.vaultURL}" + set +u + [ -z "$VAULT_ADDR" ] && export VAULT_ADDR="$VAULT_ADDR_DEFAULT" + set -u + + kv_get() { + vault kv get -format json "$1" + } + + simple_get() { + kv_get "$1" | jq ".data.data$2" -r + } + + ${cfg.extraFunctions} + '' + + (concatStringsSep "\n" (mapAttrsToList (_name: secret: let + secretPath = secret.path; + secretUser = userOrMappedID secret.user; + secretGroup = groupOrMappedID secret.group; + secretPermissions = secret.permissions; + in '' + if [[ ! -f "$SYSROOT${secretPath}" ]]; then + echo "Initializing Secret ${secretPath}" + else + echo "Updating Secret ${secretPath}" + fi + + secretFile="$SYSROOT${secretPath}" + ${secret.fetchScript} + + chown ${secretUser}:${secretGroup} "$SYSROOT${secretPath}" + chmod ${secretPermissions} "$SYSROOT${secretPath}" + '') + nonManualSecrets)) + + (concatStringsSep "\n" (mapAttrsToList + (_name: secret: let + secretPath = secret.path; + secretUser = userOrMappedID secret.user; + secretGroup = groupOrMappedID secret.group; + secretPermissions = secret.permissions; + in '' + if [[ ! -f "$SYSROOT${secretPath}" ]]; then + echo "Manual Secret ${secretPath} Doesn't Exist" + exit 1 + fi + + echo "Updating Permissions on Manual Secret ${secretPath}" + + chown ${secretUser}:${secretGroup} "$SYSROOT${secretPath}" + chmod ${secretPermissions} "$SYSROOT${secretPath}" + '') + manualSecrets)) + + '' + echo "Secrets Deployed" + ''; + + checkScript = + '' + ${scriptBase} + + getUser() { + stat --format "%U" "$1" 2>/dev/null + } + + getUserID() { + stat --format "%u" "$1" 2>/dev/null + } + + getGroup() { + stat --format "%G" "$1" 2>/dev/null + } + + getGroupID() { + stat --format "%G" "$1" 2>/dev/null + } + + userNameMatches() { + [[ "$(getUser "$1")" == "$2" ]] + } + + userIDMatches() { + [[ "$(getUserID "$1")" == "$2" ]] + } + + groupNameMatches() { + [[ "$(getGroup "$1")" == "$2" ]] + } + + groupIDMatches() { + [[ "$(getGroupID "$1")" == "$2" ]] + } + + getPermissions() { + stat --format "%a" "$1" 2>/dev/null + } + + GLOBAL_FAIL=false + '' + + (concatStringsSep "\n" (mapAttrsToList (_name: secret: let + secretPath = secret.path; + + secretUser = secret.user; + secretUserMaybeMapped = userOrMappedID secretUser; + + secretGroup = secret.group; + secretGroupMaybeMapped = groupOrMappedID secretGroup; + + secretPermissions = secret.permissions; + + userCheck = + if (isString secretUser && !isUserMapped secretUser) + then "userNameMatches \"${secretPath}\" ${secretUser}" + else "userIDMatches \"${secretPath}\" ${secretUserMaybeMapped}"; + groupCheck = + if (isString secretGroup && !isGroupMapped secretGroup) + then "groupNameMatches \"${secretPath}\" ${secretGroup}" + else "groupIDMatches \"${secretPath}\" ${secretGroupMaybeMapped}"; + in '' + LOCAL_FAIL=false + + echo "Checking ${secretPath}" + + # some variables which can be used by checkScript + # shellcheck disable=SC2034 + secretFile="$SYSROOT${secretPath}" + + if [[ -f "$SYSROOT${secretPath}" ]]; then + echo "✅ File Exists" + else + echo "❌ File Does Not Exist" + LOCAL_FAIL=true + fi + + if getUserID "$SYSROOT${secretPath}" >/dev/null && ${userCheck}; then + echo "✅ File Is Owned By Correct User" + else + echo "❌ File Is Not Owned By Correct User (${toString secretUser})" + LOCAL_FAIL=true + fi + + if getGroupID "$SYSROOT${secretPath}" >/dev/null && ${groupCheck}; then + echo "✅ File Is Owned By Correct Group" + else + echo "❌ File Is Not Owned By Correct Group (${toString secretGroup})" + LOCAL_FAIL=true + fi + + if getPermissions "$SYSROOT${secretPath}" >/dev/null && [[ "$(getPermissions "$SYSROOT${secretPath}")" -eq "${secretPermissions}" ]]; then + echo "✅ File Has Correct Permissions" + else + echo "❌ File Does Not Have Correct Permissions (${secretPermissions})" + LOCAL_FAIL=true + fi + + ${optionalString (secret.checkScript != null) secret.checkScript} + + if [[ "$LOCAL_FAIL" == "true" ]]; then + echo "❌ File Did Not Pass The Vibe Check" + GLOBAL_FAIL=true + else + echo "✅ File Passed The Vibe Check" + fi + + echo + '') + cfg.secrets)) + + '' + if [[ "$GLOBAL_FAIL" == "true" ]]; then + echo "❌ One Or More Secrets Did Not Pass The Vibe Check" + exit 1 + else + echo "✅ All Secrets Passed The Vibe Check" + fi + ''; + }; + + defaultPackages = with pkgs; [vault jq]; +in { + inherit genScripts; + + mkSecretsInitScript = ( + cfg: name: let + scripts = genScripts cfg; + in (writeShellApplication { + name = "secrets-init-${name}"; + runtimeInputs = defaultPackages ++ cfg.packages; + text = scripts.initScript; + }) + ); +} diff --git a/modules/nixos/secrets.nix b/modules/nixos/secrets.nix index 03cedbf..4036ac6 100644 --- a/modules/nixos/secrets.nix +++ b/modules/nixos/secrets.nix @@ -3,10 +3,17 @@ pkgs, config, ... -}: -with lib; let +}: let + inherit (lib.modules) mkIf mkMerge; + inherit (lib.options) mkOption; + inherit (lib) types; + inherit (pkgs) writeShellApplication; + cfg = config.services.secrets; - defaultPackages = with pkgs; [pkgs.vault pkgs.jq]; + + secretsLib = import ./secrets-lib/lib.nix { + inherit lib pkgs; + }; in { options = { services.secrets = { @@ -26,12 +33,12 @@ in { }; secretsDirUser = mkOption { - type = types.str; + type = types.either types.str types.int; default = "root"; }; secretsDirGroup = mkOption { - type = types.str; + type = types.either types.str types.int; default = "root"; }; @@ -52,21 +59,33 @@ in { description = "extra bash functions to add to top of script"; }; - extraPackages = mkOption { + uidMap = mkOption { + type = types.attrsOf types.int; + default = {}; + description = "optional mapping of users to user IDs; required for SYSROOT when user isn't available on host"; + }; + + gidMap = mkOption { + type = types.attrsOf types.int; + default = {}; + description = "optional mapping of groups to group IDs; required for SYSROOT when group isn't available on host"; + }; + + packages = mkOption { type = types.listOf types.package; - default = []; - description = "extra packages for script"; + default = with pkgs; []; + description = "packages for script"; }; secrets = mkOption { type = types.attrsOf (types.submodule ({name, ...}: { options = { user = mkOption { - type = types.str; + type = types.either types.str types.int; default = "root"; }; group = mkOption { - type = types.str; + type = types.either types.str types.int; default = "root"; }; permissions = mkOption { @@ -79,9 +98,10 @@ in { }; fetchScript = mkOption { - type = types.lines; + type = types.nullOr types.lines; + default = null; description = '' - script used to fetch secrets, $file is secret.path + script used to fetch secrets, $secretFile is secret.path ''; }; @@ -106,166 +126,26 @@ in { config = mkMerge [ (mkIf (cfg.enable) (let - scriptBase = '' - set -e -o pipefail - ${ - if cfg.debug - then "set -x" - else "" - } - ''; - - manualSecrets = filterAttrs (_: secret: secret.manual) cfg.secrets; - nonManualSecrets = filterAttrs (_: secret: !secret.manual) cfg.secrets; - - initScript = - '' - ${scriptBase} - - VAULT_ADDR_DEFAULT="${cfg.vaultURL}" - set +u - [ -z "$VAULT_ADDR" ] && export VAULT_ADDR="$VAULT_ADDR_DEFAULT" - set -u - - kv_get() { - vault kv get -format json "$1" - } - - simple_get() { - kv_get "$1" | jq ".data.data$2" -r - } - - ${cfg.extraFunctions} - '' - + (lib.concatStringsSep "\n" (lib.mapAttrsToList (_name: secret: '' - if [[ ! -f "${secret.path}" ]]; then - echo "Initializing Secret ${secret.path}" - else - echo "Updating Secret ${secret.path}" - fi - - secretFile="${secret.path}" - ${secret.fetchScript} - - chown ${secret.user}:${secret.group} "${secret.path}" - chmod ${secret.permissions} "${secret.path}" - '') - nonManualSecrets)) - + (lib.concatStringsSep "\n" (lib.mapAttrsToList - (_name: secret: '' - if [[ ! -f "${secret.path}" ]]; then - echo "Manual Secret ${secret.path} Doesn't Exist" - exit 1 - fi - - echo "Updating Permissions on Manual Secret ${secret.path}" - - chown ${secret.user}:${secret.group} "${secret.path}" - chmod ${secret.permissions} "${secret.path}" - '') - manualSecrets)) - + '' - echo "Secrets Deployed" - ''; - - checkScript = - '' - ${scriptBase} - - getUser() { - stat --format "%U" "$1" 2>/dev/null - } - - getGroup() { - stat --format "%G" "$1" 2>/dev/null - } - - getPermissions() { - stat --format "%a" "$1" 2>/dev/null - } - - GLOBAL_FAIL=false - '' - + (lib.concatStringsSep "\n" (lib.mapAttrsToList (name: secret: '' - LOCAL_FAIL=false - - echo "Secret: ${name}" - echo "Checking ${secret.path}" - - # some variables which can be used by checkScript - # shellcheck disable=SC2034 - secretFile="${secret.path}" - - if [[ -f "${secret.path}" ]]; then - echo "✅ File Exists" - else - echo "❌ File Does Not Exist" - LOCAL_FAIL=true - fi - - if getUser "${secret.path}" >/dev/null && [[ "$(getUser "${secret.path}")" == "${secret.user}" ]]; then - echo "✅ File Is Owned By Correct User" - else - echo "❌ File Is Not Owned By Correct User (${secret.user})" - LOCAL_FAIL=true - fi - - if getGroup "${secret.path}" >/dev/null && [[ "$(getGroup "${secret.path}")" == "${secret.group}" ]]; then - echo "✅ File Is Owned By Correct Group" - else - echo "❌ File Is Not Owned By Correct Group (${secret.user})" - LOCAL_FAIL=true - fi - - if getPermissions "${secret.path}" >/dev/null && [[ "$(getPermissions "${secret.path}")" -eq "${secret.permissions}" ]]; then - echo "✅ File Has Correct Permissions" - else - echo "❌ File Does Not Have Correct Permissions (${secret.permissions})" - LOCAL_FAIL=true - fi - - ${ - if secret.checkScript != null - then secret.checkScript - else "" - } - - if [[ "$LOCAL_FAIL" == "true" ]]; then - echo "❌ File Did Not Pass The Vibe Check" - GLOBAL_FAIL=true - else - echo "✅ File Passed The Vibe Check" - fi - - echo - '') - cfg.secrets)) - + '' - if [[ "$GLOBAL_FAIL" == "true" ]]; then - echo "❌ One Or More Secrets Did Not Pass The Vibe Check" - exit 1 - else - echo "✅ All Secrets Passed The Vibe Check" - fi - ''; + scripts = secretsLib.genScripts cfg; + defaultPackages = with pkgs; [vault jq]; in { environment.systemPackages = [ - (pkgs.writeShellApplication { - name = "secrets-check"; - runtimeInputs = defaultPackages ++ cfg.extraPackages; - text = checkScript; - }) - (pkgs.writeShellApplication { + (writeShellApplication { name = "secrets-init"; - runtimeInputs = defaultPackages ++ cfg.extraPackages; - text = initScript; + runtimeInputs = defaultPackages ++ cfg.packages; + text = scripts.initScript; + }) + (writeShellApplication { + name = "secrets-check"; + runtimeInputs = defaultPackages ++ cfg.packages; + text = scripts.checkScript; }) ]; })) (mkIf (cfg.enable && cfg.createSecretsDir) { systemd.tmpfiles.rules = [ - "d ${cfg.secretsDir} - ${cfg.secretsDirUser} ${cfg.secretsDirGroup}" + "d ${cfg.secretsDir} - ${toString cfg.secretsDirUser} ${toString cfg.secretsDirGroup}" ]; }) ]; diff --git a/outputs.nix b/outputs.nix index 83969b6..e924111 100644 --- a/outputs.nix +++ b/outputs.nix @@ -20,6 +20,40 @@ in (import ./overlay) ]; }; + + secretsLib = import ./modules/nixos/secrets-lib/lib.nix { + inherit (nixpkgs) lib; + inherit pkgs; + }; + + secretsInitScriptForSystem = system_name: let + systemConfig = self.nixosConfigurations.${system_name}.config; + systemSecretsConfig = systemConfig.services.secrets; + in + secretsLib.mkSecretsInitScript systemSecretsConfig "${system_name}"; + + secretsInitScriptForSystemContainer = system_name: container_name: let + systemConfig = self.nixosConfigurations.${system_name}.config; + containerConfig = systemConfig.containers.${container_name}.config; + containerSecretsConfig = containerConfig.services.secrets; + in + secretsLib.mkSecretsInitScript containerSecretsConfig "${system_name}-${container_name}"; + + secretsInitAppForSystem = system_name: packages: let + name = "secrets-init-${system_name}"; + package = packages."${name}"; + in { + type = "app"; + program = "${package}/bin/${name}"; + }; + + secretsInitAppForSystemContainer = system_name: container_name: packages: let + name = "secrets-init-${system_name}-${container_name}"; + package = packages."${name}"; + in { + type = "app"; + program = "${package}/bin/${name}"; + }; in { devShell = pkgs.mkShell { VAULT_API_ADDR = "https://vault.owo.monster"; @@ -52,11 +86,20 @@ in type = "app"; program = "${packages.mk-dual-enc-ssd}/bin/mk-dual-enc-ssd"; }; + secrets-init-lappy-t495 = secretsInitAppForSystem "lappy-t495" packages; + secrets-init-vault = secretsInitAppForSystem "vault" packages; + secrets-init-hetzner-vm = secretsInitAppForSystem "hetzner-vm" packages; + secrets-init-hetzner-vm-storage = secretsInitAppForSystemContainer "hetzner-vm" "storage" packages; }; packages = { inherit (pkgs) comic-code comic-sans; inherit (pkgs) mk-enc-usb mk-normal-enc-ssd mk-dual-enc-ssd; inherit (pkgs) gotosocial; + secrets-init-lappy-t495 = secretsInitScriptForSystem "lappy-t495"; + + secrets-init-vault = secretsInitScriptForSystem "vault"; + secrets-init-hetzner-vm = secretsInitScriptForSystem "hetzner-vm"; + secrets-init-hetzner-vm-storage = secretsInitScriptForSystemContainer "hetzner-vm" "storage"; }; })) diff --git a/overlay/default.nix b/overlay/default.nix index 7fc4fed..dbc689b 100644 --- a/overlay/default.nix +++ b/overlay/default.nix @@ -11,7 +11,7 @@ final: prev: { mk-normal-enc-ssd = final.callPackage ../extras/mk-normal-enc-ssd.nix {}; mk-dual-enc-ssd = final.callPackage ../extras/mk-dual-enc-ssd.nix {}; - gotosocial = prev.gotosocial.overrideAttrs (old: let + gotosocial = prev.gotosocial.overrideAttrs (_old: let owner = "superseriousbusiness"; repo = "gotosocial";