From 90c1ecfe146f201c243d0ca4056c3980a48fda66 Mon Sep 17 00:00:00 2001 From: Ellis Rahhal Date: Fri, 13 Dec 2024 17:14:13 -0800 Subject: [PATCH] HF-7: Move out sops config * Updated configuration.nix to match latest homefree * Added secrets config * Updated Readme --- .sops.yaml | 10 +++ README.md | 38 +++++++- build.sh | 3 + configuration.nix | 131 ++++++++++++++++++++++------ install.sh => deploy.sh | 0 generate-gpg-keys.sh | 36 ++++++++ secrets-unencrypted/authentik.yaml | 15 ++++ secrets-unencrypted/backup.yaml | 2 + secrets-unencrypted/ddclient.yaml | 2 + secrets-unencrypted/linkwarden.yaml | 4 + secrets-unencrypted/nextcloud.yaml | 8 ++ secrets-unencrypted/tailscale.yaml | 2 + secrets.nix | 76 ++++++++++++++++ secrets/.gitignore | 0 secrets/README.md | 22 +++++ 15 files changed, 318 insertions(+), 31 deletions(-) create mode 100644 .sops.yaml create mode 100755 build.sh rename install.sh => deploy.sh (100%) create mode 100755 generate-gpg-keys.sh create mode 100644 secrets-unencrypted/authentik.yaml create mode 100644 secrets-unencrypted/backup.yaml create mode 100644 secrets-unencrypted/ddclient.yaml create mode 100644 secrets-unencrypted/linkwarden.yaml create mode 100644 secrets-unencrypted/nextcloud.yaml create mode 100644 secrets-unencrypted/tailscale.yaml create mode 100644 secrets.nix create mode 100644 secrets/.gitignore create mode 100644 secrets/README.md diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..101c2cb --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,10 @@ +# see https://github.com/Mic92/dotfiles/blob/master/nixos/.sops.yaml +keys: + - &user_homefree 06321D7F20335A7E08595BA905D137EE114BA2C2 + - &host_homefree 0BC4F8FF51F3167F06683FFB19008821C072983E +creation_rules: + - path_regex: secrets/[^/]+\.(yaml|json|env|ini)$ + key_groups: + - pgp: + - *user_homefree + - *host_homefree diff --git a/README.md b/README.md index 7ea1229..ef4dec8 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,42 @@ HomeFree Sample Config ====================== -Clone this repo and modify configuration.nix as needed, then deploy with: +## Edit config + +Clone this repo and modify configuration.nix as needed onto a freshly installed NixOS machine. + +## Create secrets + +- Generate appropriate GPG keys. You will need a private SSH key at ~/.ssh/id_rsa ``` -./install.sh +./generate-gpg-keys.sh ``` + +- Create secrets file in this folder. Use the following commands. + +``` +sops secrets/authentik.yaml +sops secrets/backup.yaml +sops secrets/ddclient.yaml +sops secrets/linkwarden.yaml +sops secrets/nextcloud.yaml +sops secrets/tailscale.yaml +``` + +And copy the contents from the appropriate file in the `secrets-unencrypted` folder, changing +the values as required. + +## Build + +``` +./build.sh +``` + +## You can also deploy remotely to a machine running the Live CD + +``` +./deploy.sh +``` + +BUT, you'll have to check out the source onto the server and run the `./generate-gpg-keys.sh` script again after deployment. diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..5c89c88 --- /dev/null +++ b/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +sudo nixos-rebuild switch --flake .#${HOSTNAME} -L diff --git a/configuration.nix b/configuration.nix index f094a54..3a0ccf1 100644 --- a/configuration.nix +++ b/configuration.nix @@ -1,7 +1,8 @@ -{ lib, ... }: +{ config, lib, ... }: { imports = [ ./disk-config.nix + ./secrets.nix ]; networking = { @@ -24,6 +25,10 @@ authorizedKeys = [ "" ]; + domain = "example.com"; + additionalDomains = [ "domain2.com" ]; + timeZone = "America/Los_Angeles"; + countryCode = "US"; }; network = { @@ -62,25 +67,17 @@ zones = [ ## Repace with your own domain { - zone = "homefree.host"; + zone = "example.com"; + protocol = "hetzner"; + username = "username"; + passwordFile = config.sops.secrets."ddclient/ddclient-password".path; + } + ## Repace with your own domain + { + zone = "domain2.com"; protocol = "hetzner"; username = "erahhal"; - passwordFile = "/run/secrets/ddclient/ddclient-password"; - } - ]; - }; - - wireguard = { - peers = [ - { - name = "my-phone"; - publicKey = "="; - allowedIPs = [ "192.168.2.2/32"]; - } - { - name = "bros-phone"; - publicKey = ""; - allowedIPs = [ "192.168.2.3/32"]; + passwordFile = config.sops.secrets."ddclient/ddclient-password".path; } ]; }; @@ -90,15 +87,73 @@ enable = true; }; + authentik = { + enable = true; + secrets = { + environment = config.sops.secrets."authentik/authentik-env".path; + ldap-environment = config.sops.secrets."authentik/authentik-ldap-env".path; + }; + }; + + baikal = { + enable = true; + }; + + cryptpad = { + enable = true; + adminKeys = [ + "" + ]; + }; + homeassistant = { enable = true; }; + frigate = { + enable = true; + cameras = [ + { + enable = true; + name = "gate"; + path = "rtsp://10.0.0.15/11"; + width = 1920; + height = 1080; + } + ]; + }; gitea = { enable = true; public = true; }; + headscale = { + enable = true; + secrets = { + tailscale-key = config.sops.secrets."tailscale/key".path; + }; + }; + + headscale-ui = { + enable = true; + }; + + jellyfin = { + enable = true; + }; + + linkwarden = { + enable = true; + }; + + nextcloud = { + enable = true; + secrets = { + admin-password = config.sops.secrets."nextcloud/admin-password".path; + secret-file = config.sops.secrets."nextcloud/secret-file".path; + }; + }; + radicale = { enable = true; }; @@ -112,23 +167,41 @@ }; }; - proxied-hosts = [ + service-config = [ { label = "att"; - subdomains = [ "att" ]; - https-domains = [ "homefree.host" "rahh.al" ]; - host = "att.localdomain"; - port = 80; + reverse-proxy = { + enable = true; + subdomains = [ "att" ]; + https-domains = [ "homefree.host" "rahh.al" ]; + host = "att.localdomain"; + port = 80; + }; } { label = "yamaha-recevier-web-gui"; - subdomains = [ "yamaha" ]; - https-domains = [ "homefree-host" ]; - port = 443; - ssl = true; - ssl-no-verify = true; - host = "yamaha.localdomain"; + reverse-proxy = { + subdomains = [ "yamaha" ]; + https-domains = [ "homefree-host" ]; + port = 443; + ssl = true; + ssl-no-verify = true; + host = "yamaha.localdomain"; + }; } ]; + + backups = { + enable = true; + to-path = "/var/lib/backups"; + extra-from-paths = [ + "/mnt/nfs-volume/persona-files1" + "/mnt/nfs-volume/persona-files2" + "/home/username" + ]; + secrets = { + restic-password = config.sops.secrets."backup/restic-password".path; + }; + }; }; } diff --git a/install.sh b/deploy.sh similarity index 100% rename from install.sh rename to deploy.sh diff --git a/generate-gpg-keys.sh b/generate-gpg-keys.sh new file mode 100755 index 0000000..376005e --- /dev/null +++ b/generate-gpg-keys.sh @@ -0,0 +1,36 @@ +#! /usr/bin/env nix-shell +#! nix-shell -i bash -p gnupg ssh-to-pgp + +## Import user SSH key into GPG + +cp ~/.ssh/id_rsa /tmp/id_rsa +ssh-keygen -p -N "" -f /tmp/id_rsa +{ + IFS=$'\n' read -r -d '' CAPTURED_STDERR; + IFS=$'\n' read -r -d '' CAPTURED_STDOUT; +} < <((printf '\0%s\0' "$(ssh-to-pgp -private-key -i /tmp/id_rsa | gpg --import --allow-non-selfsigned-uid --quiet)" 1>&2) 2>&1) +USER_GPG_FINGERPRINT=$(echo $CAPTURED_STDERR | awk '{print $1;}') +echo "FINGERPRINT: ${USER_GPG_FINGERPRINT}" +rm /tmp/id_rsa +# set ultimate trust level +echo "${USER_GPG_FINGERPRINT}:6:" | gpg --import-ownertrust +echo -e "adduid\n\n${USER}@localhost\n\nsave\nexit\n" | gpg --command-fd=0 --status-fd=1 --edit-key ${USER_GPG_FINGERPRINT} + +sed -i -e "s/\&user .\+$/\&user $USER_GPG_FINGERPRINT/g" .sops.yaml + +## Import host SSH key into GPG + +# Get GPG fingerprint of server RSA key +# HOST_GPG_FINGERPRINT=$(sudo cat /etc/ssh/ssh_host_rsa_key | ssh-to-pgp -private-key | gpg --import --allow-non-selfsigned-uid --quiet 2> /dev/null | head -n 1) +{ + IFS=$'\n' read -r -d '' CAPTURED_STDERR; + IFS=$'\n' read -r -d '' CAPTURED_STDOUT; +} < <((printf '\0%s\0' "$(sudo cat /etc/ssh/ssh_host_rsa_key | ssh-to-pgp -private-key | gpg --import --allow-non-selfsigned-uid --quiet)" 1>&2) 2>&1) +HOST_GPG_FINGERPRINT=$(echo $CAPTURED_STDERR | awk '{print $1;}') +echo "FINGERPRINT: ${HOST_GPG_FINGERPRINT}" +# set ultimate trust level +echo "${HOST_GPG_FINGERPRINT}:6:" | gpg --import-ownertrust +echo -e "adduid\n\n${USER}@localhost\n\nsave\nexit\n" | gpg --command-fd=0 --status-fd=1 --edit-key ${HOST_GPG_FINGERPRINT} + +sed -i -e "s/\&host_$HOST .\+$/\&host_$HOST $HOST_GPG_FINGERPRINT/g" .sops.yaml + diff --git a/secrets-unencrypted/authentik.yaml b/secrets-unencrypted/authentik.yaml new file mode 100644 index 0000000..59e8fe4 --- /dev/null +++ b/secrets-unencrypted/authentik.yaml @@ -0,0 +1,15 @@ + authentik: + postgres-password: + authentik-env: |- + AUTHENTIK_REDIS__HOST=localhost + AUTHENTIK_POSTGRESQL__HOST=localhost + AUTHENTIK_POSTGRESQL__USER=authentik + AUTHENTIK_POSTGRESQL__NAME=authentik + AUTHENTIK_POSTGRESQL__PASSWORD= + AUTHENTIK_SECRET_KEY= + AUTHENTIK_TOKEN= + authentik-ldap-env: |- + AUTHENTIK_HOST=http://localhost:9000 + AUTHENTIK_TOKEN= + AUTHENTIK_INSECURE=true + diff --git a/secrets-unencrypted/backup.yaml b/secrets-unencrypted/backup.yaml new file mode 100644 index 0000000..b22d337 --- /dev/null +++ b/secrets-unencrypted/backup.yaml @@ -0,0 +1,2 @@ +backup: + restic-password: diff --git a/secrets-unencrypted/ddclient.yaml b/secrets-unencrypted/ddclient.yaml new file mode 100644 index 0000000..50889d9 --- /dev/null +++ b/secrets-unencrypted/ddclient.yaml @@ -0,0 +1,2 @@ +ddclient: + ddclient-password: diff --git a/secrets-unencrypted/linkwarden.yaml b/secrets-unencrypted/linkwarden.yaml new file mode 100644 index 0000000..55d6bbd --- /dev/null +++ b/secrets-unencrypted/linkwarden.yaml @@ -0,0 +1,4 @@ +linkwarden: + env: |- + NEXTAUTH_SECRET= + POSTGRESQL_PASSWORD= diff --git a/secrets-unencrypted/nextcloud.yaml b/secrets-unencrypted/nextcloud.yaml new file mode 100644 index 0000000..65bae3d --- /dev/null +++ b/secrets-unencrypted/nextcloud.yaml @@ -0,0 +1,8 @@ +nextcloud: + admin-password: + secret-file: |- + { + "redis": { + "password": "secret" + } + } diff --git a/secrets-unencrypted/tailscale.yaml b/secrets-unencrypted/tailscale.yaml new file mode 100644 index 0000000..39a545d --- /dev/null +++ b/secrets-unencrypted/tailscale.yaml @@ -0,0 +1,2 @@ +tailscale: + key: diff --git a/secrets.nix b/secrets.nix new file mode 100644 index 0000000..dd056a3 --- /dev/null +++ b/secrets.nix @@ -0,0 +1,76 @@ +{ config, ... }: +{ + ## @TODO: What to do about owner field an restartUnits? + ## This file should probably be generated by the homefree repo + ## In fact everything in this repo should be generated by + ## the config editor in homefree repo. + sops.secrets = { + "authentik/authentik-env" = { + format = "yaml"; + sopsFile = ./secrets/authentik.yaml; + owner = config.homefree.system.adminUsername; + path = "/run/secrets/authentik/authentik-env"; + restartUnits = [ "authentik.service" ]; + }; + "authentik/authentik-ldap-env" = { + format = "yaml"; + sopsFile = ./secrets/authentik.yaml; + + owner = config.homefree.system.adminUsername; + path = "/run/secrets/authentik/authentik-ldap-env"; + restartUnits = [ "authentik-ldap.service" ]; + }; + "authentik/postgres-password" = { + format = "yaml"; + sopsFile = ./secrets/authentik.yaml; + }; + "backup/restic-password" = { + format = "yaml"; + sopsFile = ./secrets/backup.yaml; + + owner = config.homefree.system.adminUsername; + path = "/run/secrets/backup/restic-password"; + restartUnits = [ "restic.service" ]; + }; + "ddclient/ddclient-password" = { + format = "yaml"; + sopsFile = ./secrets/ddclient.yaml; + + owner = config.homefree.system.adminUsername; + path = "/run/secrets/ddclient/ddclient-password"; + restartUnits = [ "ddclient.service" ]; + }; + "linkwarden/env" = { + format = "yaml"; + sopsFile = ./secrets/linkwarden.yaml; + + owner = config.homefree.system.adminUsername; + path = "/run/secrets/linkwarden/env"; + restartUnits = [ "linkwarden.service" ]; + }; + "nextcloud/admin-password" = { + format = "yaml"; + sopsFile = ./secrets/nextcloud.yaml; + + owner = "nextcloud"; + path = "/run/secrets/nextcloud/admin-password"; + restartUnits = [ "nextcloud.service" ]; + }; + "nextcloud/secret-file" = { + format = "yaml"; + sopsFile = ./secrets/nextcloud.yaml; + + owner = "nextcloud"; + path = "/run/secrets/nextcloud/secret-file"; + restartUnits = [ "nextcloud.service" ]; + }; + "tailscale/key" = { + format = "yaml"; + sopsFile = ./secrets/tailscale.yaml; + + owner = config.homefree.system.adminUsername; + path = "/run/secrets/tailscale/key"; + restartUnits = [ "tailscale.service" ]; + }; + }; +} diff --git a/secrets/.gitignore b/secrets/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/secrets/README.md b/secrets/README.md new file mode 100644 index 0000000..1a1f7a1 --- /dev/null +++ b/secrets/README.md @@ -0,0 +1,22 @@ +Secrets config +-------------- + +1. Generate appropriate GPG keys. You will need a private SSH key at ~/.ssh/id_rsa + +``` +./generate-gpg-keys.sh +``` + +Create secrets file in this folder. Use the following commands: + +``` +sops authentik.yaml +sops backup.yaml +sops ddclient.yaml +sops linkwarden.yaml +sops nextcloud.yaml +sops tailscale.yaml +``` + +And copy the contents from the appropriate file in the `secrets-unencrypted` folder, changing +the values as required.