allow generating secrets init scripts outside of module, run deadnix&formatter, update state versions

This commit is contained in:
chaos 2023-09-11 23:22:18 +01:00
parent 9b75a69bd4
commit b9b16c8509
No known key found for this signature in database
31 changed files with 499 additions and 670 deletions

View file

@ -1,20 +1,5 @@
{ {pkgs, ...}: {
pkgs, home.packages = with pkgs; [rofi];
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];
home.file.".local/share/rofi/themes/rofi-nord.rasi".source = ./rofi-nord.rasi; home.file.".local/share/rofi/themes/rofi-nord.rasi".source = ./rofi-nord.rasi;
home.file.".config/rofi/config.rasi".source = ./config.rasi; home.file.".config/rofi/config.rasi".source = ./config.rasi;

View file

@ -1,5 +1,5 @@
{pkgs, ...}: { {pkgs, ...}: {
home.packages = with pkgs; [alejandra]; home.packages = with pkgs; [alejandra deadnix];
programs.vscode-mod.extensions = with pkgs; [ programs.vscode-mod.extensions = with pkgs; [
vscode-extensions.bbenoist.nix vscode-extensions.bbenoist.nix

View file

@ -106,11 +106,11 @@ in {
home-manager.users.root = { home-manager.users.root = {
imports = with tree; [home.base home.dev.small]; imports = with tree; [home.base home.dev.small];
home.stateVersion = "22.05"; home.stateVersion = "23.05";
}; };
networking.hostName = "buildbox"; networking.hostName = "buildbox";
time.timeZone = "Europe/London"; time.timeZone = "Europe/London";
system.stateVersion = "22.05"; system.stateVersion = "23.05";
} }

View file

@ -7,7 +7,7 @@
user = "root"; user = "root";
group = "root"; group = "root";
fetchScript = '' fetchScript = ''
simple_get "/api-keys/chaos_mail/system" .password > $secretFile simple_get "/api-keys/chaos_mail/system" .password > "$secretFile"
''; '';
}; };
}; };

View file

@ -3,7 +3,6 @@
lib, lib,
inputs, inputs,
config, config,
pkgs,
... ...
}: let }: let
ports = [ ports = [
@ -54,11 +53,7 @@ in {
}))) })))
]; ];
config = { config = {config, ...}: {
config,
pkgs,
...
}: {
_module.args = { _module.args = {
inherit inputs; inherit inputs;
inherit tree; inherit tree;

View file

@ -69,7 +69,7 @@ in {
]; ];
services.roundcube = { services.roundcube = {
package = pkgs.roundcube.withPlugins (plugins: package = pkgs.roundcube.withPlugins (_plugins:
with pkgs.roundcubePlugins; [ with pkgs.roundcubePlugins; [
persistent_login persistent_login
]); ]);

View file

@ -1,7 +1,6 @@
{ {
pkgs, pkgs,
config, config,
lib,
host_secrets, host_secrets,
... ...
}: let }: let

View file

@ -83,13 +83,13 @@ in {
home-manager.users.root = { home-manager.users.root = {
imports = with tree; [home.base home.dev.small]; imports = with tree; [home.base home.dev.small];
home.packages = with pkgs; [vault]; home.packages = with pkgs; [vault];
home.stateVersion = "22.05"; home.stateVersion = "23.05";
}; };
# Manually configure nameserver. Using resolved inside the container seems to fail # Manually configure nameserver. Using resolved inside the container seems to fail
# currently # currently
environment.etc."resolv.conf".text = "nameserver 8.8.8.8"; environment.etc."resolv.conf".text = "nameserver 8.8.8.8";
system.stateVersion = "22.05"; system.stateVersion = "23.05";
}; };
}; };

View file

@ -3,7 +3,6 @@
lib, lib,
inputs, inputs,
config, config,
pkgs,
... ...
}: let }: let
container-addresses = import ../../data/container-addresses.nix {}; container-addresses = import ../../data/container-addresses.nix {};
@ -37,11 +36,7 @@ in {
}; };
})); }));
config = { config = {config, ...}: {
config,
pkgs,
...
}: {
_module.args = { _module.args = {
inherit inputs; inherit inputs;
inherit tree; inherit tree;

View file

@ -1,7 +1,5 @@
{ {
pkgs, pkgs,
config,
lib,
host_secrets, host_secrets,
... ...
}: let }: let

View file

@ -1,7 +1,5 @@
{ {
pkgs, pkgs,
config,
lib,
host_secrets, host_secrets,
... ...
}: let }: let

View file

@ -36,11 +36,7 @@ in {
}; };
})); }));
config = { config = {config, ...}: {
config,
pkgs,
...
}: {
_module.args = { _module.args = {
inherit inputs; inherit inputs;
inherit tree; inherit tree;

View file

@ -8,7 +8,7 @@ in {
services.gotosocial = { services.gotosocial = {
enable = true; enable = true;
setupPostgresqlDB = true; setupPostgresqlDB = true;
environmentFile = host_secrets.social_env_secrets.path; environmentFile = secrets.social_env_secrets.path;
settings = { settings = {
application-name = "chaos-gts"; application-name = "chaos-gts";

View file

@ -73,13 +73,13 @@ in {
home-manager.users.root = { home-manager.users.root = {
imports = with tree; [home.base home.dev.small]; imports = with tree; [home.base home.dev.small];
home.packages = with pkgs; [vault]; home.packages = with pkgs; [vault];
home.stateVersion = "22.05"; home.stateVersion = "23.05";
}; };
# Manually configure nameserver. Using resolved inside the container seems to fail # Manually configure nameserver. Using resolved inside the container seems to fail
# currently # currently
environment.etc."resolv.conf".text = "nameserver 8.8.8.8"; environment.etc."resolv.conf".text = "nameserver 8.8.8.8";
system.stateVersion = "22.05"; system.stateVersion = "23.05";
}; };
}; };

View file

@ -1,14 +1,26 @@
{pkgs, ...}: { {
config,
pkgs,
...
}: {
services.secrets = { services.secrets = {
enable = true; enable = true;
extraPackages = with pkgs; [ packages = with pkgs; [
# for music & mail passwd files # for music & mail passwd files
apacheHttpd apacheHttpd
# for rclone obscure config file # for rclone obscure config file
rclone rclone
]; ];
uidMap = {
"storage" = config.users.users."storage".uid;
};
gidMap = {
"storage" = config.users.groups."storage".gid;
};
extraFunctions = '' extraFunctions = ''
replace_slash_for_sed() { replace_slash_for_sed() {
sed "s#/#\\\/#" sed "s#/#\\\/#"
@ -108,7 +120,7 @@
fetchScript = '' fetchScript = ''
username=$(simple_get "/api-keys/storage/webdav/main" .username) username=$(simple_get "/api-keys/storage/webdav/main" .username)
password=$(simple_get "/api-keys/storage/webdav/main" .password) 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 = { webdav_media_htpasswd = {
@ -117,7 +129,7 @@
fetchScript = '' fetchScript = ''
username=$(simple_get "/api-keys/storage/webdav/media" .username) username=$(simple_get "/api-keys/storage/webdav/media" .username)
password=$(simple_get "/api-keys/storage/webdav/media" .password) 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" 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) STORAGEBOX_PASSWORD=$(simple_get_obscure /api-keys/hetzner/storagebox .password)
sed -i "s/STORAGEBOX_PASSWORD/$STORAGEBOX_PASSWORD/" ./template 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 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" rm -rf "$TMP_DIR"
''; '';

View file

@ -1,6 +1,9 @@
{...}: { {...}: {
users.groups.storage = {}; users.groups.storage = {
gid = 1000;
};
users.users.storage = { users.users.storage = {
uid = 1000;
isNormalUser = true; isNormalUser = true;
extraGroups = ["storage"]; extraGroups = ["storage"];
}; };

View file

@ -59,7 +59,7 @@ in {
home-manager.users.root = { home-manager.users.root = {
imports = with tree; [home.base home.dev.small]; imports = with tree; [home.base home.dev.small];
home.packages = with pkgs; [vault]; home.packages = with pkgs; [vault];
home.stateVersion = "22.05"; home.stateVersion = "23.05";
}; };
networking.firewall = { networking.firewall = {
@ -70,7 +70,7 @@ in {
# Manually configure nameserver. Using resolved inside the container seems to fail # Manually configure nameserver. Using resolved inside the container seems to fail
# currently # currently
environment.etc."resolv.conf".text = "nameserver 8.8.8.8"; environment.etc."resolv.conf".text = "nameserver 8.8.8.8";
system.stateVersion = "22.05"; system.stateVersion = "23.05";
}; };
}; };

View file

@ -72,11 +72,11 @@
home-manager.users.root = { home-manager.users.root = {
imports = with tree; [home.base home.dev.small]; imports = with tree; [home.base home.dev.small];
home.stateVersion = "22.05"; home.stateVersion = "23.05";
}; };
networking.hostName = "hetzner-vm"; networking.hostName = "hetzner-vm";
time.timeZone = "Europe/London"; time.timeZone = "Europe/London";
system.stateVersion = "22.05"; system.stateVersion = "23.05";
} }

View file

@ -1,6 +1,9 @@
{config, ...}: let {config, ...}: let
secrets = config.services.secrets.secrets; secrets = config.services.secrets.secrets;
in { in {
users.users.gitlab_artifacts_sync.uid = 2001;
users.groups.gitlab_artifacts_sync.gid = 2001;
services.gitlab_artifacts_sync = { services.gitlab_artifacts_sync = {
enable = true; enable = true;
credentialsEnvironmentFile = "${secrets.gitlab_env.path}"; credentialsEnvironmentFile = "${secrets.gitlab_env.path}";

View file

@ -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 = { services.secrets = {
enable = true; enable = true;
extraPackages = with pkgs; [ packages = with pkgs; [
# for music & mail passwd files # for music & mail passwd files
apacheHttpd 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 = { secrets = {
# Used directly by server # Used directly by server
# for fetching gitlab static sites # for fetching gitlab static sites
@ -15,31 +40,31 @@
group = "gitlab_artifacts_sync"; group = "gitlab_artifacts_sync";
fetchScript = '' fetchScript = ''
token=$(simple_get "/api-keys/gitlab/gitlab_pages_serve" .token) token=$(simple_get "/api-keys/gitlab/gitlab_pages_serve" .token)
echo "GITLAB_TOKEN=$token" > $secretFile echo "GITLAB_TOKEN=$token" > "$secretFile"
''; '';
}; };
# for wireguard # for wireguard
wg_privkey = { wg_privkey = {
fetchScript = '' 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 = { wg_preshared_vault = {
path = "/secrets/wg_preshared_vault"; path = "/secrets/wg_preshared_vault";
fetchScript = '' 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 = { wg_preshared_iphone8 = {
path = "/secrets/wg_preshared_iphone8"; path = "/secrets/wg_preshared_iphone8";
fetchScript = '' 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 = { wg_preshared_lappy-t495 = {
path = "/secrets/wg_preshared_lappy-t495"; path = "/secrets/wg_preshared_lappy-t495";
fetchScript = '' 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"; user = "mpd";
group = "mpd"; group = "mpd";
fetchScript = '' fetchScript = ''
simple_get "/api-keys/mpd" .password > $secretFile simple_get "/api-keys/mpd" .password > "$secretFile"
''; '';
}; };
music_stream_passwd = { music_stream_passwd = {
@ -57,37 +82,37 @@
fetchScript = '' fetchScript = ''
username=$(simple_get "/api-keys/music-stream" .username) username=$(simple_get "/api-keys/music-stream" .username)
password=$(simple_get "/api-keys/music-stream" .password) 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 = { slskd_env = {
fetchScript = '' fetchScript = ''
soulseek_password=$(simple_get "/passwords/soulseek" .password) soulseek_password=$(simple_get "/passwords/soulseek" .password)
slskd_password=$(simple_get "/passwords/slskd" .password) slskd_password=$(simple_get "/passwords/slskd" .password)
echo > $secretFile echo > "$secretFile"
echo "SLSKD_SLSK_PASSWORD=$soulseek_password" >> $secretFile echo "SLSKD_SLSK_PASSWORD=$soulseek_password" >> "$secretFile"
echo "SLSKD_PASSWORD=$slskd_password" >> $secretFile echo "SLSKD_PASSWORD=$slskd_password" >> "$secretFile"
''; '';
}; };
# Container: mail # Container: mail
mail_restic_password = { mail_restic_password = {
fetchScript = '' fetchScript = ''
simple_get "/private-public-keys/restic/Mail" .password > $secretFile simple_get "/private-public-keys/restic/Mail" .password > "$secretFile"
''; '';
}; };
mail_restic_env = { mail_restic_env = {
fetchScript = '' fetchScript = ''
RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Mail" .username) RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Mail" .username)
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Mail" .password) 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 = { private_mail_aliases = {
user = "root"; user = "root";
group = "root"; group = "root";
fetchScript = '' 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 = { chaos_mail_passwd = {
@ -95,7 +120,7 @@
group = "dovecot2"; group = "dovecot2";
fetchScript = '' fetchScript = ''
password=$(simple_get "/passwords/mail" .password) 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 = { system_mail_passwd = {
@ -103,7 +128,7 @@
group = "dovecot2"; group = "dovecot2";
fetchScript = '' fetchScript = ''
password=$(simple_get "/api-keys/chaos_mail/system" .password) 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 = { gotosocial_mail_passwd = {
@ -111,21 +136,21 @@
group = "dovecot2"; group = "dovecot2";
fetchScript = '' fetchScript = ''
password=$(simple_get "/api-keys/chaos_mail/gotosocial" .password) 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 # Container: social
social_restic_password = { social_restic_password = {
fetchScript = '' fetchScript = ''
simple_get "/private-public-keys/restic/Social" .password > $secretFile simple_get "/private-public-keys/restic/Social" .password > "$secretFile"
''; '';
}; };
social_restic_env = { social_restic_env = {
fetchScript = '' fetchScript = ''
RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Social" .username) RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Social" .username)
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Social" .password) 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 = { social_env_secrets = {
@ -133,35 +158,35 @@
group = "root"; group = "root";
fetchScript = '' fetchScript = ''
smtp_password=$(simple_get "/api-keys/chaos_mail/gotosocial" .password) 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 # Container: quassel
quassel_restic_password = { quassel_restic_password = {
fetchScript = '' fetchScript = ''
simple_get "/private-public-keys/restic/Quassel" .password > $secretFile simple_get "/private-public-keys/restic/Quassel" .password > "$secretFile"
''; '';
}; };
quassel_restic_env = { quassel_restic_env = {
fetchScript = '' fetchScript = ''
RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Quassel" .username) RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Quassel" .username)
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Quassel" .password) 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 # Container: piped
piped_restic_password = { piped_restic_password = {
fetchScript = '' fetchScript = ''
simple_get "/private-public-keys/restic/Piped" .password > $secretFile simple_get "/private-public-keys/restic/Piped" .password > "$secretFile"
''; '';
}; };
piped_restic_env = { piped_restic_env = {
fetchScript = '' fetchScript = ''
RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Piped" .username) RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Piped" .username)
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Piped" .password) 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"
''; '';
}; };
}; };

View file

@ -5,10 +5,10 @@
usb_encryption_passphrase = {manual = true;}; usb_encryption_passphrase = {manual = true;};
music_stream_password = { music_stream_password = {
user = "chaos"; user = 1000;
group = "users"; group = "users";
fetchScript = '' fetchScript = ''
simple_get "/api-keys/music-stream" .password > $secretFile simple_get "/api-keys/music-stream" .password > "$secretFile"
''; '';
}; };
@ -18,7 +18,7 @@
group = "users"; group = "users";
fetchScript = '' 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) api_password=$(simple_get "/api-keys/storage/restic/Music" .password)
restic_password=$(simple_get "/private-public-keys/restic/Music" .password) restic_password=$(simple_get "/private-public-keys/restic/Music" .password)
echo > $secretFile echo > "$secretFile"
echo "RESTIC_REPOSITORY=rest:https://''${api_username}:''${api_password}@storage-restic.owo.monster/Music" >> $secretFile echo "RESTIC_REPOSITORY=rest:https://''${api_username}:''${api_password}@storage-restic.owo.monster/Music" >> "$secretFile"
echo "RESTIC_PASSWORD=''${restic_password}" >> $secretFile echo "RESTIC_PASSWORD=''${restic_password}" >> "$secretFile"
''; '';
}; };
# for internal wireguard VPN # for internal wireguard VPN
wg_priv = { wg_priv = {
fetchScript = '' 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 = { wg_preshared_hetzner-vm = {
fetchScript = '' 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 = { wg_preshared_vault = {
fetchScript = '' 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"
''; '';
}; };
}; };

View file

@ -1,9 +1,7 @@
{ {
self,
config, config,
tree, tree,
modulesPath, modulesPath,
pkgs,
lib, lib,
... ...
}: { }: {
@ -21,7 +19,7 @@
# disable zfs # disable zfs
nixpkgs.overlays = [ nixpkgs.overlays = [
(final: super: { (_final: super: {
zfs = super.zfs.overrideAttrs (_: { zfs = super.zfs.overrideAttrs (_: {
meta.platforms = []; meta.platforms = [];
}); });

View file

@ -7,7 +7,7 @@
user = "chaos"; user = "chaos";
group = "users"; group = "users";
fetchScript = '' fetchScript = ''
simple_get "/api-keys/music-stream" .password > $secretFile simple_get "/api-keys/music-stream" .password > "$secretFile"
''; '';
}; };
# Required for home.apps.manual-backup-apps # Required for home.apps.manual-backup-apps
@ -16,7 +16,7 @@
group = "users"; group = "users";
fetchScript = '' 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) api_password=$(simple_get "/api-keys/storage/restic/Music" .password)
restic_password=$(simple_get "/private-public-keys/restic/Music" .password) restic_password=$(simple_get "/private-public-keys/restic/Music" .password)
echo > $secretFile echo > "$secretFile"
echo "RESTIC_REPOSITORY=rest:https://''${api_username}:''${api_password}@storage-restic.owo.monster/Music" >> $secretFile echo "RESTIC_REPOSITORY=rest:https://''${api_username}:''${api_password}@storage-restic.owo.monster/Music" >> "$secretFile"
echo "RESTIC_PASSWORD=''${restic_password}" >> $secretFile echo "RESTIC_PASSWORD=''${restic_password}" >> "$secretFile"
''; '';
}; };
}; };

View file

@ -14,7 +14,7 @@
home-manager.users.root = { home-manager.users.root = {
imports = with tree; [home.base]; imports = with tree; [home.base];
home.stateVersion = "22.05"; home.stateVersion = "23.05";
}; };
home-manager.users.chaos = { home-manager.users.chaos = {
@ -28,7 +28,7 @@
home.programming.languages.rust home.programming.languages.rust
home.programming.languages.nix home.programming.languages.nix
]; ];
home.stateVersion = "22.05"; home.stateVersion = "23.05";
}; };
networking.firewall.enable = true; networking.firewall.enable = true;
@ -39,5 +39,5 @@
networking.hostName = "tablet"; networking.hostName = "tablet";
time.timeZone = "Europe/London"; time.timeZone = "Europe/London";
system.stateVersion = "22.05"; system.stateVersion = "23.05";
} }

View file

@ -4,34 +4,34 @@
secrets = { secrets = {
restic_password = { restic_password = {
fetchScript = '' fetchScript = ''
simple_get "/private-public-keys/restic/Vault" .password > $secretFile simple_get "/private-public-keys/restic/Vault" .password > "$secretFile"
''; '';
}; };
restic_env = { restic_env = {
fetchScript = '' fetchScript = ''
RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Vault" .username) RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Vault" .username)
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Vault" .password) 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 = { wg_priv = {
fetchScript = '' 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 = { wg_preshared_hetzner-vm = {
fetchScript = '' 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 = { wg_preshared_iphone8 = {
fetchScript = '' 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 = { wg_preshared_lappy-t495 = {
fetchScript = '' 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"
''; '';
}; };
}; };

View file

@ -19,11 +19,11 @@
home-manager.users.root = { home-manager.users.root = {
imports = with tree; [home.base home.dev.small]; imports = with tree; [home.base home.dev.small];
home.stateVersion = "22.05"; home.stateVersion = "23.05";
}; };
networking.hostName = "vault"; networking.hostName = "vault";
time.timeZone = "Europe/London"; time.timeZone = "Europe/London";
system.stateVersion = "22.05"; system.stateVersion = "23.05";
} }

392
ic";
View file

@ -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; [

View file

@ -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;
})
);
}

View file

@ -3,10 +3,17 @@
pkgs, pkgs,
config, config,
... ...
}: }: let
with lib; let inherit (lib.modules) mkIf mkMerge;
inherit (lib.options) mkOption;
inherit (lib) types;
inherit (pkgs) writeShellApplication;
cfg = config.services.secrets; cfg = config.services.secrets;
defaultPackages = with pkgs; [pkgs.vault pkgs.jq];
secretsLib = import ./secrets-lib/lib.nix {
inherit lib pkgs;
};
in { in {
options = { options = {
services.secrets = { services.secrets = {
@ -26,12 +33,12 @@ in {
}; };
secretsDirUser = mkOption { secretsDirUser = mkOption {
type = types.str; type = types.either types.str types.int;
default = "root"; default = "root";
}; };
secretsDirGroup = mkOption { secretsDirGroup = mkOption {
type = types.str; type = types.either types.str types.int;
default = "root"; default = "root";
}; };
@ -52,21 +59,33 @@ in {
description = "extra bash functions to add to top of script"; 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; type = types.listOf types.package;
default = []; default = with pkgs; [];
description = "extra packages for script"; description = "packages for script";
}; };
secrets = mkOption { secrets = mkOption {
type = types.attrsOf (types.submodule ({name, ...}: { type = types.attrsOf (types.submodule ({name, ...}: {
options = { options = {
user = mkOption { user = mkOption {
type = types.str; type = types.either types.str types.int;
default = "root"; default = "root";
}; };
group = mkOption { group = mkOption {
type = types.str; type = types.either types.str types.int;
default = "root"; default = "root";
}; };
permissions = mkOption { permissions = mkOption {
@ -79,9 +98,10 @@ in {
}; };
fetchScript = mkOption { fetchScript = mkOption {
type = types.lines; type = types.nullOr types.lines;
default = null;
description = '' 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 [ config = mkMerge [
(mkIf (cfg.enable) (let (mkIf (cfg.enable) (let
scriptBase = '' scripts = secretsLib.genScripts cfg;
set -e -o pipefail defaultPackages = with pkgs; [vault jq];
${
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
'';
in { in {
environment.systemPackages = [ environment.systemPackages = [
(pkgs.writeShellApplication { (writeShellApplication {
name = "secrets-check";
runtimeInputs = defaultPackages ++ cfg.extraPackages;
text = checkScript;
})
(pkgs.writeShellApplication {
name = "secrets-init"; name = "secrets-init";
runtimeInputs = defaultPackages ++ cfg.extraPackages; runtimeInputs = defaultPackages ++ cfg.packages;
text = initScript; text = scripts.initScript;
})
(writeShellApplication {
name = "secrets-check";
runtimeInputs = defaultPackages ++ cfg.packages;
text = scripts.checkScript;
}) })
]; ];
})) }))
(mkIf (cfg.enable && cfg.createSecretsDir) { (mkIf (cfg.enable && cfg.createSecretsDir) {
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [
"d ${cfg.secretsDir} - ${cfg.secretsDirUser} ${cfg.secretsDirGroup}" "d ${cfg.secretsDir} - ${toString cfg.secretsDirUser} ${toString cfg.secretsDirGroup}"
]; ];
}) })
]; ];

View file

@ -20,6 +20,40 @@ in
(import ./overlay) (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 { in {
devShell = pkgs.mkShell { devShell = pkgs.mkShell {
VAULT_API_ADDR = "https://vault.owo.monster"; VAULT_API_ADDR = "https://vault.owo.monster";
@ -52,11 +86,20 @@ in
type = "app"; type = "app";
program = "${packages.mk-dual-enc-ssd}/bin/mk-dual-enc-ssd"; 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 = { packages = {
inherit (pkgs) comic-code comic-sans; inherit (pkgs) comic-code comic-sans;
inherit (pkgs) mk-enc-usb mk-normal-enc-ssd mk-dual-enc-ssd; inherit (pkgs) mk-enc-usb mk-normal-enc-ssd mk-dual-enc-ssd;
inherit (pkgs) gotosocial; 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";
}; };
})) }))

View file

@ -11,7 +11,7 @@ final: prev: {
mk-normal-enc-ssd = final.callPackage ../extras/mk-normal-enc-ssd.nix {}; mk-normal-enc-ssd = final.callPackage ../extras/mk-normal-enc-ssd.nix {};
mk-dual-enc-ssd = final.callPackage ../extras/mk-dual-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"; owner = "superseriousbusiness";
repo = "gotosocial"; repo = "gotosocial";