From bc8ad796dea448903f93fd21ffde0dece7fe0bab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Numbus?= Date: Mon, 23 Feb 2026 16:35:24 +0100 Subject: [PATCH] Lots of changes. Needs more work. --- deploy.conf | 29 +- deploy.sh | 545 +++++------------- flake.nix | 17 - frigate.nix | 97 ---- modules/default.nix | 7 - modules/services/adguard.nix | 0 modules/services/default.nix | 16 - modules/services/frigate.nix | 98 ---- modules/services/gitea.nix | 113 ---- modules/services/home-assistant.nix | 83 --- modules/services/immich.nix | 134 ----- modules/services/it-tools.nix | 77 --- modules/services/nextcloud.nix | 131 ----- modules/services/passbolt.nix | 129 ----- modules/services/pi-hole.nix | 106 ---- modules/services/traefik.nix | 64 -- templates/nix-config/configuration.nix | 168 +----- templates/nix-config/disks/boot-1.nix | 81 --- templates/nix-config/disks/boot-2.nix | 125 ---- templates/nix-config/disks/content.nix | 28 - templates/nix-config/disks/parity.nix | 28 - templates/nix-config/disks/pcr-check.nix | 124 ---- templates/nix-config/disks/snapraid.nix | 60 -- templates/nix-config/disks/spindown.nix | 25 - templates/nix-config/flake.nix | 19 +- templates/nix-config/misc/activation.nix | 129 ----- templates/nix-config/misc/mail.nix | 74 --- templates/nix-config/misc/networking.nix | 35 -- templates/nix-config/misc/smart.nix | 62 -- templates/nix-config/misc/terminal.nix | 43 -- templates/nix-config/podman/activation.nix | 0 templates/nix-config/podman/adguard.coming | 59 -- templates/nix-config/podman/frigate.nix | 98 ---- templates/nix-config/podman/gitea.nix | 113 ---- .../nix-config/podman/home-assistant.nix | 83 --- templates/nix-config/podman/immich.nix | 134 ----- templates/nix-config/podman/it-tools.nix | 77 --- templates/nix-config/podman/nextcloud-aio.nix | 98 ---- templates/nix-config/podman/nextcloud.nix | 131 ----- templates/nix-config/podman/passbolt.nix | 129 ----- templates/nix-config/podman/pi-hole.nix | 106 ---- templates/nix-config/podman/traefik.nix | 64 -- templates/nix-config/sops-nix/secrets.yaml | 81 +-- templates/podman-config/frigate/config.yaml | 70 --- .../home-assistant/mosquitto.conf | 8 - templates/podman-config/traefik/headers.yaml | 20 - .../podman-config/traefik/nextcloud.yaml | 41 -- templates/podman-config/traefik/tls.yaml | 12 - templates/podman-config/traefik/traefik.yaml | 53 -- templates/post-install/numbus-server.conf | 25 - templates/post-install/numbus-server.sh | 220 ------- 51 files changed, 186 insertions(+), 4083 deletions(-) delete mode 100644 flake.nix delete mode 100644 frigate.nix delete mode 100644 modules/default.nix delete mode 100644 modules/services/adguard.nix delete mode 100644 modules/services/default.nix delete mode 100644 modules/services/frigate.nix delete mode 100644 modules/services/gitea.nix delete mode 100644 modules/services/home-assistant.nix delete mode 100644 modules/services/immich.nix delete mode 100644 modules/services/it-tools.nix delete mode 100644 modules/services/nextcloud.nix delete mode 100644 modules/services/passbolt.nix delete mode 100644 modules/services/pi-hole.nix delete mode 100644 modules/services/traefik.nix delete mode 100644 templates/nix-config/disks/boot-1.nix delete mode 100644 templates/nix-config/disks/boot-2.nix delete mode 100644 templates/nix-config/disks/content.nix delete mode 100644 templates/nix-config/disks/parity.nix delete mode 100644 templates/nix-config/disks/pcr-check.nix delete mode 100644 templates/nix-config/disks/snapraid.nix delete mode 100644 templates/nix-config/disks/spindown.nix delete mode 100644 templates/nix-config/misc/activation.nix delete mode 100644 templates/nix-config/misc/mail.nix delete mode 100644 templates/nix-config/misc/networking.nix delete mode 100644 templates/nix-config/misc/smart.nix delete mode 100644 templates/nix-config/misc/terminal.nix delete mode 100644 templates/nix-config/podman/activation.nix delete mode 100644 templates/nix-config/podman/adguard.coming delete mode 100644 templates/nix-config/podman/frigate.nix delete mode 100644 templates/nix-config/podman/gitea.nix delete mode 100644 templates/nix-config/podman/home-assistant.nix delete mode 100644 templates/nix-config/podman/immich.nix delete mode 100644 templates/nix-config/podman/it-tools.nix delete mode 100644 templates/nix-config/podman/nextcloud-aio.nix delete mode 100644 templates/nix-config/podman/nextcloud.nix delete mode 100644 templates/nix-config/podman/passbolt.nix delete mode 100644 templates/nix-config/podman/pi-hole.nix delete mode 100644 templates/nix-config/podman/traefik.nix delete mode 100644 templates/podman-config/frigate/config.yaml delete mode 100644 templates/podman-config/home-assistant/mosquitto.conf delete mode 100644 templates/podman-config/traefik/headers.yaml delete mode 100644 templates/podman-config/traefik/nextcloud.yaml delete mode 100644 templates/podman-config/traefik/tls.yaml delete mode 100644 templates/podman-config/traefik/traefik.yaml delete mode 100644 templates/post-install/numbus-server.conf delete mode 100644 templates/post-install/numbus-server.sh diff --git a/deploy.conf b/deploy.conf index 44314ca..01f2bc7 100644 --- a/deploy.conf +++ b/deploy.conf @@ -1,28 +1,33 @@ # SCRIPT SETTINGS export DEBUG="true" -#TARGET SETTINGS -export TARGET_HOST="192.168.1.10" -export REMOTE_PASS="example" -export SSH_PUBLIC_KEY="ssh-ed25519 AAAAoefzefpoipoeCEZJCPEACPAcjapjcpajepcjAPJECJPEJAPJAZ yours@yourdomain.com" +#LIVE TARGET SETTINGS +export LIVE_TARGET_IP="192.168.1.10" +export LIVE_TARGET_PASSWD="example" + +#SERVER SETTINGS +export TIMEZONE="Europe/Paris" export SERVER_OWNER_NAME="yourName" +export SERVER_USER_EMAIL="user@your-domain.com" +export SERVER_ADMIN_EMAIL="admin@your-domain.com" +export AUTHORIZED_SSH_PUBLIC_KEY=( "ssh-ed25519 AAAAoefzefpoipoeCEZJCPEACPAcjapjcpajepcjAPJECJPEJAPJAZ yours@yourdomain.com" ) # TRAEFIK SETTINGS export DOMAIN_NAME="yourdomain.com" -export EMAIL_ADDRESS="your-mail@yourdomain.com" -export CF_DNS_API_TOKEN="yourToken" +export CLOUDFLARE_DNS_API_TOKEN="yourToken" # SMTP SETTINGS -export SENDER_EMAIL_ADDRESS="youraddress@gmail.com" -export SENDER_EMAIL_ADDRESS_PASSWORD="emrp raps vzoi vnoe" -export SENDER_EMAIL_DOMAIN="smtp.yourdomain.com" -export SENDER_EMAIL_PORT="587" +export SMTP_SERVER_USERNAME="your-address@gmail.com" +export SMTP_SERVER_PASSWORD="emrp raps vzoi vnoe" +export SMTP_SERVER_HOST="smtp.yourdomain.com" +export SMTP_SERVER_PORT="587" #NETWORK SETTINGS -export HOME_ROUTER_SUBNET="192.168.1.0/24" -export HOME_ROUTER_IP="192.168.1.1" +export NETWORK_SUBNET="192.168.1.0/24" +export NETWORK_ROUTER_IP="192.168.1.1" export HOME_SERVER_IP="192.168.1.5" # SERVICES SETTINGS +export SELECTED_DNS_SERVICE="pi-hole" # or adguard export SELECTED_SERVICES=( "frigate" "gitea" "home-assistant" "immich" "it-tools" \ "nextcloud" "passbolt" "pi-hole" "virtualization" ) diff --git a/deploy.sh b/deploy.sh index e7d515b..1c9632d 100644 --- a/deploy.sh +++ b/deploy.sh @@ -7,10 +7,12 @@ export GUM_SPIN_SPINNER_BOLD=true export GUM_SPIN_SHOW_ERROR=true export GUM_SPIN_TITLE_BOLD=true -NECESSARY_VARIABLES_LIST=( "TARGET_HOST" "REMOTE_PASS" "SSH_PUBLIC_KEY" "DOMAIN_NAME" \ -"EMAIL_ADDRESS" "CF_DNS_API_TOKEN" "SENDER_EMAIL_ADDRESS" "SENDER_EMAIL_ADDRESS_PASSWORD" \ -"SENDER_EMAIL_DOMAIN" "SENDER_EMAIL_PORT" "SERVER_OWNER_NAME" "SELECTED_SERVICES" \ -"HOME_ROUTER_SUBNET" "HOME_ROUTER_IP" "HOME_SERVER_IP" ) +NECESSARY_VARIABLES_LIST=( LIVE_TARGET_IP LIVE_TARGET_PASSWD \ +SERVER_OWNER_NAME SERVER_USER_EMAIL SERVER_ADMIN_EMAIL AUTHORIZED_SSH_PUBLIC_KEY \ +DOMAIN_NAME CLOUDFLARE_DNS_API_TOKEN \ +SMTP_SERVER_USERNAME SMTP_SERVER_PASSWORD SMTP_SERVER_HOST SMTP_SERVER_PORT \ +NETWORK_SUBNET NETWORK_ROUTER_IP HOME_SERVER_IP) + ### Default settings <-- user_input() { @@ -44,8 +46,8 @@ user_input() { strictly_necessary_information() { export IP_REGEX='^([0-9]{1,3}\.){3}[0-9]{1,3}$' - user_input "TARGET_HOST" " Please provide the IP address of the target host :" "For example : 192.168.1.100" "${IP_REGEX}" "Invalid IP address format." - user_input "REMOTE_PASS" " Please enter the password for '${TARGET_USER}@${TARGET_HOST}' :" "${TARGET_HOST}'s password" "" "" "true" + user_input "LIVE_TARGET_IP" " Please provide the IP address of the target host :" "For example : 192.168.1.100" "${IP_REGEX}" "Invalid IP address format." + user_input "LIVE_TARGET_PASSWD" " Please enter the password for '${TARGET_USER}@${LIVE_TARGET_IP}' :" "${LIVE_TARGET_IP}'s password" "" "" "true" } necessary_information() { @@ -57,29 +59,34 @@ necessary_information() { local SSH_KEY_REGEX='^ssh-[a-z0-9]+ [A-Za-z0-9+/]+.*' echo -e "\n\n➡️ This script needs information about the target you want to install NixOS on\n" - #TARGET SETTINGS - user_input "TARGET_HOST" " Please provide the IP address of the target host :" "For example : 192.168.1.100" "${IP_REGEX}" "Invalid IP address format." - user_input "REMOTE_PASS" " Please enter the password for '${TARGET_USER}@${TARGET_HOST}' :" "${TARGET_HOST}'s password" "" "" "true" - user_input "SSH_PUBLIC_KEY" " Please provide the public SSH key of an authorized device :" "For example : ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGhcYDmjMo5YApLkk/3P3HZCnOSzm0uYewNAbxL8Fci8 user@your-pc" "${SSH_KEY_REGEX}" "Invalid SSH key format (must start with ssh-...)." "true" + # LIVE TARGET SETTINGS + user_input "LIVE_TARGET_IP" " Please provide the IP address of the target host :" "For example : 192.168.1.100" "${IP_REGEX}" "Invalid IP address format." + user_input "LIVE_TARGET_PASSWD" " Please enter the password for '${TARGET_USER}@${LIVE_TARGET_IP}' :" "${LIVE_TARGET_IP}'s password" "" "" "true" + + echo -e "\n\n➡️ Now provide some information about the server you are deploying\n" + # SERVER SETTINGS + user_input "TIMEZONE" " Please provide the wanted timezone :" "For example : Europe/Paris, Europe/Berlin" "" "" + user_input "SERVER_OWNER_NAME" " Please provide the name of the owner of this server :" "For example : Steve" "" "" + user_input "SERVER_USER_EMAIL" " Please provide a valid user email address (to stay informed about your server's health) :" "For example : myemail@gmail.com" "${EMAIL_REGEX}" "Invalid email address format." + user_input "SERVER_ADMIN_EMAIL" " Please provide a valid admin email address (will be used for ACME, and system failures notifications) :" "For example : myemail@gmail.com" "${EMAIL_REGEX}" "Invalid email address format." + user_input "AUTHORIZED_SSH_PUBLIC_KEY" " Please provide a list of SSH public keys of authorized devices :" "For example : ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGhcYDmjMo5YApLkk/3P3HZCnOSzm0uYewNAbxL8Fci8 user@your-pc" "${SSH_KEY_REGEX}" "Invalid SSH key format (must start with ssh-...)." "true" echo -e "\n\n➡️ You will access your services via a domain name (e.g. cloud.mydomain.com) and containers need credentials to create those subdomains\n" # TRAEFIK SETTINGS user_input "DOMAIN_NAME" " Please provide the domain name (FQDN) your home server will use :" "For example : yourdomain.com" "${DOMAIN_REGEX}" "Invalid domain name format." - user_input "EMAIL_ADDRESS" " Please provide a valid email address (will be used for ACME, and your services) :" "For example : myemail@gmail.com" "${EMAIL_REGEX}" "Invalid email address format." - user_input "CF_DNS_API_TOKEN" " Please provide a cloudflare API token with DNS zone permission :" "For example : bA7hdvCOuXGytlNKohi3ZGtlVpf5CHpLuCMiJrE" "" "" "true" - user_input "SERVER_OWNER_NAME" " Please provide the name of the server owner :" "For example : Steve" "" "" + user_input "CLOUDFLARE_DNS_API_TOKEN" " Please provide a cloudflare API token with DNS zone permission :" "For example : bA7hdvCOuXGytlNKohi3ZGtlVpf5CHpLuCMiJrE" "" "" "true" echo -e "\n\n➡️ Some services will be able to send you emails. For that you need an email that supports sending emails (like Gmail for example)\n" # SMTP SETTINGS - user_input "SENDER_EMAIL_ADDRESS" " Please provide a valid sender email address :" "For example : myemail@gmail.com" "${EMAIL_REGEX}" "Invalid email address format." - user_input "SENDER_EMAIL_ADDRESS_PASSWORD" " Please provide the password of this email address :" "abcd efgh ijkl mnop" "" "" "true" - user_input "SENDER_EMAIL_DOMAIN" " Please provide the SMTP server endpoint :" "For Gmail : smtp.gmail.com" "${DOMAIN_REGEX}" "Invalid domain name format." - user_input "SENDER_EMAIL_PORT" " Please provide the smtp TLS port :" "For Gmail : 587" "${PORT_REGEX}" "Invalid port number." + user_input "SMTP_SERVER_USERNAME" " Please provide a valid sender email address :" "For example : myemail@gmail.com" "${EMAIL_REGEX}" "Invalid email address format." + user_input "SMTP_SERVER_PASSWORD" " Please provide the password of this email address :" "abcd efgh ijkl mnop" "" "" "true" + user_input "SMTP_SERVER_HOST" " Please provide the SMTP server endpoint :" "For Gmail : smtp.gmail.com" "${DOMAIN_REGEX}" "Invalid domain name format." + user_input "SMTP_SERVER_PORT" " Please provide the smtp TLS port :" "For Gmail : 587" "${PORT_REGEX}" "Invalid port number." echo -e "\n\n➡️ This server will connect to your local network and you will configure its IP address\n" # NETWORK SETTINGS - user_input "HOME_ROUTER_SUBNET" " Please provide your home network subnet :" "For example 192.168.1.0/24" "${SUBNET_REGEX}" "Invalid subnet format (e.g. 192.168.1.1/24)." - user_input "HOME_ROUTER_IP" " Please provide the ip address of your router :" "Most likely 192.168.1.1 or 192.168.1.254" "${IP_REGEX}" "Invalid IP address format." + user_input "NETWORK_SUBNET" " Please provide your network subnet :" "For example 192.168.1.0/24" "${SUBNET_REGEX}" "Invalid subnet format (e.g. 192.168.1.1/24)." + user_input "NETWORK_ROUTER_IP" " Please provide the ip address of your router :" "Most likely 192.168.1.1 or 192.168.1.254" "${IP_REGEX}" "Invalid IP address format." user_input "HOME_SERVER_IP" " Please choose the ip address that your server will use (i.e. any address in the 192.168.1.1/24 range that is not in use.) :" "For example 192.168.1.5" "${IP_REGEX}" "Invalid IP address format." } @@ -113,11 +120,6 @@ necessary_information_config() { fi } -more_information_config() { - sshpass -p "${REMOTE_PASS}" scp ${TARGET_USER}@${TARGET_HOST}:/etc/numbus-server/numbus-server.conf . - source "numbus-server.conf" -} - setup_ssh() { mkdir -p final-nix-config/ mkdir -p final-nix-config/etc/ @@ -130,8 +132,8 @@ setup_ssh() { chmod 700 final-nix-config/home/numbus-admin/.ssh/ ssh-keygen -t "ed25519" -C "numbus-admin@numbus-server" -f "final-nix-config/home/numbus-admin/.ssh/id_ed25519" -N "" -q - echo -e "\n\n➡️ Copying SSH key to target host '${TARGET_USER}@${TARGET_HOST}'..." - if sshpass -p "${REMOTE_PASS}" ssh-copy-id -o StrictHostKeyChecking=no -i "final-nix-config/home/numbus-admin/.ssh/id_ed25519" "${TARGET_USER}@${TARGET_HOST}"; then + echo -e "\n\n➡️ Copying SSH key to target host '${TARGET_USER}@${LIVE_TARGET_IP}'..." + if sshpass -p "${LIVE_TARGET_PASSWD}" ssh-copy-id -o StrictHostKeyChecking=no -i "final-nix-config/home/numbus-admin/.ssh/id_ed25519" "${TARGET_USER}@${LIVE_TARGET_IP}"; then echo -e "\n✅ SSH key copied successfully" else echo -e "\n❌ Failed to copy SSH key. Please check the host IP and password." @@ -141,7 +143,18 @@ setup_ssh() { ssh_to_host() { local COMMAND="${1}" - ssh -i "final-nix-config/home/numbus-admin/.ssh/id_ed25519" "${TARGET_USER}@${TARGET_HOST}" "${COMMAND}" + ssh -i "final-nix-config/home/numbus-admin/.ssh/id_ed25519" "${TARGET_USER}@${LIVE_TARGET_IP}" "${COMMAND}" +} + +hierarchy_preparation() { + mkdir -p /final-nix-config/ + mkdir -p /final-nix-config/etc + mkdir -p /final-nix-config/etc/nixos + mkdir -p /final-nix-config/etc/nixos/secrets + + echo -e "\n ✅ Writing configuration..." + cp -${FILES_COPY_FLAGS} templates/nix-config/configuration.nix final-nix-config/etc/nixos/configuration.nix + export CONFIGURATION_PATH="final-nix-config/etc/nixos/configuration.nix" } hardware_detection() { @@ -196,7 +209,7 @@ for DISK in \$(lsblk -x SIZE -d -n -e 7,11 -o NAME); do fi # Disk health - if [[ \$(echo "$REMOTE_PASS" | sudo -S smartctl -H /dev/\$DISK 2>/dev/null | grep 'self-assessment' | awk '{print \$6}') == "PASSED" ]]; then + if [[ \$(echo "$LIVE_TARGET_PASSWD" | sudo -S smartctl -H /dev/\$DISK 2>/dev/null | grep 'self-assessment' | awk '{print \$6}') == "PASSED" ]]; then DISK_HEALTH+=("PASSED") else DISK_HEALTH+=("N/A") @@ -232,7 +245,7 @@ done SSHEND ### Get hardware information <-- - scp -i "final-nix-config/home/numbus-admin/.ssh/id_ed25519" "${TARGET_USER}@${TARGET_HOST}":"${TMPFILE}" "${TMPFILE}" &> /dev/null + scp -i "final-nix-config/home/numbus-admin/.ssh/id_ed25519" "${TARGET_USER}@${LIVE_TARGET_IP}":"${TMPFILE}" "${TMPFILE}" &> /dev/null source "${TMPFILE}" && rm -rf "${TMPFILE}" ### --> Generate hardware-configuration.nix @@ -248,34 +261,46 @@ SSHEND services_selection() { echo -e "\n\n ➡️ You will now select the services you want installed on your server:" + local AVAILABLE_DNS_SERVICES=( "pi-hole" "adguard" ) + local AVAILABLE_SERVICES=( "frigate" "gitea" "home-assistant" "immich" "it-tools" \ "nextcloud" "passbolt" "virtualization" ) - local SERVICES_DESCRIPTION=( "Pi-Hole [Always included] : Block ads on all your devices" \ - "Immich : Pictures and videos backup with local machine-learning" \ + local DNS_SERVICES_DESCRIPTION=( "Pi-Hole : Simple open-source DNS black hole" \ + "AdGuard " : Feature rich DNS service ) + + local SERVICES_DESCRIPTION=( "Immich : Pictures and videos backup with local machine-learning" \ "Nextcloud : No fuss Office 365 replacement" \ "Passbolt: Security-first password manager with collaboration features" \ "Home-Assistant : Manage your smart home and security cameras" \ "Frigate [Home Assistant required] : Secure your house with security cameras" \ "Gitea : Your own git platform" \ "IT-tools : A set of useful tools when doing IT" \ - "Virtualization : Run Virtual Machines (KVM/QEMU) with Libvirt" - ) + "Virtualization : Run Virtual Machines (KVM/QEMU) with Libvirt" ) SELECTED_SERVICES=() local SELECTED_SERVICES_DESCRIPTION=$(gum choose --no-limit --header "Homelab services:" "${SERVICES_DESCRIPTION[@]}") + SELECTED_DNS_SERVICE="" + local SELECTED_DNS_SERVICE_DESCRIPTION=$(gum choose --no-limit --header "Homelab services:" "${DNS_SERVICES_DESCRIPTION[@]}") + for i in ${!AVAILABLE_SERVICES[@]}; do if printf '%s' "${SELECTED_SERVICES_DESCRIPTION}" | grep -iq "${AVAILABLE_SERVICES[${i}]}"; then SELECTED_SERVICES+=("${AVAILABLE_SERVICES[${i}]}") fi done + for i in ${!AVAILABLE_DNS_SERVICES[@]}; do + if printf '%s' "${SELECTED_DNS_SERVICE_DESCRIPTION}" | grep -iq "${AVAILABLE_DNS_SERVICES[${i}]}"; then + SELECTED_DNS_SERVICE="${AVAILABLE_DNS_SERVICES[${i}]}" + fi + done + export SELECTED_SERVICES + export SELECTED_DNS_SERVICE } disks_selection() { -### --> Disk wiping warning gum style --border normal --margin "1" --padding "1 2" --border-foreground 212 " ⚠️ $(gum style --foreground 212 'WARNING:') You will choose the disks to install NixOS on. !! PLEASE MAKE SURE YOU BACKED UP ANY IMPORTANT DATA !! @@ -285,9 +310,7 @@ disks_selection() { gum confirm "Do you understand and wish to proceed?" || { echo -e "\n\n ❌ Aborting as requested."; exit 1; } echo -e "\n\n 🔎 Fetching and analyzing disks from target host... (This may take a moment)" -### Disk wiping warning <-- -### --> Disk selection if [[ "${#DISK_NAME[@]}" -eq 0 ]]; then echo -e "\n ❌ No disks found on the target host. Aborting." exit 1 @@ -307,46 +330,19 @@ disks_selection() { local SELECTED_BOOT_DISK=$(gum choose --limit 2 --header "${HEADER}" "${GUM_PRINTED_ELEMENTS[@]}") - BOOT_DISKS_ID=() - BOOT_DISKS_NAME=() for i in ${!DISK_NAME[@]}; do if printf '%s' "$SELECTED_BOOT_DISK" | grep -iqw "${DISK_NAME[${i}]}"; then - BOOT_DISKS_ID+=("${DISK_ID[${i}]:-${DISK_DEVPATH[${i}]}}") + BOOT_DISKS_ID_LIST+=("${DISK_ID[${i}]:-${DISK_DEVPATH[${i}]}}") BOOT_DISKS_NAME+=("${DISK_NAME[${i}]}") unset "GUM_PRINTED_ELEMENTS[${i}]" fi done - if [[ "${#BOOT_DISKS_ID[@]}" -eq 0 ]]; then - echo -e "\n\n ❌ No boot disk selected. Aborting." - exit 1 - elif [[ "${#BOOT_DISKS_ID[@]}" -eq 1 ]]; then - echo -e "\n\n ⚠️ One boot disk selected, continuing with striped boot disk configuration." - echo -e "Consider using 2 boot disks instead to get data protection features on the boot disks." - export BOOT_DISK_1_ID="${BOOT_DISKS_ID[0]}" - export BOOT_DISK_1_NAME="${BOOT_DISKS_NAME[0]}" - export BOOT_DISK_2_NAME="" - elif [[ "${#BOOT_DISKS_ID[@]}" -eq 2 ]]; then - echo -e "\n\n ✅ Two boot disks selected, continuing with mirrored boot disks configuration." - echo -e "\n\n ⚠️ If the two disks are different sizes, the resulting usable space size will be \ - the one of the smallest disk." - export BOOT_DISK_1_ID="${BOOT_DISKS_ID[0]}" - export BOOT_DISK_2_ID="${BOOT_DISKS_ID[1]}" - export BOOT_DISK_1_NAME="${BOOT_DISKS_NAME[0]}" - export BOOT_DISK_2_NAME="${BOOT_DISKS_NAME[1]}" - else - echo -e "\n\n ❌ Unexpected bug. Please contact the developer. Aborting." - exit 1 - fi - echo "" gum style --foreground 212 "➡️ Please choose data and parity disks (up to 9 total) :" local SELECTED_DATA_DISK=$(gum choose --limit 9 --header "$HEADER" "${GUM_PRINTED_ELEMENTS[@]}") -### Disk selection <-- - DATA_DISKS_ID=() - DATA_DISKS_TYPE=() for i in ${!DISK_NAME[@]}; do if printf '%s' "$SELECTED_DATA_DISK" | grep -iq "${DISK_NAME[${i}]}"; then DATA_DISKS_ID+=("${DISK_ID[${i}]:-${DISK_DEVPATH[${i}]}}") @@ -357,280 +353,88 @@ disks_selection() { if [[ "${#DATA_DISKS_ID[@]}" -eq 1 ]]; then export PARITY_DISK_NUMBER=0 export CONTENT_DISK_NUMBER=1 + export PARITY_DISK_NUMBER_LIST=() + export CONTENT_DISK_NUMBER_LIST=("${#DATA_DISKS_ID[0]}") else export PARITY_DISK_NUMBER=$(((${#DATA_DISKS_ID[@]} + 2) / 3)) export CONTENT_DISK_NUMBER=$((${#DATA_DISKS_ID[@]} - PARITY_DISK_NUMBER)) + for i in $(seq 0 $(($CONTENT_DISK_NUMBER - 1))); do + CONTENT_DISK_NUMBER_LIST+=("${#DATA_DISKS_ID[${i}]}") + done + for i in $(seq $CONTENT_DISK_NUMBER $((${#DATA_DISKS_ID[@]} - 1))); do + PARITY_DISK_NUMBER_LIST+=("${#DATA_DISKS_ID[${i}]}") + done fi - export DATA_DISKS_ID - export DATA_DISKS_TYPE -} - -folder_tree_generation() { - mkdir -p final-nix-config/mnt/ - mkdir -p final-nix-config/mnt/config/ - mkdir -p final-nix-config/mnt/data/ - - mkdir -p final-nix-config/mnt/config/traefik/ - mkdir -p final-nix-config/mnt/config/traefik/rules/ - mkdir -p final-nix-config/mnt/config/traefik/certs/ - - mkdir -p final-nix-config/etc/secrets/ - mkdir -p final-nix-config/etc/secrets/disks/ - mkdir -p final-nix-config/etc/numbus-server/ - mkdir -p final-nix-config/etc/nixos/misc/ - mkdir -p final-nix-config/etc/nixos/disks/ - mkdir -p final-nix-config/etc/nixos/pcie-coral/ - mkdir -p final-nix-config/etc/nixos/podman/ - mkdir -p final-nix-config/etc/nixos/secrets/ - - mkdir -p final-nix-config/var/ - mkdir -p final-nix-config/var/lib/ - mkdir -p final-nix-config/var/lib/sops-nix -} - -services_generation() { - generate_db_creds() { - local SERVICE_UPPER="${1}" - export "${SERVICE_UPPER}_DB_NAME"="$(xkcdpass -d "-" -n 2)" - export "${SERVICE_UPPER}_DB_USERNAME"="$(xkcdpass -d "-" -n 2)" - export "${SERVICE_UPPER}_DB_PASSWORD"="$(xkcdpass -d "-")" - } - - generate_network() { - local SERVICE="${1}" - local HAS_BACKEND="${2:-0}" - local NETWORK_NAME_OVERRIDE="${3:-}" - - if [[ -z "${NETWORK_NAME_OVERRIDE}" ]]; then - NETWORK_ID=$((NETWORK_ID + 1)) - PODMAN_NETWORKS+=" sudo -u numbus-admin podman network exists \"${SERVICE}_frontend\" || sudo -u numbus-admin podman network create --driver=\"bridge\" --subnet=\"10.89.${NETWORK_ID}.0/24\" --ip-range=\"10.89.${NETWORK_ID}.0/24\" --gateway=\"10.89.${NETWORK_ID}.254\" \"${SERVICE}_frontend\""$'\n' - TRAEFIK_NETWORKS+=" ${SERVICE}_frontend:"$'\n' - TRAEFIK_NETWORKS+=" ipv4_address: 10.89.${NETWORK_ID}.253"$'\n' - TRAEFIK_REF_NETWORKS+=" ${SERVICE}_frontend:"$'\n' - TRAEFIK_REF_NETWORKS+=" external: true"$'\n' - - if [[ "${HAS_BACKEND}" == "1" ]]; then - NETWORK_ID=$((NETWORK_ID + 1)) - PODMAN_NETWORKS+=" sudo -u numbus-admin podman network exists \"${SERVICE}_backend\" || sudo -u numbus-admin podman network create --driver=\"bridge\" --subnet=\"10.89.${NETWORK_ID}.0/24\" --ip-range=\"10.89.${NETWORK_ID}.0/24\" --gateway=\"10.89.${NETWORK_ID}.254\" \"${SERVICE}_backend\""$'\n' - SERVICES_NETWORK_IDS+=("$(( ${NETWORK_ID} - 1 )),${NETWORK_ID}:${SERVICE}") - else - SERVICES_NETWORK_IDS+=("${NETWORK_ID}:${SERVICE}") - fi - else - NETWORK_ID=$((NETWORK_ID + 1)) - PODMAN_NETWORKS+=" sudo -u numbus-admin podman network exists \"${NETWORK_NAME_OVERRIDE}\" || sudo -u numbus-admin podman network create --driver=\"bridge\" --subnet=\"10.89.${NETWORK_ID}.0/24\" --ip-range=\"10.89.${NETWORK_ID}.0/24\" --gateway=\"10.89.${NETWORK_ID}.254\" \"${NETWORK_NAME_OVERRIDE}\""$'\n' - TRAEFIK_NETWORKS+=" ${NETWORK_NAME_OVERRIDE}:"$'\n' - TRAEFIK_NETWORKS+=" ipv4_address: 10.89.${NETWORK_ID}.253"$'\n' - TRAEFIK_REF_NETWORKS+=" ${NETWORK_NAME_OVERRIDE}:"$'\n' - TRAEFIK_REF_NETWORKS+=" external: true"$'\n' - SERVICES_NETWORK_IDS+=("${NETWORK_ID}:${SERVICE}") - fi - - export NETWORK_ID - export PODMAN_NETWORKS - export TRAEFIK_NETWORKS - export TRAEFIK_REF_NETWORKS - export SERVICES_NETWORK_IDS - } - - NETWORK_ID=0 - PODMAN_NETWORKS="" - TRAEFIK_NETWORKS="" - TRAEFIK_REF_NETWORKS="" - SERVICES_NETWORK_IDS=() - - echo -e "\n ✅ Writing configuration files for the selected homelab services..." - cp -${FILES_COPY_FLAGS} templates/nix-config/configuration.nix final-nix-config/etc/nixos/configuration.nix - cp -${FILES_COPY_FLAGS} templates/nix-config/podman/traefik.nix final-nix-config/etc/nixos/podman/traefik.nix - cp -${FILES_COPY_FLAGS} templates/nix-config/podman/pi-hole.nix final-nix-config/etc/nixos/podman/pi-hole.nix - envsubst < templates/podman-config/traefik/traefik.yaml > final-nix-config/mnt/config/traefik/traefik.yaml - generate_network "pi-hole" - export FTLCONF_WEBSERVER_PASSWORD="$(xkcdpass -d "-")" - - for service in "${SELECTED_SERVICES[@]}"; do - # Copy podman container file - [[ "${service}" != "virtualization" ]] && cp -${FILES_COPY_FLAGS} templates/nix-config/podman/"${service}".nix final-nix-config/etc/nixos/podman/"${service}".nix - - # Frigate config - if [[ "${service}" == "frigate" ]]; then - local FRIGATE_DEVICES_BLOCK="" - [[ "${TARGET_GRAPHICS_RENDERER}" == "true" ]] && FRIGATE_DEVICES_BLOCK+=" - /dev/dri:/dev/dri\n" - [[ "${TARGET_USB_CORAL}" == "true" ]] && FRIGATE_DEVICES_BLOCK+=" - /dev/bus/usb:/dev/bus/usb\n" - if [[ "${TARGET_PCIE_CORAL}" == "true" ]]; then - FRIGATE_DEVICES_BLOCK+=" - /dev/apex_0:/dev/apex_0\n" - sed -i "s|# ./pcie-coral/coral.nix| ./pcie-coral/coral.nix|" final-nix-config/etc/nixos/configuration.nix - cp -${FILES_COPY_FLAGS} templates/nix-config/pcie-coral/* final-nix-config/etc/nixos/pcie-coral/ - fi - if [[ -n "${FRIGATE_DEVICES_BLOCK}" ]]; then - local REPLACEMENT="devices:\n${FRIGATE_DEVICES_BLOCK%\\n}" - sed -i "s|# --- frigate devices --- #|$REPLACEMENT|" final-nix-config/etc/nixos/podman/frigate.nix - fi - - # Gitea config - elif [[ "${service}" == "gitea" ]]; then - generate_network "${service}" "1" - generate_db_creds "GITEA" - - # Home Assistant config - elif [[ "${service}" == "home-assistant" ]]; then - generate_network "${service}" "1" - if [[ -n "${TARGET_ZIGBEE_DEVICE}" ]]; then - local REPLACEMENT="devices:\n - /dev/serial/by-id/${TARGET_ZIGBEE_DEVICE}:/dev/ttyUSB0" - sed -i "s|# --- home-assistant devices --- #|$REPLACEMENT|" final-nix-config/etc/nixos/podman/home-assistant.nix - fi - export HOME_ASSISTANT_MQTT_USER="$(xkcdpass -d "-" -n 2)" - export HOME_ASSISTANT_MQTT_PASSWORD="$(xkcdpass -d "-")" - mkdir -p final-nix-config/mnt/config/mqtt/ - envsubst < templates/podman-config/home-assistant/mosquitto.conf > final-nix-config/mnt/config/mqtt/mosquitto.conf - touch final-nix-config/mnt/config/mqtt/password.txt - chmod 0700 final-nix-config/mnt/config/mqtt/password.txt - mosquitto_passwd -b final-nix-config/mnt/config/mqtt/password.txt "$HOME_ASSISTANT_MQTT_USER" "$HOME_ASSISTANT_MQTT_PASSWORD" - - # Immich config - elif [[ "${service}" == "immich" ]]; then - generate_network "${service}" "1" - generate_db_creds "IMMICH" - local IMMICH_DEVICES_BLOCK="" - if [[ "$TARGET_GRAPHICS_RENDERER" == "true" ]]; then - IMMICH_DEVICES_BLOCK+=" - /dev/dri:/dev/dri\n" - fi - if [[ -n "$IMMICH_DEVICES_BLOCK" ]]; then - local REPLACEMENT="devices:\n${IMMICH_DEVICES_BLOCK%\\n}" - sed -i "s|# --- immich devices --- #|$REPLACEMENT|" final-nix-config/etc/nixos/podman/immich.nix - fi - - # Nextcloud config - elif [[ "${service}" == "nextcloud" ]]; then - generate_network "${service}" "1" - generate_db_creds "NEXTCLOUD" - export "NEXTCLOUD_REDIS_PASSWORD"="$(xkcdpass -d "-")" -# envsubst < templates/podman-config/traefik/nextcloud.yaml > final-nix-config/mnt/config/traefik/rules/nextcloud.yaml - - # Passbolt config - elif [[ "${service}" == "passbolt" ]]; then - generate_network "${service}" "1" - generate_db_creds "PASSBOLT" - envsubst < templates/podman-config/traefik/headers.yaml > final-nix-config/mnt/config/traefik/rules/headers.yaml - envsubst < templates/podman-config/traefik/tls.yaml > final-nix-config/mnt/config/traefik/rules/tls.yaml - - # Virtualization config - elif [[ "${service}" == "virtualization" ]]; then - sed -i "s|# virtualisation.libvirtd.enable = true;| virtualisation.libvirtd.enable = true;|" final-nix-config/etc/nixos/configuration.nix - sed -i "s|# programs.virt-manager.enable = true;| programs.virt-manager.enable = true;|" final-nix-config/etc/nixos/configuration.nix - sed -i 's|extraGroups = \[ "wheel" \];|extraGroups = [ "wheel" "libvirtd" ];|' final-nix-config/etc/nixos/configuration.nix - - # Other podman containers with no special configuration - else - generate_network "${service}" - fi - done - - export PODMAN_NETWORKS - export TRAEFIK_NETWORKS - export TRAEFIK_REF_NETWORKS -} - -disks_generation() { - # Boot disk(s) - echo -e "\n\n ✅ Generating disko configuration from templates..." - local TEMPLATE_FILE="templates/nix-config/disks/boot-${#BOOT_DISKS_ID[@]}.nix" - (envsubst < "$TEMPLATE_FILE") > final-nix-config/etc/nixos/disks/disko.nix - - SNAPRAID_CONTENT_FILES="" - SNAPRAID_DATA_DISKS="" - SNAPRAID_PARITY_FILES="" - MOUNT_DEPENDENCIES_START="" - MOUNT_DEPENDENCIES_STOP="" - - # Striped configuration - if [[ "$CONTENT_DISK_NUMBER" -eq 1 && "$PARITY_DISK_NUMBER" -eq 0 ]]; then - export j=1 - export CONTENT_DISK_ID="${DATA_DISKS_ID[0]}" - if [[ "${DATA_DISKS_TYPE[0]}" == "HDD" ]]; then export ALLOW_DISCARDS="false"; else export ALLOW_DISCARDS="true"; fi - (envsubst < "templates/nix-config/disks/content.nix") >> final-nix-config/etc/nixos/disks/disko.nix - sed -i "s|/mnt/content-1|/mnt/data|" final-nix-config/etc/nixos/disks/disko.nix - - # SnapRAID configuration - elif [[ ${CONTENT_DISK_NUMBER} -gt 0 && ${PARITY_DISK_NUMBER} -gt 0 ]]; then - sed -i "s|# ./disks/snapraid.nix| ./disks/snapraid.nix|" final-nix-config/etc/nixos/configuration.nix - j=0 - for i in $(seq 0 $(($CONTENT_DISK_NUMBER - 1))); do - export j=$((j + 1)) - export CONTENT_DISK_ID="${DATA_DISKS_ID[${i}]}" - if [[ "${DATA_DISKS_TYPE[${i}]}" == "HDD" ]]; then export ALLOW_DISCARDS="false"; else export ALLOW_DISCARDS="true"; fi - (envsubst < "templates/nix-config/disks/content.nix") >> final-nix-config/etc/nixos/disks/disko.nix - SNAPRAID_CONTENT_FILES+=" \"/mnt/content-${j}/snapraid.content\""$'\n' - SNAPRAID_DATA_DISKS+=" d${j} = \"/mnt/content-${j}\";"$'\n' - MOUNT_DEPENDENCIES_START+=" \${pkgs.cryptsetup}/bin/cryptsetup open ${CONTENT_DISK_ID}-part1 crypted-content-${j} --key-file /etc/secrets/disks/content-${j}"$'\n' - MOUNT_DEPENDENCIES_START+=" \${pkgs.coreutils}/bin/mkdir -p /mnt/content-${j}"$'\n' - MOUNT_DEPENDENCIES_START+=" \${pkgs.util-linux}/bin/mount /mnt/content-${j}"$'\n' - MOUNT_DEPENDENCIES_STOP+=" \${pkgs.util-linux}/bin/umount /mnt/content-${j}"$'\n' - MOUNT_DEPENDENCIES_STOP+=" \${pkgs.cryptsetup}/bin/cryptsetup close crypted-content-${j}"$'\n' - done - echo -e "\n ✅ Generated $CONTENT_DISK_NUMBER data disk configuration(s)." - j=0 - for i in $(seq $CONTENT_DISK_NUMBER $((${#DATA_DISKS_ID[@]} - 1))); do - export j=$((j + 1)) - export PARITY_DISK_ID="${DATA_DISKS_ID[${i}]}" - if [[ "${DATA_DISKS_TYPE[${i}]}" == "HDD" ]]; then export ALLOW_DISCARDS="false"; else export ALLOW_DISCARDS="true"; fi - (envsubst < "templates/nix-config/disks/parity.nix") >> final-nix-config/etc/nixos/disks/disko.nix - SNAPRAID_PARITY_FILES+=" \"/mnt/parity-${j}/snapraid.parity\""$'\n' - MOUNT_DEPENDENCIES_START+=" \${pkgs.cryptsetup}/bin/cryptsetup open ${PARITY_DISK_ID}-part1 crypted-parity-${j} --key-file /etc/secrets/disks/parity-${j}"$'\n' - MOUNT_DEPENDENCIES_START+=" \${pkgs.coreutils}/bin/mkdir -p /mnt/parity-${j}"$'\n' - MOUNT_DEPENDENCIES_START+=" \${pkgs.util-linux}/bin/mount /mnt/parity-${j}"$'\n' - MOUNT_DEPENDENCIES_STOP+=" \${pkgs.util-linux}/bin/umount /mnt/parity-${j}"$'\n' - MOUNT_DEPENDENCIES_STOP+=" \${pkgs.cryptsetup}/bin/cryptsetup close crypted-parity-${j}"$'\n' - done - echo -e "\n ✅ Generated $PARITY_DISK_NUMBER parity disk configuration(s)." - [[ ${CONTENT_DISK_NUMBER} -eq 1 && ${PARITY_DISK_NUMBER} -eq 1 ]] && SNAPRAID_CONTENT_FILES+=" \"/mnt/content-0/snapraid.content\""$'\n' && SNAPRAID_DATA_DISKS+=" d0 = \"/mnt/content-0\";"$'\n' - export SNAPRAID_CONTENT_FILES - export SNAPRAID_DATA_DISKS - export SNAPRAID_PARITY_FILES - export MOUNT_DEPENDENCIES_START - export MOUNT_DEPENDENCIES_STOP - fi - - envsubst < templates/nix-config/disks/snapraid.nix > final-nix-config/etc/nixos/disks/snapraid.nix - - # Close the disko.nix block - cat <<'EOF' >> final-nix-config/etc/nixos/disks/disko.nix - }; - }; -} -EOF - - echo -e "\n ✅ Final disko configuration created." - - SPINDOWN_DISKS_ID=() if [[ "${#DATA_DISKS_ID[@]}" -gt 0 ]]; then for i in ${!DATA_DISKS_ID[@]}; do if [[ "${DATA_DISKS_TYPE[${i}]}" == "HDD" ]]; then SPINDOWN_DISKS_ID+=("${DATA_DISKS_ID[${i}]}") fi done - if [[ "${#SPINDOWN_DISKS_ID[@]}" -gt 0 ]]; then - cp -${FILES_COPY_FLAGS} templates/nix-config/disks/spindown.nix final-nix-config/etc/nixos/disks/ - local FORMATTED_DISKS="" - for disk in "${SPINDOWN_DISKS_ID[@]}"; do - FORMATTED_DISKS+=" \"$disk\"\n" - done - sed -i "s|DISK_LIST|${FORMATTED_DISKS}|" final-nix-config/etc/nixos/disks/spindown.nix - echo -e "\n ✅ Disk spindown configuration created." - fi fi -### Config generation <-- + + export SPINDOWN_DISKS_ID + export PARITY_DISK_NUMBER_LIST + export CONTENT_DISK_NUMBER_LIST +} + +server_config_generation() { + echo -e "\n # Server settings" >> ${CONFIGURATION_PATH} + echo -e " time.timeZone = \"${TIMEZONE}\";" >> ${CONFIGURATION_PATH} + echo -e " config.numbus.owner = \"${SERVER_OWNER_NAME}\";" >> ${CONFIGURATION_PATH} +} + +network_config_generation() { + echo -e "\n # Network settings" >> ${CONFIGURATION_PATH} + echo -e " config.numbus.networking.ipAddress = \"${HOME_SERVER_IP}\";" >> ${CONFIGURATION_PATH} + echo -e " config.numbus.networking.interface = \"${TARGET_INTERFACE}\";" >> ${CONFIGURATION_PATH} + echo -e " config.numbus.networking.routerIpAddress = \"${NETWORK_ROUTER_IP}\";" >> ${CONFIGURATION_PATH} +} + +services_config_generation() { + echo -e "\n # DNS settings" >> ${CONFIGURATION_PATH} + echo -e " config.numbus.dns = \"${SELECTED_DNS_SERVICE}\";" >> ${CONFIGURATION_PATH} + echo -e " config.numbus.services.${SELECTED_DNS_SERVICE} = true;" >> ${CONFIGURATION_PATH} + + echo -e "\n # Services settings" >> ${CONFIGURATION_PATH} + echo -e " config.numbus.services.domain = \"${DOMAIN_NAME}\";" >> ${CONFIGURATION_PATH} + for service in "${SELECTED_SERVICES[@]}"; do + echo -e " config.numbus.services.${service}.enable = true;" >> ${CONFIGURATION_PATH} + done +} + +mail_config_generation() { + echo -e "\n # Mail settings" >> ${CONFIGURATION_PATH} + echo -e " config.numbus.mail.enable = true;" >> ${CONFIGURATION_PATH} + echo -e " config.numbus.mail.userAddress = \"${SERVER_USER_EMAIL}\";" >> ${CONFIGURATION_PATH} + echo -e " config.numbus.mail.adminAddress = \"${SERVER_ADMIN_EMAIL}\";" >> ${CONFIGURATION_PATH} + echo -e " config.numbus.mail.smtpUsername = \"${SMTP_SERVER_USERNAME}\";" >> ${CONFIGURATION_PATH} + echo -e " config.numbus.mail.smtpPasswordPath = config.sops.secrets.smtpPassword.path;" >> ${CONFIGURATION_PATH} + + if [[ "${SMTP_SERVER_HOST}" != "smtp.gmail.com" ]]; then + echo -e " config.numbus.mail.smtpServer = \"${SMTP_SERVER_HOST}\";" >> ${CONFIGURATION_PATH} + if [[ "${SMTP_SERVER_PORT}" != "587" ]]; then + echo -e " config.numbus.mail.smtpPort = ${SMTP_SERVER_PORT};" >> ${CONFIGURATION_PATH} + fi +} + +disk_config_generation() { + echo -e "\n # Hardware settings" >> ${CONFIGURATION_PATH} + echo -e " config.numbus.hardware.bootDisksList = [ ${BOOT_DISKS_ID_LIST[@]} ];" >> ${CONFIGURATION_PATH} + echo -e " config.numbus.hardware.dataDisksList = [ ${CONTENT_DISK_NUMBER_LIST[@]} ];" >> ${CONFIGURATION_PATH} + echo -e " config.numbus.hardware.parityDisksList = [ ${PARITY_DISK_NUMBER_LIST[@]} ];" >> ${CONFIGURATION_PATH} } keys_generation() { -### --> Generate disk keys - for i in $(seq 1 "${#BOOT_DISKS_ID[@]}"); do + for i in $(seq 1 "${#BOOT_DISKS_ID_LIST[@]}"); do PASS="$(xkcdpass)" echo -n "$PASS" > "final-nix-config/etc/secrets/disks/boot-${i}" chmod 600 "final-nix-config/etc/secrets/disks/boot-${i}" ssh_to_host 'bash -s' << EOF -echo "$REMOTE_PASS" | sudo -S mkdir -p /etc/secrets/disks/ -echo "$REMOTE_PASS" | sudo -S bash -c "printf '%s' '$PASS' > /etc/secrets/disks/boot-${i}" +echo "$LIVE_TARGET_PASSWD" | sudo -S mkdir -p /etc/secrets/disks/ +echo "$LIVE_TARGET_PASSWD" | sudo -S bash -c "printf '%s' '$PASS' > /etc/secrets/disks/boot-${i}" +echo "$LIVE_TARGET_PASSWD" | sudo -S chmod 600 /etc/secrets/disks/boot-${i}" EOF done for i in $(seq 1 "$CONTENT_DISK_NUMBER"); do @@ -638,7 +442,8 @@ EOF echo -n "$PASS" > "final-nix-config/etc/secrets/disks/content-${i}" chmod 600 "final-nix-config/etc/secrets/disks/content-${i}" ssh_to_host 'bash -s' << EOF -echo "$REMOTE_PASS" | sudo -S bash -c "printf '%s' '$PASS' > /etc/secrets/disks/content-${i}" +echo "$LIVE_TARGET_PASSWD" | sudo -S bash -c "printf '%s' '$PASS' > /etc/secrets/disks/content-${i}" +echo "$LIVE_TARGET_PASSWD" | sudo -S chmod 600 /etc/secrets/disks/content-${i}" EOF done for i in $(seq 1 "$PARITY_DISK_NUMBER"); do @@ -646,10 +451,10 @@ EOF echo -n "$PASS" > "final-nix-config/etc/secrets/disks/parity-${i}" chmod 600 "final-nix-config/etc/secrets/disks/parity-${i}" ssh_to_host 'bash -s' << EOF -echo "$REMOTE_PASS" | sudo -S bash -c "printf '%s' '$PASS' > /etc/secrets/disks/parity-${i}" +echo "$LIVE_TARGET_PASSWD" | sudo -S bash -c "printf '%s' '$PASS' > /etc/secrets/disks/parity-${i}" +echo "$LIVE_TARGET_PASSWD" | sudo -S chmod 600 /etc/secrets/disks/parity-${i}" EOF done -### Generate disk keys <-- echo -e "\n ✅ Generating sops-nix keys..." ssh-to-age -private-key -i final-nix-config/home/numbus-admin/.ssh/id_ed25519 > final-nix-config/var/lib/sops-nix/key.txt @@ -666,41 +471,15 @@ EOF --output final-nix-config/etc/nixos/secrets/secrets.yaml } -nix_generation() { - echo -e "\n ✅ Copying the configuration to the new machine..." - cp -${FILES_COPY_FLAGS} templates/nix-config/flake.nix final-nix-config/etc/nixos/ - cp -${FILES_COPY_FLAGS} templates/nix-config/misc/* final-nix-config/etc/nixos/misc/ - - echo "${SERVER_OWNER_NAME:-User}" > final-nix-config/etc/numbus-server/owner - echo -e "\n ✅ Writing correct ips to configuration.nix..." - sed -i "s|HOME_SERVER_IP|${HOME_SERVER_IP}|g" final-nix-config/etc/nixos/misc/networking.nix - sed -i "s|HOME_ROUTER_IP|${HOME_ROUTER_IP}|g" final-nix-config/etc/nixos/misc/networking.nix - sed -i "s|TARGET_INTERFACE|${TARGET_INTERFACE}|g" final-nix-config/etc/nixos/misc/networking.nix - sed -i "s|DOMAIN_NAME|${DOMAIN_NAME}|" final-nix-config/etc/nixos/misc/mail.nix - sed -i "s|EMAIL_ADDRESS|${EMAIL_ADDRESS}|" final-nix-config/etc/nixos/misc/mail.nix - sed -i "s|SENDER_MAIL_DOMAIN|${SENDER_EMAIL_DOMAIN}|" final-nix-config/etc/nixos/misc/mail.nix - sed -i "s|SENDER_MAIL_ADDRESS|${SENDER_EMAIL_ADDRESS}|" final-nix-config/etc/nixos/misc/mail.nix - sed -i "s*PODMAN_NETWORKS*${PODMAN_NETWORKS//$'\n'/\\n}*" final-nix-config/etc/nixos/misc/activation.nix - sed -i "s|TRAEFIK_NETWORKS|${TRAEFIK_NETWORKS//$'\n'/\\n}|" final-nix-config/etc/nixos/podman/traefik.nix - sed -i "s|TRAEFIK_REF_NETWORKS|${TRAEFIK_REF_NETWORKS//$'\n'/\\n}|" final-nix-config/etc/nixos/podman/traefik.nix - if [[ "${TARGET_TPM}" == "true" && ${TARGET_TPM_VERSION} -eq 2 ]]; then - sed -i "s|# ./disks/pcr-check.nix| ./disks/pcr-check.nix|" final-nix-config/etc/nixos/configuration.nix - sed -i "s|# boot.initrd.systemd.tpm2.enable = true;| boot.initrd.systemd.tpm2.enable = true;|" final-nix-config/etc/nixos/configuration.nix - sed -i "s|# systemIdentity.enable = true;| systemIdentity.enable = true;|" final-nix-config/etc/nixos/configuration.nix - cp -${FILES_COPY_FLAGS} templates/nix-config/disks/pcr-check.nix final-nix-config/etc/nixos/disks/ - fi -} - sum_up() { -### --> Disk selection recap DISK_RECAP_CONTENT=$(cat << EOF ### Disk Configuration Summary Please review the selected disk layout before proceeding. -**Boot Disks (${#BOOT_DISKS_ID[@]}):** -* **Boot 1:** \`${BOOT_DISKS_ID[0]}\` -$( [[ -n "${BOOT_DISKS_ID[1]:-}" ]] && echo "* **Boot 2:** \`${BOOT_DISKS_ID[1]}\`" || echo "* **Boot 2:** *Not configured*" ) +**Boot Disks (${#BOOT_DISKS_ID_LIST[@]}):** +* **Boot 1:** \`${BOOT_DISKS_ID_LIST[0]}\` +$( [[ -n "${BOOT_DISKS_ID_LIST[1]:-}" ]] && echo "* **Boot 2:** \`${BOOT_DISKS_ID_LIST[1]}\`" || echo "* **Boot 2:** *Not configured*" ) **Data Disks ($CONTENT_DISK_NUMBER):** $( j=1 && for i in $(seq 0 $(($CONTENT_DISK_NUMBER - 1))); do echo "* **Data ${j}:** \`${DATA_DISKS_ID[${i}]}\`" && j=$((j + 1)); done ) @@ -714,40 +493,6 @@ EOF gum style --border normal --margin "1" --padding "1 2" --border-foreground 212 "$(gum format <<< "${DISK_RECAP_CONTENT}")" gum confirm "Proceed with this disk configuration?" || { echo -e "\n\n ❌ Aborting as requested."; exit 1; } -### Disk selection recap <-- - -### Keys recap <-- - KEYS_RECAP_CONTENT=$(cat << EOF -### Generated Secrets Summary - -Please save these secrets in a secure location (e.g., a password manager). - -**Service Credentials:** -$( [[ -n ${HOME_ASSISTANT_MQTT_USER:-} ]] && echo "* **Home Assistant MQTT User:** \`${HOME_ASSISTANT_MQTT_USER}\`" && \ -echo "* **Home Assistant MQTT Password:** \`$HOME_ASSISTANT_MQTT_PASSWORD\`" \ -|| echo "* **Home assistant:** *Not configured*" ) -$( [[ -n ${FTLCONF_WEBSERVER_PASSWORD:-} ]] && echo "* **Pi-hole Web Password:** \`${FTLCONF_WEBSERVER_PASSWORD}\`" \ -|| echo "* **Pi-hole:** *Not configured*" ) -$( [[ -n ${PASSBOLT_DB_NAME:-} ]] && echo "* **Passbolt DB Name:** \`${PASSBOLT_DB_NAME}\`" && \ -echo "* **Passbolt DB User:** \`${PASSBOLT_DB_USERNAME}\`" && echo "* **Passbolt DB Password:** \`${PASSBOLT_DB_PASSWORD}\`" \ -|| echo "* **Passbolt:** *Not configured*" ) -$( [[ -n ${IMMICH_DB_NAME:-} ]] && echo "* **Immich DB Name:** \`${IMMICH_DB_NAME}\`" && \ -echo "* **Immich DB User:** \`${IMMICH_DB_USERNAME}\`" && echo "* **Immich DB Password:** \`${IMMICH_DB_PASSWORD}\`" \ -|| echo "* **Immich:** *Not configured*" ) -$( [[ -n ${GITEA_DB_NAME:-} ]] && echo "* **Gitea DB Name:** \`${GITEA_DB_NAME}\`" && \ -echo "* **Gitea DB User:** \`${GITEA_DB_USERNAME}\`" && echo "* **Gitea DB Password:** \`${GITEA_DB_PASSWORD}\`" \ -|| echo "* **Gitea:** *Not configured*" ) - -**Disk Encryption Keys:** -$( for i in $(seq 1 "${#BOOT_DISKS_ID[@]}"); do f="final-nix-config/etc/secrets/disks/boot-${i}"; [[ -f "$f" ]] && echo "* **Boot Disk $i Key:** \`$(cat "$f")\`"; done ) -$( for i in $(seq 1 "$CONTENT_DISK_NUMBER"); do f="final-nix-config/etc/secrets/disks/content-${i}"; [[ -f "$f" ]] && echo "* **Content Disk $i Key:** \`$(cat "$f")\`"; done ) -$( for i in $(seq 1 "$PARITY_DISK_NUMBER"); do f="final-nix-config/etc/secrets/disks/parity-${i}"; [[ -f "$f" ]] && echo "* **Parity Disk $i Key:** \`$(cat "$f")\`"; done ) -EOF -) - - gum style --border normal --margin "1" --padding "1 2" --border-foreground 212 "$(gum format <<< "${KEYS_RECAP_CONTENT}")" - gum confirm "Do you want to deploy NixOS on the target host?" || { echo -e "\n\n ❌ Aborting as requested"; exit 1; } -### Keys recap <-- } cloudflare_dns_setup() { @@ -761,7 +506,7 @@ cloudflare_dns_setup() { local CREATION_STATUS CREATION_STATUS=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \ - -H "Authorization: Bearer ${CF_DNS_API_TOKEN}" \ + -H "Authorization: Bearer ${CLOUDFLARE_DNS_API_TOKEN}" \ -H "Content-Type: application/json" \ --data "{\"type\":\"A\",\"name\":\"${SUBDOMAIN}\",\"content\":\"${HOME_SERVER_IP}\",\"ttl\":1,\"proxied\":false}" | jq -r '.success') @@ -784,12 +529,12 @@ cloudflare_dns_setup() { || { echo -e "\n ⚠️ DNS records for ${SUBDOMAIN} will not be updated"; return 0; } RECORD_IDS=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?name=${SUBDOMAIN}&type=A" \ - -H "Authorization: Bearer ${CF_DNS_API_TOKEN}" \ + -H "Authorization: Bearer ${CLOUDFLARE_DNS_API_TOKEN}" \ -H "Content-Type: application/json" | jq -r '.result[].id') for id in ${RECORD_IDS}; do curl -s -X DELETE "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${id}" \ - -H "Authorization: Bearer ${CF_DNS_API_TOKEN}" \ + -H "Authorization: Bearer ${CLOUDFLARE_DNS_API_TOKEN}" \ -H "Content-Type: application/json" > /dev/null 2>&1 done @@ -812,7 +557,7 @@ cloudflare_dns_setup() { # Get Zone ID ZONE_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=${DOMAIN_NAME}" \ - -H "Authorization: Bearer ${CF_DNS_API_TOKEN}" \ + -H "Authorization: Bearer ${CLOUDFLARE_DNS_API_TOKEN}" \ -H "Content-Type: application/json" | jq -r '.result[0].id') if [[ "${ZONE_ID}" == "null" || -z "${ZONE_ID}" ]]; then @@ -823,7 +568,7 @@ cloudflare_dns_setup() { # Check for existing records and create them if non-existent for service_domain in "${SELECTED_SERVICES_DNS[@]}"; do DNS_RECORDS=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?name=${service_domain}&type=A" \ - -H "Authorization: Bearer ${CF_DNS_API_TOKEN}" \ + -H "Authorization: Bearer ${CLOUDFLARE_DNS_API_TOKEN}" \ -H "Content-Type: application/json") RECORD_COUNT=$(echo "${DNS_RECORDS}" | jq '.result | length') @@ -856,7 +601,7 @@ export_configuration() { echo -e "\n# SERVER SETTINGS" >> $CONFIG_EXPORT_FILE echo "export SERVER_OWNER_NAME=\"${SERVER_OWNER_NAME:-User}\"" >> $CONFIG_EXPORT_FILE echo -e "\n# DISK SETTINGS" >> $CONFIG_EXPORT_FILE - echo "export BOOT_DISKS_ID=\"(${BOOT_DISKS_ID[@]})\"" >> $CONFIG_EXPORT_FILE + echo "export BOOT_DISKS_ID_LIST=\"(${BOOT_DISKS_ID_LIST[@]})\"" >> $CONFIG_EXPORT_FILE echo "export DATA_DISKS_ID=\"(${DATA_DISKS_ID[@]})\"" >> $CONFIG_EXPORT_FILE echo "export DATA_DISKS_TYPE=\"(${DATA_DISKS_TYPE[@]})\"" >> $CONFIG_EXPORT_FILE echo "export SPINDOWN_DISKS_ID=\"(${SPINDOWN_DISKS_ID[@]})\"" >> $CONFIG_EXPORT_FILE @@ -880,7 +625,7 @@ deploy() { --flake ./final-nix-config/etc/nixos#numbus-server \ --extra-files final-nix-config \ --chown "/home/numbus-admin/" 1000:1000 \ - --target-host ${TARGET_USER}@${TARGET_HOST} + --target-host ${TARGET_USER}@${LIVE_TARGET_IP} echo -e "\n\n✅ Installation successfull !" sleep 1 @@ -888,8 +633,8 @@ deploy() { postrun_action() { TARGET_USER="numbus-admin" - TARGET_HOST="${HOME_SERVER_IP}" - REMOTE_PASS="changeMe!" + LIVE_TARGET_IP="${HOME_SERVER_IP}" + LIVE_TARGET_PASSWD="changeMe!" echo -e "\n\n Now the remote machine will reboot. You will need to input the boot disk(s) passphrase. This will be the only time you will have to do so, it will be automatic in the future." @@ -926,7 +671,7 @@ postrun_action() { Do you want to enable automatic disk decryption on boot ?" if gum confirm "➡️ I understand, 'yes' to proceed."; then - sshpass -p "${REMOTE_PASS}" ssh -i "final-nix-config/home/numbus-admin/.ssh/id_ed25519" "${TARGET_USER}@${TARGET_HOST}" 'bash -s' << EOF + sshpass -p "${LIVE_TARGET_PASSWD}" ssh -i "final-nix-config/home/numbus-admin/.ssh/id_ed25519" "${TARGET_USER}@${LIVE_TARGET_IP}" 'bash -s' << EOF echo "Enrolling boot disk key to TPM..." BOOT_DISKS_NAME=(${BOOT_DISKS_NAME[@]}) @@ -943,14 +688,14 @@ for i in \${!BOOT_DISKS_NAME[@]}; do DISK_PATH="/dev/\${BOOT_DISKS_NAME[\${i}]}2" fi [[ "\${DEBUG}" == "true" ]] && echo "Issuing enroll command for disk \${DISK_PATH}..." - echo ${REMOTE_PASS} | sudo -S systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 --unlock-key-file=/etc/secrets/disks/boot-\${j} \${DISK_PATH} + echo ${LIVE_TARGET_PASSWD} | sudo -S systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 --unlock-key-file=/etc/secrets/disks/boot-\${j} \${DISK_PATH} j=\$((j + 1)) done echo "Getting PCRS 15 hash..." -PCR_HASH=\$(echo ${REMOTE_PASS} | sudo -S systemd-analyze pcrs 15 --json=short) +PCR_HASH=\$(echo ${LIVE_TARGET_PASSWD} | sudo -S systemd-analyze pcrs 15 --json=short) -echo ${REMOTE_PASS} | sudo -S sed -i "s|PCR_HASH|\${PCR_HASH}|" /etc/nixos/configuration.nix +echo ${LIVE_TARGET_PASSWD} | sudo -S sed -i "s|PCR_HASH|\${PCR_HASH}|" /etc/nixos/configuration.nix EOF else echo "Skipping TPM configuration." @@ -967,13 +712,13 @@ securely on a hidden sheet of paper or add it to your password manager (locally gum confirm "➡️ I understand, 'yes' to proceed." || { echo -e "\n\n❌ Aborting as requested."; exit 1; } - echo $REMOTE_PASS | sudo -S passwd numbus-admin + echo $LIVE_TARGET_PASSWD | sudo -S passwd numbus-admin } nix_update() { echo -e "\n\n🔄 Updating NixOS on the remote server..." - nixos-rebuild --target-host numbus-admin@${TARGET_HOST} \ + nixos-rebuild --target-host numbus-admin@${LIVE_TARGET_IP} \ --use-remote-sudo switch --flake final-nix-config/etc/nixos#numbus-server } diff --git a/flake.nix b/flake.nix deleted file mode 100644 index 87081f4..0000000 --- a/flake.nix +++ /dev/null @@ -1,17 +0,0 @@ -{ - description = "Numbus Server - Your Personal Cloud, Simplified"; - - inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; - }; - - outputs = { self, nixpkgs, ... }: { - nixosModules = { - default = { config, pkgs, lib, ... }: { - imports = [ - ./modules/default.nix - ]; - }; - }; - }; -} \ No newline at end of file diff --git a/frigate.nix b/frigate.nix deleted file mode 100644 index 466d8ca..0000000 --- a/frigate.nix +++ /dev/null @@ -1,97 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; - -let - cfg = config.numbus.services.frigate; - container_name = "frigate"; - compose_file = "podman/frigate/compose.yaml"; - config_dir = "/mnt/config/frigate"; - data_dir = "/mnt/data/frigate"; -in -{ - options.numbus.services.frigate = { - enable = mkEnableOption "Frigate NVR"; - - domain = mkOption { - type = types.str; - description = "The root domain name (e.g., example.com). Frigate will use frigate.example.com"; - }; - - mqtt = { - user = mkOption { - type = types.str; - default = "frigate"; - description = "MQTT User for Frigate"; - }; - # In the future, we will handle passwords via sops-nix secrets - }; - - devices = mkOption { - type = types.listOf types.str; - default = []; - example = [ "/dev/dri:/dev/dri" "/dev/bus/usb:/dev/bus/usb" ]; - description = "List of devices to map into the container"; - }; - }; - - config = mkIf cfg.enable { - environment.etc."${compose_file}".text = - '' - services: - frigate: - image: ghcr.io/blakeblackshear/frigate:stable - container_name: frigate - shm_size: "512MB" - networks: - home-assistant_frontend: - home-assistant_backend: - volumes: - - ${config_dir}:/config - - ${data_dir}/clips:/media/frigate/clips - - ${data_dir}/recordings:/media/frigate/recordings - - ${data_dir}/exports:/media/frigate/exports - - /etc/localtime:/etc/localtime:ro - - type: tmpfs - target: /tmp/cache - tmpfs: - size: 2000000000 - environment: - FRIGATE_MQTT_USER: ${cfg.mqtt.user} - # We will handle the password injection securely in the next phase - FRIGATE_MQTT_PASSWORD: $FRIGATE_MQTT_PASSWORD - devices: - ${concatStringsSep "\n " (map (d: "- ${d}") cfg.devices)} - labels: - - traefik.enable=true - - traefik.docker.network=home-assistant_frontend - - traefik.http.services.frigate.loadbalancer.server.port=8971 - - traefik.http.services.frigate.loadbalancer.server.scheme=http - - traefik.http.routers.frigate-https.entrypoints=websecure - - "traefik.http.routers.frigate-https.rule=Host(`frigate.${cfg.domain}`)" - - traefik.http.routers.frigate-https.tls=true - - traefik.http.routers.frigate-https.tls.certresolver=cloudflare - restart: unless-stopped - - networks: - home-assistant_backend: - external: true - home-assistant_frontend: - external: true - ''; - - systemd.services."${container_name}" = { - description = "Podman container : ${container_name}"; - after = [ "traefik.service" "home-assistant.service" "pi-hole.service" ]; - requires = [ "traefik.service" "home-assistant.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.podman-compose pkgs.coreutils ]; - serviceConfig = { - User = "numbus-admin"; - Type = "exec"; - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - }; - }; - }; -} \ No newline at end of file diff --git a/modules/default.nix b/modules/default.nix deleted file mode 100644 index e6a2234..0000000 --- a/modules/default.nix +++ /dev/null @@ -1,7 +0,0 @@ -{ ... }: - -{ - imports = [ - ./services/default.nix - ]; -} \ No newline at end of file diff --git a/modules/services/adguard.nix b/modules/services/adguard.nix deleted file mode 100644 index e69de29..0000000 diff --git a/modules/services/default.nix b/modules/services/default.nix deleted file mode 100644 index 6ce174d..0000000 --- a/modules/services/default.nix +++ /dev/null @@ -1,16 +0,0 @@ -{ ... }: - -{ - imports = [ - ./adguard.nix - ./frigate.nix - ./gitea.nix - ./home-assistant.nix - ./immich.nix - ./it-tools.nix - ./nextcloud.nix - ./passbolt.nix - ./pi-hole.nix - ./traefik.nix - ]; -} \ No newline at end of file diff --git a/modules/services/frigate.nix b/modules/services/frigate.nix deleted file mode 100644 index ff82aa3..0000000 --- a/modules/services/frigate.nix +++ /dev/null @@ -1,98 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "frigate"; - compose_file = "podman/frigate/compose.yaml"; - config_dir = "/mnt/config/frigate"; - data_dir = "/mnt/data/frigate"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - services: - frigate: - image: ghcr.io/blakeblackshear/frigate:stable - container_name: frigate - shm_size: "512MB" - networks: - home-assistant_frontend: - home-assistant_backend: - volumes: - - ${config_dir}:/config - - ${data_dir}/clips:/media/frigate/clips - - ${data_dir}/recordings:/media/frigate/recordings - - ${data_dir}/exports:/media/frigate/exports - - /etc/localtime:/etc/localtime:ro - - type: tmpfs - target: /tmp/cache - tmpfs: - size: 2000000000 - environment: - FRIGATE_MQTT_USER: $FRIGATE_MQTT_USER - FRIGATE_MQTT_PASSWORD: $FRIGATE_MQTT_PASSWORD - # --- frigate devices --- # - labels: - - traefik.enable=true - - traefik.docker.network=home-assistant_frontend - - traefik.http.services.frigate.loadbalancer.server.port=8971 - - traefik.http.services.frigate.loadbalancer.server.scheme=http - - traefik.http.routers.frigate-https.entrypoints=websecure - - traefik.http.routers.frigate-https.rule=Host(`frigate.$DOMAIN_NAME`) - - traefik.http.routers.frigate-https.tls=true - - traefik.http.routers.frigate-https.tls.certresolver=cloudflare - restart: unless-stopped - - networks: - home-assistant_backend: - external: true - home-assistant_frontend: - external: true - ''; - - systemd.services."${container_name}" = { - description = "Podman container : ${container_name}"; - after = [ "traefik.service" "home-assistant.service" "pi-hole.service" ]; - requires = [ "traefik.service" "home-assistant.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - TimeoutStartSec = "600"; - ExecStartPre = [ - "${pkgs.bash}/bin/bash -c 'sleep $((RANDOM % 180))'" - "-${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull" - ]; - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - - systemd.services."update-${container_name}" = { - description = "Update ${container_name} container"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.systemd}/bin/systemctl restart ${container_name}.service"; - }; - }; - - systemd.timers."update-${container_name}" = { - timerConfig = { - OnCalendar = "02:00"; - RandomizedDelaySec = "60m"; - Unit = "update-${container_name}.service"; - }; - wantedBy = [ "timers.target" ]; - }; - }; -} \ No newline at end of file diff --git a/modules/services/gitea.nix b/modules/services/gitea.nix deleted file mode 100644 index 0b21a15..0000000 --- a/modules/services/gitea.nix +++ /dev/null @@ -1,113 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "gitea"; - compose_file = "podman/gitea/compose.yaml"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - services: - gitea: - image: docker.io/gitea/gitea:latest - container_name: gitea - networks: - gitea_frontend: - gitea_backend: - volumes: - - gitea_data:/data - - /etc/localtime:/etc/localtime:ro - environment: - - USER_UID=1000 - - USER_GID=1000 - - GITEA__database__DB_TYPE=postgres - - GITEA__database__HOST=$POSTGRES_HOST:$POSTGRES_PORT - - GITEA__database__NAME=$DB_NAME - - GITEA__database__USER=$DB_USERNAME - - GITEA__database__PASSWD=$DB_PASSWORD - - GITEA__server__SSH_PORT=2424 - - GITEA__server__ROOT_URL=gitea.$DOMAIN_NAME - labels: - - traefik.enable=true - - traefik.docker.network=gitea_frontend - - traefik.http.services.gitea.loadbalancer.server.port=3000 - - traefik.http.services.gitea.loadbalancer.server.scheme=http - - traefik.http.routers.gitea-https.entrypoints=websecure - - traefik.http.routers.gitea-https.rule=Host(`gitea.$DOMAIN_NAME`) - - traefik.http.routers.gitea-https.tls=true - - traefik.http.routers.gitea-https.tls.certresolver=cloudflare - depends_on: - - gitea-database - restart: unless-stopped - - gitea-database: - image: docker.io/library/postgres:17.5 - container_name: gitea-database - environment: - - POSTGRES_USER=$DB_USERNAME - - POSTGRES_PASSWORD=$DB_PASSWORD - - POSTGRES_DB=$DB_NAME - networks: - gitea_backend: - volumes: - - gitea_database:/var/lib/postgresql/data - restart: unless-stopped - - volumes: - gitea_data: - gitea_database: - - networks: - gitea_frontend: - external: true - gitea_backend: - external: true - ''; - - systemd.services."${container_name}" = { - description = "Podman container : ${container_name}"; - after = [ "network.target" "traefik.service" "pi-hole.service" ]; - requires = [ "traefik.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - TimeoutStartSec = "900"; - ExecStartPre = [ - "${pkgs.bash}/bin/bash -c 'sleep $((RANDOM % 400))'" - "-${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull" - ]; - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - - systemd.services."update-${container_name}" = { - description = "Update ${container_name} container"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.systemd}/bin/systemctl restart ${container_name}.service"; - }; - }; - - systemd.timers."update-${container_name}" = { - timerConfig = { - OnCalendar = "02:00"; - RandomizedDelaySec = "60m"; - Unit = "update-${container_name}.service"; - }; - wantedBy = [ "timers.target" ]; - }; - }; -} \ No newline at end of file diff --git a/modules/services/home-assistant.nix b/modules/services/home-assistant.nix deleted file mode 100644 index af89e46..0000000 --- a/modules/services/home-assistant.nix +++ /dev/null @@ -1,83 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "home-assistant"; - compose_file = "podman/home-assistant/compose.yaml"; - config_dir_1 = "/mnt/config/home-assistant"; - config_dir_2 = "/mnt/config/mqtt"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - services: - home-assistant: - image: ghcr.io/home-assistant/home-assistant:latest - container_name: home-assistant - networks: - home-assistant_frontend: - home-assistant_backend: - volumes: - - ${config_dir_1}:/config - - /etc/localtime:/etc/localtime:ro - - /run/dbus:/run/dbus:ro - # --- home-assistant devices --- # - labels: - - traefik.enable=true - - traefik.docker.network=home-assistant_frontend - - traefik.http.services.home-assistant.loadbalancer.server.port=8123 - - traefik.http.services.home-assistant.loadbalancer.server.scheme=http - - traefik.http.routers.home-assistant-https.entrypoints=websecure - - traefik.http.routers.home-assistant-https.rule=Host(`home-assistant.$DOMAIN_NAME`) - - traefik.http.routers.home-assistant-https.tls=true - - traefik.http.routers.home-assistant-https.tls.certresolver=cloudflare - restart: unless-stopped - - frigate-mqtt: - image: eclipse-mosquitto - container_name: mqtt - user: 1000:1000 - networks: - home-assistant_backend: - volumes: - - ${config_dir_2}:/mosquitto - restart: unless-stopped - - networks: - home-assistant_backend: - external: true - home-assistant_frontend: - external: true - ''; - systemd.services.${container_name} = { - description = "Podman container : ${container_name}"; - after = [ "network.target" "traefik.service" "pi-hole.service" ]; - requires = [ "traefik.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - TimeoutStartSec = "600"; - # Pull the latest image before running - ExecStartPre = [ - "${pkgs.coreutils}/bin/sleep 180" - "-${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull" - ]; - # Bring the service up - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - # Take it down gracefully - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - }; -} \ No newline at end of file diff --git a/modules/services/immich.nix b/modules/services/immich.nix deleted file mode 100644 index 746c6c2..0000000 --- a/modules/services/immich.nix +++ /dev/null @@ -1,134 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "immich"; - compose_file = "podman/immich/compose.yaml"; - config_dir = "/mnt/config/immich"; - data_dir = "/mnt/data/immich"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - services: - immich-server: - image: ghcr.io/immich-app/immich-server:$IMMICH_VERSION - container_name: immich-server - networks: - immich_frontend: - immich_backend: - volumes: - - $UPLOAD_LOCATION:/data - - /etc/localtime:/etc/localtime:ro - # --- immich devices --- # - labels: - - traefik.enable=true - - traefik.docker.network=immich_frontend - - traefik.http.services.immich.loadbalancer.server.port=2283 - - traefik.http.services.immich.loadbalancer.server.scheme=http - - traefik.http.routers.immich-https.entrypoints=websecure - - traefik.http.routers.immich-https.rule=Host(`immich.$DOMAIN_NAME`) - - traefik.http.routers.immich-https.tls=true - - traefik.http.routers.immich-https.tls.certresolver=cloudflare - env_file: - - .env - depends_on: - - immich-redis - - immich-database - restart: always - healthcheck: - disable: false - - immich-machine-learning: - container_name: immich-machine-learning - image: ghcr.io/immich-app/immich-machine-learning:$IMMICH_VERSION - networks: - immich_backend: - volumes: - - ${config_dir}/models:/cache - env_file: - - .env - restart: always - healthcheck: - disable: false - - immich-redis: - container_name: immich-redis - image: docker.io/valkey/valkey:8-bookworm@sha256:a137a2b60aca1a75130022d6bb96af423fefae4eb55faf395732db3544803280 - networks: - immich_backend: - healthcheck: - test: redis-cli ping || exit 1 - restart: always - - immich-database: - container_name: immich-database - image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:32324a2f41df5de9efe1af166b7008c3f55646f8d0e00d9550c16c9822366b4a - networks: - immich_backend: - shm_size: 128mb - volumes: - # Do not edit the next line. If you want to change the database storage location on your system, edit the value of DB_DATA_LOCATION in the .env file - - $DB_DATA_LOCATION:/var/lib/postgresql/data - environment: - POSTGRES_PASSWORD: $DB_PASSWORD - POSTGRES_USER: $DB_USERNAME - POSTGRES_DB: $DB_DATABASE_NAME - POSTGRES_INITDB_ARGS: '--data-checksums' - restart: always - healthcheck: - disable: false - - networks: - immich_backend: - external: true - immich_frontend: - external: true - ''; - - systemd.services."${container_name}" = { - description = "Podman container : ${container_name}"; - after = [ "network.target" "traefik.service" "pi-hole.service" ]; - requires = [ "traefik.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - TimeoutStartSec = "900"; - ExecStartPre = [ - "${pkgs.bash}/bin/bash -c 'sleep $((RANDOM % 400))'" - "-${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull" - ]; - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - - systemd.services."update-${container_name}" = { - description = "Update ${container_name} container"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.systemd}/bin/systemctl restart ${container_name}.service"; - }; - }; - - systemd.timers."update-${container_name}" = { - timerConfig = { - OnCalendar = "02:00"; - RandomizedDelaySec = "60m"; - Unit = "update-${container_name}.service"; - }; - wantedBy = [ "timers.target" ]; - }; - }; -} \ No newline at end of file diff --git a/modules/services/it-tools.nix b/modules/services/it-tools.nix deleted file mode 100644 index ee29889..0000000 --- a/modules/services/it-tools.nix +++ /dev/null @@ -1,77 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "it-tools"; - compose_file = "podman/it-tools/compose.yaml"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - services: - it-tools: - container_name: it-tools - image: corentinth/it-tools - networks: - it-tools_frontend: - labels: - - traefik.enable=true - - traefik.docker.network=it-tools_frontend - - traefik.http.services.it-tools.loadbalancer.server.port=80 - - traefik.http.services.it-tools.loadbalancer.server.scheme=http - - traefik.http.routers.it-tools-https.entrypoints=websecure - - traefik.http.routers.it-tools-https.rule=Host(`it-tools.$DOMAIN_NAME`) - - traefik.http.routers.it-tools-https.tls=true - - traefik.http.routers.it-tools-https.tls.certresolver=cloudflare - restart: unless-stopped - networks: - it-tools_frontend: - external: true - ''; - - systemd.services."${container_name}" = { - description = "Podman container : ${container_name}"; - after = [ "network.target" "traefik.service" "pi-hole.service" ]; - requires = [ "traefik.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - TimeoutStartSec = "600"; - ExecStartPre = [ - "${pkgs.bash}/bin/bash -c 'sleep $((RANDOM % 180))'" - "-${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull" - ]; - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - - systemd.services."update-${container_name}" = { - description = "Update ${container_name} container"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.systemd}/bin/systemctl restart ${container_name}.service"; - }; - }; - - systemd.timers."update-${container_name}" = { - timerConfig = { - OnCalendar = "02:00"; - RandomizedDelaySec = "60m"; - Unit = "update-${container_name}.service"; - }; - wantedBy = [ "timers.target" ]; - }; - }; -} \ No newline at end of file diff --git a/modules/services/nextcloud.nix b/modules/services/nextcloud.nix deleted file mode 100644 index 9f02a75..0000000 --- a/modules/services/nextcloud.nix +++ /dev/null @@ -1,131 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "nextcloud"; - compose_file = "podman/nextcloud/compose.yaml"; - data_dir = "/mnt/data/nextcloud"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - services: - nextcloud-server: - image: docker.io/library/nextcloud:latest - container_name: nextcloud-server - restart: unless-stopped - networks: - nextcloud_frontend: - nextcloud_backend: - volumes: - - nextcloud_data:/var/www/html - - ${data_dir}:/var/www/html/data - environment: - MYSQL_HOST: nextcloud-database - MYSQL_DATABASE: $MYSQL_DATABASE - MYSQL_USER: $MYSQL_USER - MYSQL_PASSWORD: $MYSQL_PASSWORD - REDIS_HOST: nextcloud-redis - REDIS_HOST_PASSWORD: $REDIS_HOST_PASSWORD - NEXTCLOUD_TRUSTED_DOMAINS: $DOMAIN_NAME - SMTP_HOST: $SMTP_HOST - SMTP_SECURE: tls - SMTP_PORT: $SMTP_PORT - SMTP_NAME: $SMTP_NAME - SMTP_PASSWORD: $SMTP_PASSWORD - MAIL_FROM_ADDRESS: $MAIL_FROM_ADDRESS - MAIL_DOMAIN: $DOMAIN_NAME - APACHE_DISABLE_REWRITE_IP: 1 - TRUSTED_PROXIES: traefik - OVERWRITEPROTOCOL: https - labels: - - traefik.enable=true - - traefik.docker.network=nextcloud_frontend - - traefik.http.services.nextcloud.loadbalancer.server.port=80 - - traefik.http.services.nextcloud.loadbalancer.server.scheme=http - - traefik.http.routers.nextcloud-https.entrypoints=websecure - - traefik.http.routers.nextcloud-https.rule=Host(`nextcloud.$DOMAIN_NAME`) - - traefik.http.routers.nextcloud-https.tls=true - - traefik.http.routers.nextcloud-https.tls.certresolver=cloudflare - depends_on: - - nextcloud-database - - nextcloud-redis: - image: docker.io/library/redis:alpine - name: nextcloud-redis - restart: unless-stopped - networks: - nextcloud_backend: - command: redis-server --requirepass $REDIS_HOST_PASSWORD - - nextcloud-database: - image: docker.io/library/mariadb:latest - container_name: nextcloud-database - restart: unless-stopped - networks: - nextcloud_backend: - volumes: - - nextcloud_database:/var/lib/mysql - environment: - MARIADB_DATABASE: $MYSQL_DATABASE - MARIADB_USER: $MYSQL_USER - MARIADB_PASSWORD: $MYSQL_PASSWORD - MARIADB_RANDOM_ROOT_PASSWORD: true - - networks: - nextcloud_frontend: - external: true - nextcloud_backend: - external: true - - volumes: - nextcloud_data: - nextcloud_database: - ''; - - systemd.services."${container_name}" = { - description = "Podman container : ${container_name}"; - after = [ "network.target" "traefik.service" "pi-hole.service" ]; - requires = [ "traefik.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - TimeoutStartSec = "600"; - ExecStartPre = [ - "${pkgs.bash}/bin/bash -c 'sleep $((RANDOM % 180))'" - "-${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull" - ]; - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - - systemd.services."update-${container_name}" = { - description = "Update ${container_name} container"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.systemd}/bin/systemctl restart ${container_name}.service"; - }; - }; - - systemd.timers."update-${container_name}" = { - timerConfig = { - OnCalendar = "02:00"; - RandomizedDelaySec = "60m"; - Unit = "update-${container_name}.service"; - }; - wantedBy = [ "timers.target" ]; - }; - }; -} \ No newline at end of file diff --git a/modules/services/passbolt.nix b/modules/services/passbolt.nix deleted file mode 100644 index 5901f11..0000000 --- a/modules/services/passbolt.nix +++ /dev/null @@ -1,129 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "passbolt"; - compose_file = "podman/passbolt/compose.yaml"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - services: - passbolt: - image: passbolt/passbolt:latest-ce-non-root - container_name: passbolt - networks: - passbolt_frontend: - passbolt_backend: - volumes: - - passbolt-gpg:/etc/passbolt/gpg - - passbolt-jwt:/etc/passbolt/jwt - environment: - APP_DEFAULT_TIMEZONE: $TZ - APP_FULL_BASE_URL: https://passbolt.$DOMAIN_NAME - DATASOURCES_DEFAULT_HOST: "passbolt-database" - DATASOURCES_DEFAULT_USERNAME: $PASSBOLT_MYSQL_USER - DATASOURCES_DEFAULT_PASSWORD: $PASSBOLT_MYSQL_PASSWORD - DATASOURCES_DEFAULT_DATABASE: $PASSBOLT_MYSQL_DATABASE - EMAIL_DEFAULT_FROM_NAME: "Passbolt" - EMAIL_TRANSPORT_DEFAULT_HOST: $EMAIL_TRANSPORT_DEFAULT_HOST - EMAIL_TRANSPORT_DEFAULT_PORT: $EMAIL_TRANSPORT_DEFAULT_PORT - EMAIL_TRANSPORT_DEFAULT_USERNAME: $EMAIL_TRANSPORT_DEFAULT_USERNAME - EMAIL_TRANSPORT_DEFAULT_PASSWORD: $EMAIL_TRANSPORT_DEFAULT_PASSWORD - EMAIL_TRANSPORT_DEFAULT_TLS: true - EMAIL_DEFAULT_FROM: $EMAIL_ADDRESS - PASSBOLT_SSL_FORCE: true - labels: - - traefik.enable=true - - traefik.docker.network=passbolt_frontend - - traefik.http.services.passbolt.loadbalancer.server.port=4433 - - traefik.http.services.passbolt.loadbalancer.server.scheme=https - - traefik.http.routers.passbolt-https.entrypoints=websecure - - traefik.http.routers.passbolt-https.rule=Host(`passbolt.$DOMAIN_NAME`) - - traefik.http.routers.passbolt-https.tls=true - - traefik.http.routers.passbolt-https.tls.certresolver=cloudflare - command: - [ - "/usr/bin/wait-for.sh", - "-t", - "0", - "passbolt-database:3306", - "--", - "/docker-entrypoint.sh", - ] - depends_on: - - passbolt-database - restart: unless-stopped - - passbolt-database: - image: mariadb:11.3 - container_name: passbolt-database - networks: - passbolt_backend: - volumes: - - passbolt-database:/var/lib/mysql - environment: - MYSQL_RANDOM_ROOT_PASSWORD: "true" - MYSQL_DATABASE: $PASSBOLT_MYSQL_DATABASE - MYSQL_USER: $PASSBOLT_MYSQL_USER - MYSQL_PASSWORD: $PASSBOLT_MYSQL_PASSWORD - restart: unless-stopped - - networks: - passbolt_backend: - external: true - passbolt_frontend: - external: true - - volumes: - passbolt-database: - passbolt-gpg: - passbolt-jwt: - ''; - - systemd.services."${container_name}" = { - description = "Podman container : ${container_name}"; - after = [ "network.target" "traefik.service" "pi-hole.service" ]; - requires = [ "traefik.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - TimeoutStartSec = "600"; - ExecStartPre = [ - "${pkgs.bash}/bin/bash -c 'sleep $((RANDOM % 180))'" - "-${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull" - ]; - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - - systemd.services."update-${container_name}" = { - description = "Update ${container_name} container"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.systemd}/bin/systemctl restart ${container_name}.service"; - }; - }; - - systemd.timers."update-${container_name}" = { - timerConfig = { - OnCalendar = "02:00"; - RandomizedDelaySec = "60m"; - Unit = "update-${container_name}.service"; - }; - wantedBy = [ "timers.target" ]; - }; - }; -} \ No newline at end of file diff --git a/modules/services/pi-hole.nix b/modules/services/pi-hole.nix deleted file mode 100644 index 3fd8833..0000000 --- a/modules/services/pi-hole.nix +++ /dev/null @@ -1,106 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "pi-hole"; - compose_file = "podman/pi-hole/compose.yaml"; - config_dir = "/mnt/config/pi-hole"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - services: - pihole: - image: docker.io/pihole/pihole:latest - container_name: pi-hole - networks: - pi-hole_frontend: - ports: - # DNS Ports - - "53:53/tcp" - - "53:53/udp" - environment: - TZ: $TZ - FTLCONF_webserver_api_password: $FTLCONF_webserver_api_password - FTLCONF_dns_hosts: | - $HOME_SERVER_IP frigate.$DOMAIN_NAME - $HOME_SERVER_IP gitea.$DOMAIN_NAME - $HOME_SERVER_IP home-assistant.$DOMAIN_NAME - $HOME_SERVER_IP immich.$DOMAIN_NAME - $HOME_SERVER_IP it-tools.$DOMAIN_NAME - $HOME_SERVER_IP nextcloud.$DOMAIN_NAME - $HOME_SERVER_IP nextcloud-aio.$DOMAIN_NAME - $HOME_SERVER_IP passbolt.$DOMAIN_NAME - $HOME_SERVER_IP pi-hole.$DOMAIN_NAME - $HOME_SERVER_IP traefik.$DOMAIN_NAME - FTLCONF_dhcp_active: "false" - FTLCONF_dns_upstreams: 9.9.9.9;149.112.112.112 - FTLCONF_ntp_ipv4_active: "false" - FTLCONF_ntp_ipv6_active: "false" - FTLCONF_ntp_sync_active: "false" - volumes: - - ${config_dir}:/etc/pihole - cap_add: - - SYS_NICE - labels: - - traefik.enable=true - - traefik.docker.network=pi-hole_frontend - - traefik.http.services.pihole.loadbalancer.server.port=80 - - traefik.http.services.pihole.loadbalancer.server.scheme=http - - traefik.http.routers.pihole-https.entrypoints=websecure - - traefik.http.routers.pihole-https.rule=Host(`pi-hole.$DOMAIN_NAME`) - - traefik.http.routers.pihole-https.tls=true - - traefik.http.routers.pihole-https.tls.certresolver=cloudflare - restart: unless-stopped - - networks: - pi-hole_frontend: - external: true - ''; - - systemd.services."${container_name}" = { - description = "Podman container : ${container_name}"; - after = [ "network.target" "traefik.service" ]; - requires = [ "traefik.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - TimeoutStartSec = "600"; - ExecStartPre = [ - "${pkgs.bash}/bin/bash -c 'sleep 20'" - "-${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull" - ]; - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - - systemd.services."update-${container_name}" = { - description = "Update ${container_name} container"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.systemd}/bin/systemctl restart ${container_name}.service"; - }; - }; - - systemd.timers."update-${container_name}" = { - timerConfig = { - OnCalendar = "02:00"; - RandomizedDelaySec = "60m"; - Unit = "update-${container_name}.service"; - }; - wantedBy = [ "timers.target" ]; - }; - }; -} diff --git a/modules/services/traefik.nix b/modules/services/traefik.nix deleted file mode 100644 index e8594f6..0000000 --- a/modules/services/traefik.nix +++ /dev/null @@ -1,64 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "traefik"; - compose_file = "podman/traefik/compose.yaml"; - config_dir = "/mnt/config/traefik"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - services: - traefik: - image: docker.io/library/traefik:latest - container_name: traefik - networks: -TRAEFIK_NETWORKS - ports: - - "80:80" - - "443:443" - volumes: - - /run/user/1000/podman/podman.sock:/run/docker.sock:ro - - ${config_dir}/rules/:/etc/traefik/conf/:ro - - ${config_dir}/traefik.yaml:/etc/traefik/traefik.yaml:ro - - ${config_dir}/certs/:/var/traefik/certs/:rw - environment: - - CF_DNS_API_TOKEN=$CF_DNS_API_TOKEN - labels: - - traefik.enable=true - - traefik.http.services.traefik.loadbalancer.server.port=8080 - - traefik.http.services.traefik.loadbalancer.server.scheme=http - - traefik.http.routers.traefik-https.entrypoints=websecure - - traefik.http.routers.traefik-https.rule=Host(`traefik.$DOMAIN_NAME`) - - traefik.http.routers.traefik-https.tls=true - - traefik.http.routers.traefik-https.tls.certresolver=cloudflare - restart: always - networks: -TRAEFIK_REF_NETWORKS - ''; - - systemd.services.traefik = { - description = "Podman container : ${container_name}"; - after = [ "numbus-activation.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - ExecStartPre = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull"; - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - }; -} \ No newline at end of file diff --git a/templates/nix-config/configuration.nix b/templates/nix-config/configuration.nix index 89a8377..0977db7 100644 --- a/templates/nix-config/configuration.nix +++ b/templates/nix-config/configuration.nix @@ -4,173 +4,31 @@ imports = [ (modulesPath + "/installer/scan/not-detected.nix") (modulesPath + "/profiles/qemu-guest.nix") - inputs.sops-nix.nixosModules.sops - ./disks/disko.nix - ./misc/activation.nix - ./misc/mail.nix - ./misc/networking.nix - ./misc/smart.nix - ./misc/terminal.nix -# ./disks/pcr-check.nix -# ./disks/snapraid.nix -# ./pcie-coral/coral.nix ]; - # Enable email notifications - email.enable = true; - - # Hardware settings - hardware.enableRedistributableFirmware = true; - hardware.cpu.intel.updateMicrocode = true; - hardware.cpu.amd.updateMicrocode = true; + # System + system.stateVersion = "25.11"; # Secrets management sops.defaultSopsFile = ./secrets/secrets.yaml; sops.age.sshKeyPaths = [ "/home/numbus-admin/.ssh/id_ed25519" ]; sops.age.keyFile = "/var/lib/sops-nix/key.txt"; - sops.secrets."ssh_public_keys" = { owner = "numbus-admin"; path = "/etc/ssh/authorized_keys.d/numbus-admin"; }; - sops.secrets."sender_email_address_password" = {}; - sops.secrets."domain_name" = {}; - sops.secrets."podman/frigate" = { owner = "numbus-admin"; path = "/etc/podman/frigate/.env"; }; - sops.secrets."podman/gitea" = { owner = "numbus-admin"; path = "/etc/podman/gitea/.env"; }; - sops.secrets."podman/home_assistant" = { owner = "numbus-admin"; path = "/etc/podman/home-assistant/.env"; }; - sops.secrets."podman/immich" = { owner = "numbus-admin"; path = "/etc/podman/immich/.env"; }; - sops.secrets."podman/it_tools" = { owner = "numbus-admin"; path = "/etc/podman/it-tools/.env"; }; - sops.secrets."podman/nextcloud" = { owner = "numbus-admin"; path = "/etc/podman/nextcloud/.env"; }; - sops.secrets."podman/passbolt" = { owner = "numbus-admin"; path = "/etc/podman/passbolt/.env"; }; - sops.secrets."podman/pi_hole" = { owner = "numbus-admin"; path = "/etc/podman/pi-hole/.env"; }; - sops.secrets."podman/traefik" = { owner = "numbus-admin"; path = "/etc/podman/traefik/.env"; }; - - # Bootloader options - boot.initrd.systemd.enable = true; - boot.loader.systemd-boot.enable = true; - boot.loader.efi.canTouchEfiVariables = true; - boot.swraid.mdadmConf = "MAILADDR ${config.email.userAddress},${config.email.adminAddress}"; -# boot.initrd.systemd.tpm2.enable = true; - - boot.kernel.sysctl = { - "vm.overcommit_memory" = 1; - }; + sops.secrets."ssh_public_keys" = { owner = "numbus-admin"; path = "/home/numbus-admin/.ssh/authorized_keys"; mode = "0600"; }; + sops.secrets."smtpPassword" = { owner = "numbus-admin"; mode = "0600"; }; + sops.secrets."cloudflareDnsApiToken" = { owner = "numbus-admin"; mode = "0600"; }; # # TPM2 PCR check # systemIdentity.enable = true; # systemIdentity.pcr15 = "PCR_HASH"; - # Timezone + # Server time.timeZone = "Europe/Paris"; + config.numbus.owner = "Raphael"; - # Internationalisation properties. - i18n.defaultLocale = "fr_FR.UTF-8"; - i18n.extraLocaleSettings = { - LC_ADDRESS = "fr_FR.UTF-8"; - LC_IDENTIFICATION = "fr_FR.UTF-8"; - LC_MEASUREMENT = "fr_FR.UTF-8"; - LC_MONETARY = "fr_FR.UTF-8"; - LC_NAME = "fr_FR.UTF-8"; - LC_NUMERIC = "fr_FR.UTF-8"; - LC_PAPER = "fr_FR.UTF-8"; - LC_TELEPHONE = "fr_FR.UTF-8"; - LC_TIME = "fr_FR.UTF-8"; - }; + # Enable email notifications + config.numbus.mail.enable = true; + config.numbus.mail.userAddress = "user@tunea.eu"; + config.numbus.mail.adminAddress = "admin@tunea.eu"; + config.numbus.mail.smtpUsername = "raphaels.server@gmail.com"; + config.numbus.mail.smtpPasswordPath = config.sops.secrets.smtpPassword.path; - # Keyboard mapping - console.keyMap = "fr"; - services.xserver.xkb = { - layout = "fr"; - variant = ""; - }; - - # Enable SSH - services.openssh.enable = true; - - # Allow unfree packages - nixpkgs.config.allowUnfree = true; - - # Install packages - environment.systemPackages = with pkgs; [ - git - ncdu - fastfetch - tpm2-tss - sops - age - powertop - pciutils - hdparm - hd-idle - hddtemp - smartmontools - cpufrequtils - intel-gpu-tools - podman - podman-compose - podman-tui - slirp4netns -# passt -# netavark -# aardvark-dns - snapraid - mergerfs - mergerfs-tools - ]; - - # Power savings - services.autoaspm.enable = true; - powerManagement.powertop.enable = true; - boot.kernelParams = [ - "pcie_aspm=force" - "consoleblank=60" - ]; - - # Enable cron service - services.cron = { - enable = true; - systemCronJobs = [ - ]; - }; - - # Enable Podman - virtualisation.podman.enable = true; - virtualisation.podman.defaultNetwork.settings.dns_enabled = true; - - # Enable libvirt -# virtualisation.libvirtd.enable = true; -# programs.virt-manager.enable = true; - - # User account - users.users.numbus-admin = { - shell = pkgs.fish; - isNormalUser = true; - description = "Numbus Admin"; - extraGroups = [ "wheel" ]; - uid = 1000; - initialPassword = "changeMe!"; - # required for auto start before user login - linger = true; - # required for rootless container with multiple users - autoSubUidGidRange = true; - }; - - # Enable auto updates - system.autoUpgrade = { - enable = true; - allowReboot = true; - flake = inputs.self.outPath; - flags = [ "--print-build-logs" ]; - dates = "02:00"; - randomizedDelaySec = "45min"; - }; - - nix.gc = { - automatic = true; - dates = "weekly"; - options = "--delete-older-than 7d"; - }; - - # Enable NixOS flakes - nix.settings.experimental-features = [ "nix-command" "flakes" ]; - # Enable auto nix-store optimization - nix.settings.auto-optimise-store = true; - - system.stateVersion = "25.11"; -} diff --git a/templates/nix-config/disks/boot-1.nix b/templates/nix-config/disks/boot-1.nix deleted file mode 100644 index 89af7e4..0000000 --- a/templates/nix-config/disks/boot-1.nix +++ /dev/null @@ -1,81 +0,0 @@ -{ - disko.devices = { - # Boot disk LVM configuration - lvm_vg = { - pool = { - type = "lvm_vg"; - lvs = { - swap = { - size = "16G"; - content = { - type = "swap"; - }; - }; - snapraid = { - size = "1G"; - content = { - type = "filesystem"; - format = "btrfs"; - mountpoint = "/mnt/content-0"; - }; - }; - root = { - size = "100%"; - content = { - type = "btrfs"; - extraArgs = [ "-f" ]; - subvolumes = { - "/rootfs" = { - mountpoint = "/"; - mountOptions = [ "compress=zstd" "noatime" ]; - }; - "/home" = { - mountpoint = "/home"; - mountOptions = [ "compress=zstd" ]; - }; - "/nix" = { - mountpoint = "/nix"; - mountOptions = [ "compress=zstd" "noatime" ]; - }; - }; - }; - }; - }; - }; - }; - disk = { - # Boot disk - "boot-1" = { - type = "disk"; - device = "$BOOT_DISK_1_ID"; - content = { - type = "gpt"; - partitions = { - ESP = { - size = "1G"; - type = "EF00"; - content = { - type = "filesystem"; - format = "vfat"; - mountpoint = "/boot"; - mountOptions = [ "umask=0077" ]; - }; - }; - luks = { - size = "100%"; - content = { - type = "luks"; - name = "crypted-boot-1"; - settings = { - keyFile = "/etc/secrets/disks/boot-1"; - allowDiscards = true; - }; - content = { - type = "lvm_pv"; - vg = "pool"; - }; - }; - }; - }; - }; - }; diff --git a/templates/nix-config/disks/boot-2.nix b/templates/nix-config/disks/boot-2.nix deleted file mode 100644 index cde81f9..0000000 --- a/templates/nix-config/disks/boot-2.nix +++ /dev/null @@ -1,125 +0,0 @@ -{ - disko.devices = { - mdadm = { - boot = { - type = "mdadm"; - level = 1; - metadata = "1.2"; - content = { - type = "filesystem"; - format = "vfat"; - mountpoint = "/boot"; - mountOptions = [ "umask=0077" ]; - }; - }; - }; - lvm_vg = { - pool = { - type = "lvm_vg"; - lvs = { - swap = { - size = "16G"; - lvm_type = "mirror"; - content = { - type = "swap"; - }; - }; - snapraid = { - size = "1G"; - lvm_type = "mirror"; - content = { - type = "filesystem"; - format = "btrfs"; - mountpoint = "/mnt/content-0"; - }; - }; - root = { - size = "100%"; - lvm_type = "mirror"; - content = { - type = "btrfs"; - extraArgs = [ "-f" ]; - subvolumes = { - "/rootfs" = { - mountpoint = "/"; - mountOptions = [ "compress=zstd" "noatime" ]; - }; - "/home" = { - mountpoint = "/home"; - mountOptions = [ "compress=zstd" ]; - }; - "/nix" = { - mountpoint = "/nix"; - mountOptions = [ "compress=zstd" "noatime" ]; - }; - }; - }; - }; - }; - }; - }; - disk = { - boot-1 = { - type = "disk"; - device = "$BOOT_DISK_1_ID"; - content = { - type = "gpt"; - partitions = { - ESP = { - size = "1G"; - type = "EF00"; - content = { - type = "mdraid"; - name = "boot"; - }; - }; - luks = { - size = "100%"; - content = { - type = "luks"; - name = "crypted-boot-1"; - settings = { - allowDiscards = true; - keyFile = "/etc/secrets/disks/boot-1"; - }; - content = { - type = "lvm_pv"; - vg = "pool"; - }; - }; - }; - }; - }; - }; - boot-2 = { - type = "disk"; - device = "$BOOT_DISK_2_ID"; - content = { - type = "gpt"; - partitions = { - ESP = { - size = "1G"; - type = "EF00"; - content = { - type = "mdraid"; - name = "boot"; - }; - }; - luks = { - size = "100%"; - content = { - type = "luks"; - name = "crypted-boot-2"; - settings = { - allowDiscards = true; - keyFile = "/etc/secrets/disks/boot-2"; - }; - content = { - type = "lvm_pv"; - vg = "pool"; - }; - }; - }; - }; - }; - }; diff --git a/templates/nix-config/disks/content.nix b/templates/nix-config/disks/content.nix deleted file mode 100644 index ca8c8d1..0000000 --- a/templates/nix-config/disks/content.nix +++ /dev/null @@ -1,28 +0,0 @@ - "content-${j}" = { - type = "disk"; - device = "${CONTENT_DISK_ID}"; - content = { - type = "gpt"; - partitions = { - luks = { - size = "100%"; - content = { - type = "luks"; - name = "crypted-content-${j}"; - initrdUnlock = false; - settings = { - keyFile = "/etc/secrets/disks/content-${j}"; - allowDiscards = ${ALLOW_DISCARDS:-false}; - crypttabExtraOpts = [ "nofail" "noauto" ]; - }; - content = { - type = "filesystem"; - format = "xfs"; - mountpoint = "/mnt/content-${j}"; - mountOptions = [ "nofail" "noauto" ]; - }; - }; - }; - }; - }; - }; diff --git a/templates/nix-config/disks/parity.nix b/templates/nix-config/disks/parity.nix deleted file mode 100644 index 56af6b9..0000000 --- a/templates/nix-config/disks/parity.nix +++ /dev/null @@ -1,28 +0,0 @@ - "parity-${j}" = { - type = "disk"; - device = "${PARITY_DISK_ID}"; - content = { - type = "gpt"; - partitions = { - luks = { - size = "100%"; - content = { - type = "luks"; - name = "crypted-parity-${j}"; - initrdUnlock = false; - settings = { - keyFile = "/etc/secrets/disks/parity-${j}"; - allowDiscards = ${ALLOW_DISCARDS:-false}; - crypttabExtraOpts = [ "nofail" "noauto" ]; - }; - content = { - type = "filesystem"; - format = "xfs"; - mountpoint = "/mnt/parity-${j}"; - mountOptions = [ "nofail" "noauto" ]; - }; - }; - }; - }; - }; - }; diff --git a/templates/nix-config/disks/pcr-check.nix b/templates/nix-config/disks/pcr-check.nix deleted file mode 100644 index 16d2a9a..0000000 --- a/templates/nix-config/disks/pcr-check.nix +++ /dev/null @@ -1,124 +0,0 @@ -{ lib, utils, config, ... }: - -let - inherit (lib) - head - optional - foldl' - nameValuePair - listToAttrs - optionals - concatStringsSep - sortOn - mkIf - mkEnableOption - mkOption - types - ; -in - -{ - options = { - systemIdentity = { - enable = mkEnableOption "hashing of Luks values into PCR 15 and subsequent checks"; - pcr15 = mkOption { - type = types.nullOr types.str; - default = null; - description = '' - The expected value of PCR 15 after all luks partitions have been unlocked - Should be a 64 character hex string as ouput by the sha256 field of - 'systemd-analyze pcrs 15 --json=short' - If set to null (the default) it will not check the value. - If the check fails the boot will abort and you will be dropped into an emergency shell, if enabled. - In ermergency shell type: - 'systemctl disable check-pcrs' - 'systemctl default' - to continue booting - ''; - }; - }; - boot.initrd.luks.devices = lib.mkOption { - type = - with lib.types; - attrsOf (submodule { - config.crypttabExtraOpts = optionals config.systemIdentity.enable [ - "tpm2-device=auto" - "tpm2-measure-pcr=yes" - ]; - }); - }; - }; - config = mkIf config.systemIdentity.enable { - boot.kernelParams = [ - "rd.luks=no" - ]; - boot.initrd.systemd.services = - { - check-pcrs = mkIf (config.systemIdentity.pcr15 != null) { - script = '' - echo "Checking PCR 15 value" - if [[ $(systemd-analyze pcrs 15 --json=short | jq -r ".[0].sha256") != "${config.systemIdentity.pcr15}" ]] ; then - echo "PCR 15 check failed" - exit 1 - else - echo "PCR 15 check succeeded" - fi - ''; - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - }; - unitConfig.DefaultDependencies = "no"; - after = [ "cryptsetup.target" ]; - before = [ "sysroot.mount" ]; - requiredBy = [ "sysroot.mount" ]; - }; - } - // (listToAttrs ( - foldl' ( - acc: attrs: - let - extraOpts = attrs.value.crypttabExtraOpts ++ (optional attrs.value.allowDiscards "discard"); - cfg = config.boot.initrd.systemd; - in - [ - (nameValuePair "cryptsetup-${attrs.name}" { - unitConfig = { - Description = "Cryptography setup for ${attrs.name}"; - DefaultDependencies = "no"; - IgnoreOnIsolate = true; - Conflicts = [ "umount.target" ]; - BindsTo = "${utils.escapeSystemdPath attrs.value.device}.device"; - }; - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - TimeoutSec = "infinity"; - KeyringMode = "shared"; - OOMScoreAdjust = 500; - ImportCredential = "cryptsetup.*"; - ExecStart = ''${cfg.package}/bin/systemd-cryptsetup attach '${attrs.name}' '${attrs.value.device}' '-' '${concatStringsSep "," extraOpts}' ''; - ExecStop = ''${cfg.package}/bin/systemd-cryptsetup detach '${attrs.name}' ''; - }; - after = - [ - "cryptsetup-pre.target" - "systemd-udevd-kernel.socket" - "${utils.escapeSystemdPath attrs.value.device}.device" - ] - ++ (optional cfg.tpm2.enable "systemd-tpm2-setup-early.service") - ++ optional (acc != [ ]) "${(head acc).name}.service"; - before = [ - "blockdev@dev-mapper-${attrs.name}.target" - "cryptsetup.target" - "umount.target" - ]; - wants = [ "blockdev@dev-mapper-${attrs.name}.target" ]; - requiredBy = [ "sysroot.mount" ]; - }) - ] - ++ acc - ) [ ] (sortOn (x: x.name) (lib.attrsets.attrsToList config.boot.initrd.luks.devices)) - )); - }; -} diff --git a/templates/nix-config/disks/snapraid.nix b/templates/nix-config/disks/snapraid.nix deleted file mode 100644 index 593a3f0..0000000 --- a/templates/nix-config/disks/snapraid.nix +++ /dev/null @@ -1,60 +0,0 @@ -{ config, lib, pkgs, ... }: - -{ -### --> MergerFS setup - fileSystems."/mnt/data" = { - device = "/mnt/content-*"; - fsType = "fuse.mergerfs"; - options = [ - "category.create=ff" - "cache.files=partial" - "dropcacheonclose=true" - "defaults" - "noauto" - "nofail" - "allow_other" - "moveonenospc=1" - "minfreespace=50G" - "func.getattr=newest" - "fsname=mergerfs_data" - "x-mount.mkdir" - "x-systemd.automount" - "x-systemd.requires=mount-dependencies.service" - ]; - }; -### MergerFS setup <-- - - systemd.services.mount-dependencies = { - description = "This service will mount the encrypted disks for mergerFS"; - after = [ "network.target" ]; - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - # Bring the service up - ExecStart = pkgs.writeShellScript "mount-disks" '' -$MOUNT_DEPENDENCIES_START - ''; - # Take it down gracefully - ExecStop = pkgs.writeShellScript "unmount-disks" '' -$MOUNT_DEPENDENCIES_STOP - ''; - Restart = "on-failure"; - }; - }; - -### --> SnapRAID setup - services.snapraid = { - enable = true; - contentFiles = [ -$SNAPRAID_CONTENT_FILES - ]; - parityFiles = [ -$SNAPRAID_PARITY_FILES - ]; - dataDisks = { -$SNAPRAID_DATA_DISKS - }; - }; -### SnapRAID setup <-- -} \ No newline at end of file diff --git a/templates/nix-config/disks/spindown.nix b/templates/nix-config/disks/spindown.nix deleted file mode 100644 index d74ee1c..0000000 --- a/templates/nix-config/disks/spindown.nix +++ /dev/null @@ -1,25 +0,0 @@ -{ config, pkgs, lib, ... }: - -let - hardDrives = [ -DISK_LIST - ]; -in - -{ -### --> Disk spindown - systemd.services.hd-idle = { - description = "External HD spin down daemon"; - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - Type = "simple"; - ExecStart = - let - idleTime = toString 1800; - hardDriveParameter = lib.strings.concatMapStringsSep " " (x: "-a ${x} -i ${idleTime}") hardDrives; - in - "${pkgs.hd-idle}/bin/hd-idle -i 0 ${hardDriveParameter}"; - }; - }; -### Disk spindown <-- -} \ No newline at end of file diff --git a/templates/nix-config/flake.nix b/templates/nix-config/flake.nix index 3091cb1..5799aae 100644 --- a/templates/nix-config/flake.nix +++ b/templates/nix-config/flake.nix @@ -2,6 +2,9 @@ inputs = { # Core Nixpkgs nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; + # Numbus server configuration + numbus.url = "git+https://gittea.dev/numbus/numbus-server-module"; + numbus.inputs.nixpkgs.follows = "nixpkgs"; # Disk-partitioning helper disko.url = "github:nix-community/disko"; disko.inputs.nixpkgs.follows = "nixpkgs"; @@ -13,27 +16,20 @@ autoaspm.inputs.nixpkgs.follows = "nixpkgs"; }; - outputs = { self, nixpkgs, disko, sops-nix, autoaspm, ... }@inputs: let + outputs = { self, nixpkgs, numbus, disko, sops-nix, autoaspm, ... }@inputs: let # System definition system = "x86_64-linux"; pkgs = import nixpkgs { inherit system; config.allowUnfree = true; }; - - # Helper: collect every *.nix file inside ./podman as a list - podmanModules = let - dir = ./podman; - entries = builtins.readDir dir; - names = builtins.attrNames entries; - nixNames = builtins.filter (n: builtins.match ".*\\.nix" n != null) names; - in map (name: "${dir}/${name}") nixNames; - in { nixosConfigurations = { numbus-server = nixpkgs.lib.nixosSystem { inherit system; specialArgs = { inherit inputs; }; modules = [ + # Numbus server configuration + numbus.nixosModules.numbus # Disk-partitioning helper disko.nixosModules.disko # Secrets handling @@ -43,8 +39,7 @@ # Core host configuration ./configuration.nix ./hardware-configuration.nix - # Podman services - automatically added from ./podman/*.nix - ] ++ podmanModules; + ] }; }; }; diff --git a/templates/nix-config/misc/activation.nix b/templates/nix-config/misc/activation.nix deleted file mode 100644 index a3d5737..0000000 --- a/templates/nix-config/misc/activation.nix +++ /dev/null @@ -1,129 +0,0 @@ -{ config, pkgs, ... }: - -{ - systemd.services.numbus-activation = { - description = "Numbus-Server activation : Correct permissions"; - wantedBy = [ "multi-user.target" "traefik.service" ]; - after = [ "network.target" "local-fs.target" ]; - path = [ pkgs.coreutils pkgs.podman pkgs.sudo ]; - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - }; - script = '' - #!/usr/bin/env bash - - if [[ -e /home/numbus-admin/.numbus-server/activated.true ]]; then - echo "Already activated" - exit 0 - fi - - echo "Creating directories with correct permissions..." - mkdir -p /mnt/config/ /mnt/data/ /mnt/data/nextcloud/ - mkdir -p /home/numbus-admin/.numbus-server/ - chown -R numbus-admin:users /mnt/config/ - chown -R numbus-admin:users /mnt/data/ - chown -R 100032:100032 /mnt/data/nextcloud/ - - echo "Creating podman networks..." - export PATH=$PATH:/run/wrappers/bin - -PODMAN_NETWORKS - - mkdir -p /home/numbus-admin/.numbus-server/ - touch /home/numbus-admin/.numbus-server/activated.true - chown -R numbus-admin:users /home/numbus-admin/.numbus-server/ - echo "Activated successfully !" - ''; - }; - - systemd.services.numbus-quirks = { - description = "Numbus-Server services : Apply quirks"; - wantedBy = [ "multi-user.target" ]; - after = [ - "network.target" - "local-fs.target" - "numbus-activation-chowned.service" - "numbus-activation-networked.service" - "pi-hole.service" - "home-assistant.service" - ]; - path = [ pkgs.curl pkgs.coreutils pkgs.systemd pkgs.podman pkgs.sudo ]; - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - }; - script = '' - #!/usr/bin/env bash - set -euo pipefail - - if [[ -e /home/numbus-admin/.numbus-server/quirked.true ]]; then - echo "Quirks already applied" - exit 0 - fi - - DOMAIN_NAME="$(cat /run/secrets/domain_name)" - - if [[ -e /etc/nixos/podman/pi-hole.nix ]]; then - echo "Applying Pi-Hole quirks..." - mkdir -p /mnt/config/pi-hole/ - chown -R numbus-admin:users /mnt/config/pi-hole/ - echo "Waiting for Pi-hole to be ready..." - until [[ -e /mnt/config/pi-hole/pihole-FTL.db ]]; do - sleep 15 - done - sleep 60 - sudo -u numbus-admin podman exec pi-hole pihole -g - sleep 60 - systemctl restart pi-hole.service - echo "Pi-Hole quirk applied and service ready !" - fi - - if [[ -e /etc/nixos/podman/home-assistant.nix ]]; then - echo "Applying Home Assistant quirks..." - mkdir -p /mnt/config/home-assistant/ - chown -R numbus-admin:users /mnt/config/home-assistant/ - echo "Waiting for Home Assistant to be ready..." - until [[ -e /mnt/config/home-assistant/configuration.yaml ]]; do - sleep 15 - done - sleep 180 - systemctl stop home-assistant.service - cat << 'EOF' >> /mnt/config/home-assistant/configuration.yaml - -http: - use_x_forwarded_for: true - trusted_proxies: 10.89.0.0/16 - -zha: -EOF - systemctl start home-assistant.service - echo "Home Assistant quirk applied and service ready !" - fi - - if [[ -e /etc/nixos/podman/frigate.nix ]]; then - echo "Applying Frigate quirks..." - mkdir -p /mnt/config/frigate/ - chown -R numbus-admin:users /mnt/config/frigate/ - echo "Waiting for Frigate to be ready..." - until [[ -e /mnt/config/frigate/config.yaml ]]; do - sleep 15 - done - sleep 180 - systemctl stop frigate.service - cat << 'EOF' >> /mnt/config/frigate/config.yaml - -tls: - enabled: false -EOF - systemctl start frigate.service - echo "Frigate quirk applied and service ready !" - fi - - mkdir -p /home/numbus-admin/.numbus-server/ - touch /home/numbus-admin/.numbus-server/quirked.true - chown -R numbus-admin:users /home/numbus-admin/.numbus-server/ - echo "Quirks applied successfully !" - ''; - }; -} \ No newline at end of file diff --git a/templates/nix-config/misc/mail.nix b/templates/nix-config/misc/mail.nix deleted file mode 100644 index 4fcfa67..0000000 --- a/templates/nix-config/misc/mail.nix +++ /dev/null @@ -1,74 +0,0 @@ -{ config, pkgs, lib, ... }: - -let - cfg = config.email; -in - -### --> Mail notifications configuration -{ - options.email = { - enable = lib.mkEnableOption "Email sending functionality"; - fromAddress = lib.mkOption { - description = "The 'from' address"; - type = lib.types.str; - default = "no-reply@DOMAIN_NAME"; - }; - userAddress = lib.mkOption { - description = "The 'to' address"; - type = lib.types.str; - default = "EMAIL_ADDRESS"; - }; - adminAddress = lib.mkOption { - description = "The admin email address to receive alerts in copy"; - type = lib.types.str; - default = "admin@numbus.eu"; - }; - smtpServer = lib.mkOption { - description = "The SMTP server address"; - type = lib.types.str; - default = "SENDER_MAIL_DOMAIN"; - }; - smtpPort = lib.mkOption { - description = "The SMTP port"; - type = lib.types.port; - default = 465; - }; - smtpUsername = lib.mkOption { - description = "The SMTP username"; - type = lib.types.str; - default = "SENDER_MAIL_ADDRESS"; - }; - smtpPasswordPath = lib.mkOption { - description = "Path to the secret containing SMTP password"; - type = lib.types.path; - default = config.sops.secrets.sender_email_address_password.path; - }; - }; - - config = lib.mkIf cfg.enable { - environment.etc."aliases".text = '' - root: ${config.email.userAddress}, ${config.email.adminAddress} - default: ${config.email.userAddress}, ${config.email.adminAddress} - ''; - - programs.msmtp = { - enable = true; - defaults = { - aliases = "/etc/aliases"; - timeout = 60; - syslog = "on"; - }; - accounts.default = { - auth = true; - host = config.email.smtpServer; - port = config.email.smtpPort; - from = config.email.fromAddress; - user = config.email.smtpUsername; - tls = true; - tls_starttls = false; - passwordeval = "${pkgs.coreutils}/bin/cat ${config.email.smtpPasswordPath}"; - }; - }; - }; -### Mail notifications configuration <-- -} \ No newline at end of file diff --git a/templates/nix-config/misc/networking.nix b/templates/nix-config/misc/networking.nix deleted file mode 100644 index 4049b50..0000000 --- a/templates/nix-config/misc/networking.nix +++ /dev/null @@ -1,35 +0,0 @@ -{ config, pkgs, lib, ... }: - -{ - # Hostname - networking.hostName = "numbus-server"; - - networking.networkmanager.enable = false; - - # Allow rootless containers to bind to port 53 and up - boot.kernel.sysctl."net.ipv4.ip_unprivileged_port_start" = 53; - - # Bridge configuration for VMs - networking.bridges.br0.interfaces = [ "TARGET_INTERFACE" ]; - networking.interfaces."TARGET_INTERFACE".useDHCP = false; - networking.interfaces.br0.useDHCP = false; - networking.nameservers = [ "HOME_SERVER_IP" "9.9.9.9" ]; - networking.interfaces.br0.ipv4.addresses = [{ - address = "HOME_SERVER_IP"; - prefixLength = 24; - }]; - networking.defaultGateway = { - address = "HOME_ROUTER_IP"; - interface = "br0"; - }; - - networking.nftables.enable = true; - - # Open ports in the firewall - networking.firewall = { - enable = true; - allowPing = true; - allowedTCPPorts = [ 53 80 443 ]; - allowedUDPPorts = [ 53 443 ]; - }; -} \ No newline at end of file diff --git a/templates/nix-config/misc/smart.nix b/templates/nix-config/misc/smart.nix deleted file mode 100644 index ca20ba5..0000000 --- a/templates/nix-config/misc/smart.nix +++ /dev/null @@ -1,62 +0,0 @@ -{ config, pkgs, ... }: - -let - smartd_notifier = pkgs.writeScript "smartd-notify.sh" '' - #!${pkgs.bash}/bin/bash - - # 1. Send Technical Email to Admin - ADMIN_EMAIL="${config.email.adminAddress}" - SUBJECT="Numbus Server Alert: $SMARTD_FAILTYPE on $SMARTD_DEVICE" - - TECH_BODY=" - SMARTD Alert Details: - Server owner: $OWNER_NAME - Device: $SMARTD_DEVICE - Type: $SMARTD_DEVICETYPE - Failure Type: $SMARTD_FAILTYPE - Message: $SMARTD_MESSAGE - - Full Message: - $SMARTD_FULLMESSAGE - " - printf "Subject: [ADMIN] $SUBJECT\n\n$TECH_BODY" | /run/wrappers/bin/sendmail -t "$ADMIN_EMAIL" - - # 2. Send Friendly Email to Owner - USER_EMAIL="${config.email.userAddress}" - OWNER_NAME=$(cat /etc/numbus-server/owner 2>/dev/null || echo "User") - - FRIENDLY_BODY="Cher/Chère $OWNER_NAME, - - Votre serveur a automatiquement détecté une panne matérielle de disque dur. - Ce genre de panne est tout à fait normal selon l'âge de votre matériel et n'entraîne - dans la grande majorité des cas aucune perte de données grâce au système de - stockage redondant préventif. - - Votre administrateur a été notifié de cette panne. Il vous recontactera dans de très - brefs délais afin de procéder au remplacement, si nécessaire, du disque dur défaillant. - - Merci de votre confiance, - L'équipe de support, - Numbus-Server." - - printf "Subject: [Alerte] Défaillance matérielle sur votre serveur Numbus\n\n$FRIENDLY_BODY" | /run/wrappers/bin/sendmail -t "$USER_EMAIL" - ''; -in -{ -### --> SMART disk heath - services.smartd = { - enable = true; - defaults.autodetected = "-a -o on -S on -s (S/../.././00|L/../../6/01) -n standby,q -M exec ${smartd_notifier}"; - notifications = { - wall = { - enable = true; - }; - mail = { - enable = true; - sender = config.email.fromAddress; - recipient = "${config.email.userAddress},${config.email.adminAddress}"; - }; - }; - }; -### SMART disk heath <-- -} \ No newline at end of file diff --git a/templates/nix-config/misc/terminal.nix b/templates/nix-config/misc/terminal.nix deleted file mode 100644 index 27ab46b..0000000 --- a/templates/nix-config/misc/terminal.nix +++ /dev/null @@ -1,43 +0,0 @@ -{ config, pkgs, ... }: - -{ - environment.systemPackages = with pkgs; [ - fish - fishPlugins.fzf-fish - fishPlugins.grc - grc - fzf - ]; - - programs.fish = { - enable = true; - interactiveShellInit = '' - set fish_greeting # Disable greeting - fastfetch - echo -e "\n\nWelcome to your Numbus-Server !\n\n- This system is managed by NixOS\n- All changes are futile\n- Please consider buying support if you can't get your server running\n- Have a nice day and enjoy !" - ''; - shellAliases = { - nixup = "cd /etc/nixos/ && sudo nix flake update && sudo nixos-rebuild --flake . switch --upgrade && cd -"; - nixwitch = "cd /etc/nixos/ && sudo nix flake update && sudo nixos-rebuild --flake . switch && cd -"; - systraefik = "sudo systemctl status traefik.service"; - syspi-hole = "sudo systemctl status pi-hole.service"; - syspassbolt = "sudo systemctl status passbolt.service"; - sysnextcloud = "sudo systemctl status nextcloud.service"; - sysit-tools = "sudo systemctl status it-tools.service"; - sysimmich = "sudo systemctl status immich.service"; - syshome-assistant = "sudo systemctl status home-assistant.service"; - sysgitea = "sudo systemctl status gitea.service"; - sysfrigate = "sudo systemctl status frigate.service"; - }; - }; - -# # Login message -# environment.loginShellInit = '' -# if [ "$(id -u)" -eq 1000 ]; then -# if [ -n "$SSH_TTY" ]; then -# fastfetch -# echo -e "\n\nWelcome to your Numbus-Server !\n\n- This system is managed by NixOS\n- All changes are futile\n- Please consider buying support if you can't get your server running\n- Have a nice day and enjoy !" -# fi -# fi -# ''; -} \ No newline at end of file diff --git a/templates/nix-config/podman/activation.nix b/templates/nix-config/podman/activation.nix deleted file mode 100644 index e69de29..0000000 diff --git a/templates/nix-config/podman/adguard.coming b/templates/nix-config/podman/adguard.coming deleted file mode 100644 index e3adc73..0000000 --- a/templates/nix-config/podman/adguard.coming +++ /dev/null @@ -1,59 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "adguard"; - compose_file = "podman/adguard/compose.yaml"; - config_dir = "/mnt/config/adguard"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - ''; - - systemd.services."${container_name}" = { - description = "Podman container : ${container_name}"; - after = [ "network.target" ]; - requires = [ "traefik.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - TimeoutStartSec = "600"; - ExecStartPre = [ - "${pkgs.bash}/bin/bash -c 'sleep $((RANDOM % 180))'" - "-${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull" - ]; - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - - systemd.services."update-${container_name}" = { - description = "Update ${container_name} container"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.systemd}/bin/systemctl restart ${container_name}.service"; - }; - }; - - systemd.timers."update-${container_name}" = { - timerConfig = { - OnCalendar = "02:00"; - RandomizedDelaySec = "60m"; - Unit = "update-${container_name}.service"; - }; - wantedBy = [ "timers.target" ]; - }; - }; -} \ No newline at end of file diff --git a/templates/nix-config/podman/frigate.nix b/templates/nix-config/podman/frigate.nix deleted file mode 100644 index ff82aa3..0000000 --- a/templates/nix-config/podman/frigate.nix +++ /dev/null @@ -1,98 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "frigate"; - compose_file = "podman/frigate/compose.yaml"; - config_dir = "/mnt/config/frigate"; - data_dir = "/mnt/data/frigate"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - services: - frigate: - image: ghcr.io/blakeblackshear/frigate:stable - container_name: frigate - shm_size: "512MB" - networks: - home-assistant_frontend: - home-assistant_backend: - volumes: - - ${config_dir}:/config - - ${data_dir}/clips:/media/frigate/clips - - ${data_dir}/recordings:/media/frigate/recordings - - ${data_dir}/exports:/media/frigate/exports - - /etc/localtime:/etc/localtime:ro - - type: tmpfs - target: /tmp/cache - tmpfs: - size: 2000000000 - environment: - FRIGATE_MQTT_USER: $FRIGATE_MQTT_USER - FRIGATE_MQTT_PASSWORD: $FRIGATE_MQTT_PASSWORD - # --- frigate devices --- # - labels: - - traefik.enable=true - - traefik.docker.network=home-assistant_frontend - - traefik.http.services.frigate.loadbalancer.server.port=8971 - - traefik.http.services.frigate.loadbalancer.server.scheme=http - - traefik.http.routers.frigate-https.entrypoints=websecure - - traefik.http.routers.frigate-https.rule=Host(`frigate.$DOMAIN_NAME`) - - traefik.http.routers.frigate-https.tls=true - - traefik.http.routers.frigate-https.tls.certresolver=cloudflare - restart: unless-stopped - - networks: - home-assistant_backend: - external: true - home-assistant_frontend: - external: true - ''; - - systemd.services."${container_name}" = { - description = "Podman container : ${container_name}"; - after = [ "traefik.service" "home-assistant.service" "pi-hole.service" ]; - requires = [ "traefik.service" "home-assistant.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - TimeoutStartSec = "600"; - ExecStartPre = [ - "${pkgs.bash}/bin/bash -c 'sleep $((RANDOM % 180))'" - "-${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull" - ]; - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - - systemd.services."update-${container_name}" = { - description = "Update ${container_name} container"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.systemd}/bin/systemctl restart ${container_name}.service"; - }; - }; - - systemd.timers."update-${container_name}" = { - timerConfig = { - OnCalendar = "02:00"; - RandomizedDelaySec = "60m"; - Unit = "update-${container_name}.service"; - }; - wantedBy = [ "timers.target" ]; - }; - }; -} \ No newline at end of file diff --git a/templates/nix-config/podman/gitea.nix b/templates/nix-config/podman/gitea.nix deleted file mode 100644 index 0b21a15..0000000 --- a/templates/nix-config/podman/gitea.nix +++ /dev/null @@ -1,113 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "gitea"; - compose_file = "podman/gitea/compose.yaml"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - services: - gitea: - image: docker.io/gitea/gitea:latest - container_name: gitea - networks: - gitea_frontend: - gitea_backend: - volumes: - - gitea_data:/data - - /etc/localtime:/etc/localtime:ro - environment: - - USER_UID=1000 - - USER_GID=1000 - - GITEA__database__DB_TYPE=postgres - - GITEA__database__HOST=$POSTGRES_HOST:$POSTGRES_PORT - - GITEA__database__NAME=$DB_NAME - - GITEA__database__USER=$DB_USERNAME - - GITEA__database__PASSWD=$DB_PASSWORD - - GITEA__server__SSH_PORT=2424 - - GITEA__server__ROOT_URL=gitea.$DOMAIN_NAME - labels: - - traefik.enable=true - - traefik.docker.network=gitea_frontend - - traefik.http.services.gitea.loadbalancer.server.port=3000 - - traefik.http.services.gitea.loadbalancer.server.scheme=http - - traefik.http.routers.gitea-https.entrypoints=websecure - - traefik.http.routers.gitea-https.rule=Host(`gitea.$DOMAIN_NAME`) - - traefik.http.routers.gitea-https.tls=true - - traefik.http.routers.gitea-https.tls.certresolver=cloudflare - depends_on: - - gitea-database - restart: unless-stopped - - gitea-database: - image: docker.io/library/postgres:17.5 - container_name: gitea-database - environment: - - POSTGRES_USER=$DB_USERNAME - - POSTGRES_PASSWORD=$DB_PASSWORD - - POSTGRES_DB=$DB_NAME - networks: - gitea_backend: - volumes: - - gitea_database:/var/lib/postgresql/data - restart: unless-stopped - - volumes: - gitea_data: - gitea_database: - - networks: - gitea_frontend: - external: true - gitea_backend: - external: true - ''; - - systemd.services."${container_name}" = { - description = "Podman container : ${container_name}"; - after = [ "network.target" "traefik.service" "pi-hole.service" ]; - requires = [ "traefik.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - TimeoutStartSec = "900"; - ExecStartPre = [ - "${pkgs.bash}/bin/bash -c 'sleep $((RANDOM % 400))'" - "-${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull" - ]; - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - - systemd.services."update-${container_name}" = { - description = "Update ${container_name} container"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.systemd}/bin/systemctl restart ${container_name}.service"; - }; - }; - - systemd.timers."update-${container_name}" = { - timerConfig = { - OnCalendar = "02:00"; - RandomizedDelaySec = "60m"; - Unit = "update-${container_name}.service"; - }; - wantedBy = [ "timers.target" ]; - }; - }; -} \ No newline at end of file diff --git a/templates/nix-config/podman/home-assistant.nix b/templates/nix-config/podman/home-assistant.nix deleted file mode 100644 index af89e46..0000000 --- a/templates/nix-config/podman/home-assistant.nix +++ /dev/null @@ -1,83 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "home-assistant"; - compose_file = "podman/home-assistant/compose.yaml"; - config_dir_1 = "/mnt/config/home-assistant"; - config_dir_2 = "/mnt/config/mqtt"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - services: - home-assistant: - image: ghcr.io/home-assistant/home-assistant:latest - container_name: home-assistant - networks: - home-assistant_frontend: - home-assistant_backend: - volumes: - - ${config_dir_1}:/config - - /etc/localtime:/etc/localtime:ro - - /run/dbus:/run/dbus:ro - # --- home-assistant devices --- # - labels: - - traefik.enable=true - - traefik.docker.network=home-assistant_frontend - - traefik.http.services.home-assistant.loadbalancer.server.port=8123 - - traefik.http.services.home-assistant.loadbalancer.server.scheme=http - - traefik.http.routers.home-assistant-https.entrypoints=websecure - - traefik.http.routers.home-assistant-https.rule=Host(`home-assistant.$DOMAIN_NAME`) - - traefik.http.routers.home-assistant-https.tls=true - - traefik.http.routers.home-assistant-https.tls.certresolver=cloudflare - restart: unless-stopped - - frigate-mqtt: - image: eclipse-mosquitto - container_name: mqtt - user: 1000:1000 - networks: - home-assistant_backend: - volumes: - - ${config_dir_2}:/mosquitto - restart: unless-stopped - - networks: - home-assistant_backend: - external: true - home-assistant_frontend: - external: true - ''; - systemd.services.${container_name} = { - description = "Podman container : ${container_name}"; - after = [ "network.target" "traefik.service" "pi-hole.service" ]; - requires = [ "traefik.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - TimeoutStartSec = "600"; - # Pull the latest image before running - ExecStartPre = [ - "${pkgs.coreutils}/bin/sleep 180" - "-${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull" - ]; - # Bring the service up - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - # Take it down gracefully - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - }; -} \ No newline at end of file diff --git a/templates/nix-config/podman/immich.nix b/templates/nix-config/podman/immich.nix deleted file mode 100644 index 746c6c2..0000000 --- a/templates/nix-config/podman/immich.nix +++ /dev/null @@ -1,134 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "immich"; - compose_file = "podman/immich/compose.yaml"; - config_dir = "/mnt/config/immich"; - data_dir = "/mnt/data/immich"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - services: - immich-server: - image: ghcr.io/immich-app/immich-server:$IMMICH_VERSION - container_name: immich-server - networks: - immich_frontend: - immich_backend: - volumes: - - $UPLOAD_LOCATION:/data - - /etc/localtime:/etc/localtime:ro - # --- immich devices --- # - labels: - - traefik.enable=true - - traefik.docker.network=immich_frontend - - traefik.http.services.immich.loadbalancer.server.port=2283 - - traefik.http.services.immich.loadbalancer.server.scheme=http - - traefik.http.routers.immich-https.entrypoints=websecure - - traefik.http.routers.immich-https.rule=Host(`immich.$DOMAIN_NAME`) - - traefik.http.routers.immich-https.tls=true - - traefik.http.routers.immich-https.tls.certresolver=cloudflare - env_file: - - .env - depends_on: - - immich-redis - - immich-database - restart: always - healthcheck: - disable: false - - immich-machine-learning: - container_name: immich-machine-learning - image: ghcr.io/immich-app/immich-machine-learning:$IMMICH_VERSION - networks: - immich_backend: - volumes: - - ${config_dir}/models:/cache - env_file: - - .env - restart: always - healthcheck: - disable: false - - immich-redis: - container_name: immich-redis - image: docker.io/valkey/valkey:8-bookworm@sha256:a137a2b60aca1a75130022d6bb96af423fefae4eb55faf395732db3544803280 - networks: - immich_backend: - healthcheck: - test: redis-cli ping || exit 1 - restart: always - - immich-database: - container_name: immich-database - image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:32324a2f41df5de9efe1af166b7008c3f55646f8d0e00d9550c16c9822366b4a - networks: - immich_backend: - shm_size: 128mb - volumes: - # Do not edit the next line. If you want to change the database storage location on your system, edit the value of DB_DATA_LOCATION in the .env file - - $DB_DATA_LOCATION:/var/lib/postgresql/data - environment: - POSTGRES_PASSWORD: $DB_PASSWORD - POSTGRES_USER: $DB_USERNAME - POSTGRES_DB: $DB_DATABASE_NAME - POSTGRES_INITDB_ARGS: '--data-checksums' - restart: always - healthcheck: - disable: false - - networks: - immich_backend: - external: true - immich_frontend: - external: true - ''; - - systemd.services."${container_name}" = { - description = "Podman container : ${container_name}"; - after = [ "network.target" "traefik.service" "pi-hole.service" ]; - requires = [ "traefik.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - TimeoutStartSec = "900"; - ExecStartPre = [ - "${pkgs.bash}/bin/bash -c 'sleep $((RANDOM % 400))'" - "-${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull" - ]; - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - - systemd.services."update-${container_name}" = { - description = "Update ${container_name} container"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.systemd}/bin/systemctl restart ${container_name}.service"; - }; - }; - - systemd.timers."update-${container_name}" = { - timerConfig = { - OnCalendar = "02:00"; - RandomizedDelaySec = "60m"; - Unit = "update-${container_name}.service"; - }; - wantedBy = [ "timers.target" ]; - }; - }; -} \ No newline at end of file diff --git a/templates/nix-config/podman/it-tools.nix b/templates/nix-config/podman/it-tools.nix deleted file mode 100644 index ee29889..0000000 --- a/templates/nix-config/podman/it-tools.nix +++ /dev/null @@ -1,77 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "it-tools"; - compose_file = "podman/it-tools/compose.yaml"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - services: - it-tools: - container_name: it-tools - image: corentinth/it-tools - networks: - it-tools_frontend: - labels: - - traefik.enable=true - - traefik.docker.network=it-tools_frontend - - traefik.http.services.it-tools.loadbalancer.server.port=80 - - traefik.http.services.it-tools.loadbalancer.server.scheme=http - - traefik.http.routers.it-tools-https.entrypoints=websecure - - traefik.http.routers.it-tools-https.rule=Host(`it-tools.$DOMAIN_NAME`) - - traefik.http.routers.it-tools-https.tls=true - - traefik.http.routers.it-tools-https.tls.certresolver=cloudflare - restart: unless-stopped - networks: - it-tools_frontend: - external: true - ''; - - systemd.services."${container_name}" = { - description = "Podman container : ${container_name}"; - after = [ "network.target" "traefik.service" "pi-hole.service" ]; - requires = [ "traefik.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - TimeoutStartSec = "600"; - ExecStartPre = [ - "${pkgs.bash}/bin/bash -c 'sleep $((RANDOM % 180))'" - "-${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull" - ]; - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - - systemd.services."update-${container_name}" = { - description = "Update ${container_name} container"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.systemd}/bin/systemctl restart ${container_name}.service"; - }; - }; - - systemd.timers."update-${container_name}" = { - timerConfig = { - OnCalendar = "02:00"; - RandomizedDelaySec = "60m"; - Unit = "update-${container_name}.service"; - }; - wantedBy = [ "timers.target" ]; - }; - }; -} \ No newline at end of file diff --git a/templates/nix-config/podman/nextcloud-aio.nix b/templates/nix-config/podman/nextcloud-aio.nix deleted file mode 100644 index 1259eaf..0000000 --- a/templates/nix-config/podman/nextcloud-aio.nix +++ /dev/null @@ -1,98 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "nextcloud"; - compose_file = "podman/nextcloud/compose.yaml"; - data_dir = "/mnt/data/nextcloud"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - services: - nextcloud-aio-mastercontainer: - image: ghcr.io/nextcloud-releases/all-in-one:latest - container_name: nextcloud-aio-mastercontainer - networks: - nextcloud-aio: - volumes: - - nextcloud_aio_mastercontainer:/mnt/docker-aio-config - - /run/user/1000/podman/podman.sock:/var/run/docker.sock:ro - environment: - APACHE_PORT: 11000 - APACHE_IP_BINDING: 127.0.0.1 - NEXTCLOUD_DATADIR: ${data_dir} - NEXTCLOUD_ENABLE_DRI_DEVICE: $NEXTCLOUD_ENABLE_DRI_DEVICE - NEXTCLOUD_UPLOAD_LIMIT: 16G - NEXTCLOUD_MAX_TIME: 3600 - NEXTCLOUD_MEMORY_LIMIT: 2048M - NEXTCLOUD_ADDITIONAL_APKS: imagemagick - NEXTCLOUD_ADDITIONAL_PHP_EXTENSIONS: imagick - WATCHTOWER_DOCKER_SOCKET_PATH: /run/user/1000/podman/podman.sock - labels: - - traefik.enable=true - - traefik.docker.network=nextcloud-aio - - traefik.http.services.nextcloud-aio.loadbalancer.server.port=8080 - - traefik.http.services.nextcloud-aio.loadbalancer.server.scheme=https - - traefik.http.routers.nextcloud-aio-https.entrypoints=websecure - - traefik.http.routers.nextcloud-aio-https.rule=Host(`nextcloud-aio.$DOMAIN_NAME`) - - traefik.http.routers.nextcloud-aio-https.tls=true - - traefik.http.routers.nextcloud-aio-https.tls.certresolver=cloudflare - init: true - restart: always - - networks: - nextcloud-aio: - external: true - - volumes: - nextcloud_aio_mastercontainer: - name: nextcloud_aio_mastercontainer - ''; - - systemd.services."${container_name}" = { - description = "Podman container : ${container_name}"; - after = [ "network.target" "traefik.service" "pi-hole.service" ]; - requires = [ "traefik.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - TimeoutStartSec = "600"; - ExecStartPre = [ - "${pkgs.bash}/bin/bash -c 'sleep $((RANDOM % 180))'" - "-${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull" - ]; - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - - systemd.services."update-${container_name}" = { - description = "Update ${container_name} container"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.systemd}/bin/systemctl restart ${container_name}.service"; - }; - }; - - systemd.timers."update-${container_name}" = { - timerConfig = { - OnCalendar = "02:00"; - RandomizedDelaySec = "60m"; - Unit = "update-${container_name}.service"; - }; - wantedBy = [ "timers.target" ]; - }; - }; -} \ No newline at end of file diff --git a/templates/nix-config/podman/nextcloud.nix b/templates/nix-config/podman/nextcloud.nix deleted file mode 100644 index 9f02a75..0000000 --- a/templates/nix-config/podman/nextcloud.nix +++ /dev/null @@ -1,131 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "nextcloud"; - compose_file = "podman/nextcloud/compose.yaml"; - data_dir = "/mnt/data/nextcloud"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - services: - nextcloud-server: - image: docker.io/library/nextcloud:latest - container_name: nextcloud-server - restart: unless-stopped - networks: - nextcloud_frontend: - nextcloud_backend: - volumes: - - nextcloud_data:/var/www/html - - ${data_dir}:/var/www/html/data - environment: - MYSQL_HOST: nextcloud-database - MYSQL_DATABASE: $MYSQL_DATABASE - MYSQL_USER: $MYSQL_USER - MYSQL_PASSWORD: $MYSQL_PASSWORD - REDIS_HOST: nextcloud-redis - REDIS_HOST_PASSWORD: $REDIS_HOST_PASSWORD - NEXTCLOUD_TRUSTED_DOMAINS: $DOMAIN_NAME - SMTP_HOST: $SMTP_HOST - SMTP_SECURE: tls - SMTP_PORT: $SMTP_PORT - SMTP_NAME: $SMTP_NAME - SMTP_PASSWORD: $SMTP_PASSWORD - MAIL_FROM_ADDRESS: $MAIL_FROM_ADDRESS - MAIL_DOMAIN: $DOMAIN_NAME - APACHE_DISABLE_REWRITE_IP: 1 - TRUSTED_PROXIES: traefik - OVERWRITEPROTOCOL: https - labels: - - traefik.enable=true - - traefik.docker.network=nextcloud_frontend - - traefik.http.services.nextcloud.loadbalancer.server.port=80 - - traefik.http.services.nextcloud.loadbalancer.server.scheme=http - - traefik.http.routers.nextcloud-https.entrypoints=websecure - - traefik.http.routers.nextcloud-https.rule=Host(`nextcloud.$DOMAIN_NAME`) - - traefik.http.routers.nextcloud-https.tls=true - - traefik.http.routers.nextcloud-https.tls.certresolver=cloudflare - depends_on: - - nextcloud-database - - nextcloud-redis: - image: docker.io/library/redis:alpine - name: nextcloud-redis - restart: unless-stopped - networks: - nextcloud_backend: - command: redis-server --requirepass $REDIS_HOST_PASSWORD - - nextcloud-database: - image: docker.io/library/mariadb:latest - container_name: nextcloud-database - restart: unless-stopped - networks: - nextcloud_backend: - volumes: - - nextcloud_database:/var/lib/mysql - environment: - MARIADB_DATABASE: $MYSQL_DATABASE - MARIADB_USER: $MYSQL_USER - MARIADB_PASSWORD: $MYSQL_PASSWORD - MARIADB_RANDOM_ROOT_PASSWORD: true - - networks: - nextcloud_frontend: - external: true - nextcloud_backend: - external: true - - volumes: - nextcloud_data: - nextcloud_database: - ''; - - systemd.services."${container_name}" = { - description = "Podman container : ${container_name}"; - after = [ "network.target" "traefik.service" "pi-hole.service" ]; - requires = [ "traefik.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - TimeoutStartSec = "600"; - ExecStartPre = [ - "${pkgs.bash}/bin/bash -c 'sleep $((RANDOM % 180))'" - "-${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull" - ]; - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - - systemd.services."update-${container_name}" = { - description = "Update ${container_name} container"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.systemd}/bin/systemctl restart ${container_name}.service"; - }; - }; - - systemd.timers."update-${container_name}" = { - timerConfig = { - OnCalendar = "02:00"; - RandomizedDelaySec = "60m"; - Unit = "update-${container_name}.service"; - }; - wantedBy = [ "timers.target" ]; - }; - }; -} \ No newline at end of file diff --git a/templates/nix-config/podman/passbolt.nix b/templates/nix-config/podman/passbolt.nix deleted file mode 100644 index 5901f11..0000000 --- a/templates/nix-config/podman/passbolt.nix +++ /dev/null @@ -1,129 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "passbolt"; - compose_file = "podman/passbolt/compose.yaml"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - services: - passbolt: - image: passbolt/passbolt:latest-ce-non-root - container_name: passbolt - networks: - passbolt_frontend: - passbolt_backend: - volumes: - - passbolt-gpg:/etc/passbolt/gpg - - passbolt-jwt:/etc/passbolt/jwt - environment: - APP_DEFAULT_TIMEZONE: $TZ - APP_FULL_BASE_URL: https://passbolt.$DOMAIN_NAME - DATASOURCES_DEFAULT_HOST: "passbolt-database" - DATASOURCES_DEFAULT_USERNAME: $PASSBOLT_MYSQL_USER - DATASOURCES_DEFAULT_PASSWORD: $PASSBOLT_MYSQL_PASSWORD - DATASOURCES_DEFAULT_DATABASE: $PASSBOLT_MYSQL_DATABASE - EMAIL_DEFAULT_FROM_NAME: "Passbolt" - EMAIL_TRANSPORT_DEFAULT_HOST: $EMAIL_TRANSPORT_DEFAULT_HOST - EMAIL_TRANSPORT_DEFAULT_PORT: $EMAIL_TRANSPORT_DEFAULT_PORT - EMAIL_TRANSPORT_DEFAULT_USERNAME: $EMAIL_TRANSPORT_DEFAULT_USERNAME - EMAIL_TRANSPORT_DEFAULT_PASSWORD: $EMAIL_TRANSPORT_DEFAULT_PASSWORD - EMAIL_TRANSPORT_DEFAULT_TLS: true - EMAIL_DEFAULT_FROM: $EMAIL_ADDRESS - PASSBOLT_SSL_FORCE: true - labels: - - traefik.enable=true - - traefik.docker.network=passbolt_frontend - - traefik.http.services.passbolt.loadbalancer.server.port=4433 - - traefik.http.services.passbolt.loadbalancer.server.scheme=https - - traefik.http.routers.passbolt-https.entrypoints=websecure - - traefik.http.routers.passbolt-https.rule=Host(`passbolt.$DOMAIN_NAME`) - - traefik.http.routers.passbolt-https.tls=true - - traefik.http.routers.passbolt-https.tls.certresolver=cloudflare - command: - [ - "/usr/bin/wait-for.sh", - "-t", - "0", - "passbolt-database:3306", - "--", - "/docker-entrypoint.sh", - ] - depends_on: - - passbolt-database - restart: unless-stopped - - passbolt-database: - image: mariadb:11.3 - container_name: passbolt-database - networks: - passbolt_backend: - volumes: - - passbolt-database:/var/lib/mysql - environment: - MYSQL_RANDOM_ROOT_PASSWORD: "true" - MYSQL_DATABASE: $PASSBOLT_MYSQL_DATABASE - MYSQL_USER: $PASSBOLT_MYSQL_USER - MYSQL_PASSWORD: $PASSBOLT_MYSQL_PASSWORD - restart: unless-stopped - - networks: - passbolt_backend: - external: true - passbolt_frontend: - external: true - - volumes: - passbolt-database: - passbolt-gpg: - passbolt-jwt: - ''; - - systemd.services."${container_name}" = { - description = "Podman container : ${container_name}"; - after = [ "network.target" "traefik.service" "pi-hole.service" ]; - requires = [ "traefik.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - TimeoutStartSec = "600"; - ExecStartPre = [ - "${pkgs.bash}/bin/bash -c 'sleep $((RANDOM % 180))'" - "-${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull" - ]; - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - - systemd.services."update-${container_name}" = { - description = "Update ${container_name} container"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.systemd}/bin/systemctl restart ${container_name}.service"; - }; - }; - - systemd.timers."update-${container_name}" = { - timerConfig = { - OnCalendar = "02:00"; - RandomizedDelaySec = "60m"; - Unit = "update-${container_name}.service"; - }; - wantedBy = [ "timers.target" ]; - }; - }; -} \ No newline at end of file diff --git a/templates/nix-config/podman/pi-hole.nix b/templates/nix-config/podman/pi-hole.nix deleted file mode 100644 index 3fd8833..0000000 --- a/templates/nix-config/podman/pi-hole.nix +++ /dev/null @@ -1,106 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "pi-hole"; - compose_file = "podman/pi-hole/compose.yaml"; - config_dir = "/mnt/config/pi-hole"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - services: - pihole: - image: docker.io/pihole/pihole:latest - container_name: pi-hole - networks: - pi-hole_frontend: - ports: - # DNS Ports - - "53:53/tcp" - - "53:53/udp" - environment: - TZ: $TZ - FTLCONF_webserver_api_password: $FTLCONF_webserver_api_password - FTLCONF_dns_hosts: | - $HOME_SERVER_IP frigate.$DOMAIN_NAME - $HOME_SERVER_IP gitea.$DOMAIN_NAME - $HOME_SERVER_IP home-assistant.$DOMAIN_NAME - $HOME_SERVER_IP immich.$DOMAIN_NAME - $HOME_SERVER_IP it-tools.$DOMAIN_NAME - $HOME_SERVER_IP nextcloud.$DOMAIN_NAME - $HOME_SERVER_IP nextcloud-aio.$DOMAIN_NAME - $HOME_SERVER_IP passbolt.$DOMAIN_NAME - $HOME_SERVER_IP pi-hole.$DOMAIN_NAME - $HOME_SERVER_IP traefik.$DOMAIN_NAME - FTLCONF_dhcp_active: "false" - FTLCONF_dns_upstreams: 9.9.9.9;149.112.112.112 - FTLCONF_ntp_ipv4_active: "false" - FTLCONF_ntp_ipv6_active: "false" - FTLCONF_ntp_sync_active: "false" - volumes: - - ${config_dir}:/etc/pihole - cap_add: - - SYS_NICE - labels: - - traefik.enable=true - - traefik.docker.network=pi-hole_frontend - - traefik.http.services.pihole.loadbalancer.server.port=80 - - traefik.http.services.pihole.loadbalancer.server.scheme=http - - traefik.http.routers.pihole-https.entrypoints=websecure - - traefik.http.routers.pihole-https.rule=Host(`pi-hole.$DOMAIN_NAME`) - - traefik.http.routers.pihole-https.tls=true - - traefik.http.routers.pihole-https.tls.certresolver=cloudflare - restart: unless-stopped - - networks: - pi-hole_frontend: - external: true - ''; - - systemd.services."${container_name}" = { - description = "Podman container : ${container_name}"; - after = [ "network.target" "traefik.service" ]; - requires = [ "traefik.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - TimeoutStartSec = "600"; - ExecStartPre = [ - "${pkgs.bash}/bin/bash -c 'sleep 20'" - "-${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull" - ]; - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - - systemd.services."update-${container_name}" = { - description = "Update ${container_name} container"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.systemd}/bin/systemctl restart ${container_name}.service"; - }; - }; - - systemd.timers."update-${container_name}" = { - timerConfig = { - OnCalendar = "02:00"; - RandomizedDelaySec = "60m"; - Unit = "update-${container_name}.service"; - }; - wantedBy = [ "timers.target" ]; - }; - }; -} diff --git a/templates/nix-config/podman/traefik.nix b/templates/nix-config/podman/traefik.nix deleted file mode 100644 index e8594f6..0000000 --- a/templates/nix-config/podman/traefik.nix +++ /dev/null @@ -1,64 +0,0 @@ -{ config, pkgs, ... }: - -let - container_name = "traefik"; - compose_file = "podman/traefik/compose.yaml"; - config_dir = "/mnt/config/traefik"; -in - -{ - config = { - environment.etc."${compose_file}".text = - /* - yaml - */ - '' - services: - traefik: - image: docker.io/library/traefik:latest - container_name: traefik - networks: -TRAEFIK_NETWORKS - ports: - - "80:80" - - "443:443" - volumes: - - /run/user/1000/podman/podman.sock:/run/docker.sock:ro - - ${config_dir}/rules/:/etc/traefik/conf/:ro - - ${config_dir}/traefik.yaml:/etc/traefik/traefik.yaml:ro - - ${config_dir}/certs/:/var/traefik/certs/:rw - environment: - - CF_DNS_API_TOKEN=$CF_DNS_API_TOKEN - labels: - - traefik.enable=true - - traefik.http.services.traefik.loadbalancer.server.port=8080 - - traefik.http.services.traefik.loadbalancer.server.scheme=http - - traefik.http.routers.traefik-https.entrypoints=websecure - - traefik.http.routers.traefik-https.rule=Host(`traefik.$DOMAIN_NAME`) - - traefik.http.routers.traefik-https.tls=true - - traefik.http.routers.traefik-https.tls.certresolver=cloudflare - restart: always - networks: -TRAEFIK_REF_NETWORKS - ''; - - systemd.services.traefik = { - description = "Podman container : ${container_name}"; - after = [ "numbus-activation.service" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.podman pkgs.coreutils ]; - - serviceConfig = { - User = "numbus-admin"; - Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ]; - Type = "exec"; - ExecStartPre = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} pull"; - ExecStart = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} up --remove-orphans"; - ExecStop = "${pkgs.podman-compose}/bin/podman-compose -f /etc/${compose_file} down"; - Restart = "on-failure"; - RestartSec = "5m"; - StartLimitBurst = "3"; - }; - }; - }; -} \ No newline at end of file diff --git a/templates/nix-config/sops-nix/secrets.yaml b/templates/nix-config/sops-nix/secrets.yaml index 463bfc8..37a145e 100644 --- a/templates/nix-config/sops-nix/secrets.yaml +++ b/templates/nix-config/sops-nix/secrets.yaml @@ -1,77 +1,4 @@ -ssh_public_keys: "$SSH_PUBLIC_KEY" -sender_email_address_password: "$SENDER_EMAIL_ADDRESS_PASSWORD" -domain_name: "$DOMAIN_NAME" - -podman: - frigate: | - DOMAIN_NAME="$DOMAIN_NAME" - FRIGATE_MQTT_USER="$HOME_ASSISTANT_MQTT_USER" - FRIGATE_MQTT_PASSWORD="$HOME_ASSISTANT_MQTT_PASSWORD" - gitea: | - DOMAIN_NAME="$DOMAIN_NAME" - DB_NAME="$GITEA_DB_NAME" - DB_USERNAME="$GITEA_DB_USERNAME" - DB_PASSWORD="$GITEA_DB_PASSWORD" - POSTGRES_HOST="gitea-database" - POSTGRES_PORT=5432 - home_assistant: | - DOMAIN_NAME="$DOMAIN_NAME" - HOME_ASSISTANT_MQTT_USER="$HOME_ASSISTANT_MQTT_USER" - HOME_ASSISTANT_MQTT_PASSWORD="$HOME_ASSISTANT_MQTT_PASSWORD" - immich: | - DOMAIN_NAME="$DOMAIN_NAME" - DB_DATABASE_NAME="$IMMICH_DB_NAME" - DB_USERNAME="$IMMICH_DB_USERNAME" - DB_PASSWORD="$IMMICH_DB_PASSWORD" - IMMICH_VERSION="release" - IMMICH_TRUSTED_PROXIES=172.16.50.253 - REDIS_HOSTNAME="immich-redis" - DB_HOSTNAME="immich-database" - UPLOAD_LOCATION=/mnt/data/immich - DB_DATA_LOCATION=/mnt/config/immich/database - TZ="Europe/Paris" - it_tools: | - DOMAIN_NAME="$DOMAIN_NAME" - nextcloud: | - DOMAIN_NAME="$DOMAIN_NAME" - MYSQL_DATABASE="$NEXTCLOUD_DB_NAME" - MYSQL_USER="$NEXTCLOUD_DB_USERNAME" - MYSQL_PASSWORD="$NEXTCLOUD_DB_PASSWORD" - REDIS_HOST_PASSWORD="$NEXTCLOUD_REDIS_PASSWORD" - SMTP_HOST="$SENDER_EMAIL_DOMAIN" - SMTP_PORT="$SENDER_EMAIL_PORT" - SMTP_NAME="$SENDER_EMAIL_ADDRESS" - SMTP_PASSWORD="$SENDER_EMAIL_ADDRESS_PASSWORD" - MAIL_FROM_ADDRESS="$EMAIL_ADDRESS" - passbolt: | - DOMAIN_NAME="$DOMAIN_NAME" - PASSBOLT_MYSQL_DATABASE="$PASSBOLT_DB_NAME" - PASSBOLT_MYSQL_USER="$PASSBOLT_DB_USERNAME" - PASSBOLT_MYSQL_PASSWORD="$PASSBOLT_DB_PASSWORD" - EMAIL_TRANSPORT_DEFAULT_HOST="$SENDER_EMAIL_DOMAIN" - EMAIL_TRANSPORT_DEFAULT_PORT="$SENDER_EMAIL_PORT" - EMAIL_TRANSPORT_DEFAULT_USERNAME="$SENDER_EMAIL_ADDRESS" - EMAIL_TRANSPORT_DEFAULT_PASSWORD="$SENDER_EMAIL_ADDRESS_PASSWORD" - EMAIL_DEFAULT_FROM="$EMAIL_ADDRESS" - TZ="Europe/Paris" - pi_hole: | - DOMAIN_NAME="$DOMAIN_NAME" - HOME_ROUTER_SUBNET=$HOME_ROUTER_SUBNET - HOME_ROUTER_IP=$HOME_ROUTER_IP - HOME_SERVER_IP=$HOME_SERVER_IP - FTLCONF_webserver_api_password="$FTLCONF_WEBSERVER_PASSWORD" - TZ="Europe/Paris" - traefik: | - DOMAIN_NAME="$DOMAIN_NAME" - CF_DNS_API_TOKEN="$CF_DNS_API_TOKEN" - -disks: - content-disk-1: "$CONTENT_DISK_1_KEY" - content-disk-2: "$CONTENT_DISK_2_KEY" - content-disk-3: "$CONTENT_DISK_3_KEY" - content-disk-4: "$CONTENT_DISK_4_KEY" - content-disk-5: "$CONTENT_DISK_5_KEY" - content-disk-6: "$CONTENT_DISK_6_KEY" - parity-disk-1: "$PARITY_DISK_1_KEY" - parity-disk-2: "$PARITY_DISK_2_KEY" - parity-disk-3: "$PARITY_DISK_3_KEY" +authorizedSshPublicKeys: | + "$AUTHORIZED_SSH_PUBLIC_KEY" +smtpPassword: "$SMTP_SERVER_PASSWORD" +cloudlfareDnsApiToken: "$CLOUDFLARE_DNS_API_TOKEN" \ No newline at end of file diff --git a/templates/podman-config/frigate/config.yaml b/templates/podman-config/frigate/config.yaml deleted file mode 100644 index 75c2365..0000000 --- a/templates/podman-config/frigate/config.yaml +++ /dev/null @@ -1,70 +0,0 @@ -# Home-assistant connection settings -mqtt: - host: frigate-mqtt - port: 1883 - user: $HOME_ASSISTANT_MQTT_USER - password: $HOME_ASSISTANT_MQTT_PASSWORD - stats_interval: 60 - -# Ffmpeg configuration -ffmpeg: - hwaccel_args: preset-vaapi - -# Snapshots configuration -snapshots: - enabled: true - clean_copy: true - timestamp: true - bounding_box: true - crop: false - retain: - default: 10 - objects: - person: 10 - -# Recordings configuration -record: - enabled: true - retain: - days: 3 - mode: motion - alerts: - retain: - days: 30 - mode: motion - detections: - retain: - days: 30 - mode: motion - -# Cameras configuration -cameras: - camera-1: - enabled: true - onvif: # Enable if camera supports it - host: ip_address - port: 2020 - user: user - password: password - ffmpeg: - inputs: - - path: rtsp://user:password@ip_address:port/url # Check the camera documentation - roles: - - detect - - record - detect: - enabled: true - width: 1280 - height: 720 - fps: 5 - -# Coral TPU configuration -detectors: - coral: - type: edgetpu - device: usb - -version: 0.16-0 - -tls: - enabled: false \ No newline at end of file diff --git a/templates/podman-config/home-assistant/mosquitto.conf b/templates/podman-config/home-assistant/mosquitto.conf deleted file mode 100644 index c1effb6..0000000 --- a/templates/podman-config/home-assistant/mosquitto.conf +++ /dev/null @@ -1,8 +0,0 @@ -persistence true -persistence_location /mosquitto/data/ -log_dest file /mosquitto/log/mosquitto.log -listener 1883 - -## Authentication ## -allow_anonymous false -password_file /mosquitto/config/password.txt \ No newline at end of file diff --git a/templates/podman-config/traefik/headers.yaml b/templates/podman-config/traefik/headers.yaml deleted file mode 100644 index 05b7d7e..0000000 --- a/templates/podman-config/traefik/headers.yaml +++ /dev/null @@ -1,20 +0,0 @@ -http: - middlewares: - passbolt: - headers: - FrameDeny: true - AccessControlAllowMethods: 'GET,OPTIONS,PUT' - AccessControlAllowOriginList: - - origin-list-or-null - AccessControlMaxAge: 100 - AddVaryHeader: true - BrowserXssFilter: true - ContentTypeNosniff: true - ForceSTSHeader: true - STSIncludeSubdomains: true - STSPreload: true - ContentSecurityPolicy: default-src 'self' 'unsafe-inline' - CustomFrameOptionsValue: SAMEORIGIN - ReferrerPolicy: same-origin - PermissionsPolicy: vibrate 'self' - STSSeconds: 315360000 \ No newline at end of file diff --git a/templates/podman-config/traefik/nextcloud.yaml b/templates/podman-config/traefik/nextcloud.yaml deleted file mode 100644 index c1616fe..0000000 --- a/templates/podman-config/traefik/nextcloud.yaml +++ /dev/null @@ -1,41 +0,0 @@ -http: - routers: - nextcloud: - rule: "Host(`nextcloud.${DOMAIN_NAME}`)" - entrypoints: - - "websecure" - service: nextcloud - middlewares: - - nextcloud-chain - tls: - certresolver: "cloudflare" - - services: - nextcloud: - loadBalancer: - servers: - - url: "http://nextcloud-aio-apache:11000" - - middlewares: - nextcloud-secure-headers: - headers: - hostsProxyHeaders: - - "X-Forwarded-Host" - referrerPolicy: "same-origin" - BrowserXssFilter: true - ContentTypeNosniff: true - ForceSTSHeader: true - STSIncludeSubdomains: true - STSPreload: true - STSSeconds: 315360000 - - https-redirect: - redirectscheme: - scheme: https - - nextcloud-chain: - chain: - middlewares: - # - ... (e.g. rate limiting middleware) - - https-redirect - - nextcloud-secure-headers \ No newline at end of file diff --git a/templates/podman-config/traefik/tls.yaml b/templates/podman-config/traefik/tls.yaml deleted file mode 100644 index ee52752..0000000 --- a/templates/podman-config/traefik/tls.yaml +++ /dev/null @@ -1,12 +0,0 @@ -tls: - options: - default: - minVersion: VersionTLS12 - sniStrict: true - curvePreferences: - - CurveP521 - - CurveP384 - cipherSuites: - - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 \ No newline at end of file diff --git a/templates/podman-config/traefik/traefik.yaml b/templates/podman-config/traefik/traefik.yaml deleted file mode 100644 index 9c7ea26..0000000 --- a/templates/podman-config/traefik/traefik.yaml +++ /dev/null @@ -1,53 +0,0 @@ -global: - checkNewVersion: false - sendAnonymousUsage: false - -# - level: [TRACE, DEBUG, INFO, WARN, ERROR, FATAL] -log: - level: ERROR - -accesslog: {} - -api: - dashboard: true - insecure: true - -entryPoints: - web: - address: :80 - http: - redirections: - entryPoint: - to: websecure - scheme: https - websecure: - address: :443 - forwardedHeaders: - trustedIPs: - # Local IPs - - "127.0.0.1/32" - - "10.0.0.0/8" - - "192.168.0.0/16" - - "172.16.0.0/12" - -certificatesResolvers: - cloudflare: - acme: - email: ${EMAIL_ADDRESS} - storage: /var/traefik/certs/cloudflare-acme.json - caServer: "https://acme-v02.api.letsencrypt.org/directory" - dnsChallenge: - provider: cloudflare - resolvers: - - "1.1.1.1:53" - - "9.9.9.9:53" - -serversTransport: - insecureSkipVerify: true - -providers: - docker: - exposedByDefault: false - file: - directory: "/etc/traefik/conf/" - watch: true \ No newline at end of file diff --git a/templates/post-install/numbus-server.conf b/templates/post-install/numbus-server.conf deleted file mode 100644 index e61d766..0000000 --- a/templates/post-install/numbus-server.conf +++ /dev/null @@ -1,25 +0,0 @@ -#TARGET SETTINGS -TARGET_HOST="192.168.1.10" -TARGET_SSH_PUBLIC_KEY="ssh-ed25519 AAAAoefzefpoipoeCEZJCPEACPAcjapjcpajepcjAPJECJPEJAPJAZ yours@yourdomain.com" -# TRAEFIK SETTINGS -DOMAIN_NAME="yourdomain.com" -DOMAIN_EMAIL_ADDRESS="your-mail@yourdomain.com" -DOMAIN_CF_DNS_API_TOKEN="yourToken" -#SMTP SETTINGS -SENDER_EMAIL_ADDRESS="youraddress@gmail.com" -SENDER_EMAIL_ADDRESS_PASSWORD="emrp raps vzoi vnoe" -SENDER_EMAIL_DOMAIN="smtp.yourdomain.com" -SENDER_EMAIL_PORT="587" -#NETWORK SETTINGS -NETWORK_HOME_ROUTER_SUBNET="192.168.1.0/24" -NETWORK_HOME_ROUTER_IP="192.168.1.1" -NETWORK_HOME_SERVER_IP="192.168.1.5" -# SERVICE SETTINGS -SELECTED_SERVICES=("frigate" "home-assistant") -# DISK SETTINGS -BOOT_DISKS_ID=("/dev/disk/by-id/nvme001-dfzpjvp") -DATA_DISKS_ID=("/dev/disk/by-id/sata-barracuda-veojapoj") -DATA_DISKS_TYPE=("HDD") -SPINDOWN_DISKS_ID=("/dev/disk/by-id/sata-barracuda-veojapoj") -CONTENT_DISK_NUMBER=2 -PARITY_DISK_NUMBER=2 \ No newline at end of file diff --git a/templates/post-install/numbus-server.sh b/templates/post-install/numbus-server.sh deleted file mode 100644 index 5eb3182..0000000 --- a/templates/post-install/numbus-server.sh +++ /dev/null @@ -1,220 +0,0 @@ -#!/usr/bin/env nix-shell -#!nix-shell -i bash -p gum fastfetch xkcdpass sops ssh-to-age age sshpass envsubst pciutils usbutils mosquitto - -networking() { - SELECTED_SUBACTION=$(gum choose --header "Choose a setting to change:" "${NETWORKING_SETTINGS_LIST[@]}") - - if [[ "$SELECTED_SUBACTION" = " 🏠 Change the home router subnet" ]]; then - echo "Some future logic here" - elif [[ "$SELECTED_SUBACTION" = " 🌐 Change the home router IP address" ]]; then - echo "Some future logic here" - elif [[ "$SELECTED_SUBACTION" = " 🖥️ Change the server's IP address" ]]; then - echo "Some future logic here" - elif [[ "$SELECTED_SUBACTION" = " 🌍 Change the domain name" ]]; then - echo "Some future logic here" - else - echo -e "\n\n ❌ Unexpected bug. Please contact the developer. Aborting." - exit 1 - fi -} - -backup() { - SELECTED_SUBACTION=$(gum choose --header "Choose a setting to change:" "${BACKUP_SETTINGS_LIST[@]}") - - if [[ "$SELECTED_SUBACTION" = " 🕣 Change the backup time" ]]; then - echo "Some future logic here" - elif [[ "$SELECTED_SUBACTION" = " 💾 Backup all data to a ssh remote" ]]; then - echo "Some future logic here" - elif [[ "$SELECTED_SUBACTION" = " 💿 Backup all data to a local folder" ]]; then - echo "Some future logic here" - else - echo -e "\n\n ❌ Unexpected bug. Please contact the developer. Aborting." - exit 1 - fi -} - -services() { - echo "Some future logic here" -} - -devices() { - echo "Some future logic here" -} - - -disks() { - SELECTED_SUBACTION=$(gum choose --header "Choose a setting to change:" "${DISKS_SETTINGS_LIST[@]}") - - if [[ "$SELECTED_SUBACTION" = " ➕ Add or remove a boot disk" ]]; then - echo "Some future logic here" - elif [[ "$SELECTED_SUBACTION" = " ➕ Add or remove data disk(s)" ]]; then - echo "Some future logic here" - elif [[ "$SELECTED_SUBACTION" = " 🔄 Replace a boot disk" ]]; then - echo "Some future logic here" - elif [[ "$SELECTED_SUBACTION" = " 🔄 Replace a data disk" ]]; then - echo "Some future logic here" - else - echo -e "\n\n ❌ Unexpected bug. Please contact the developer. Aborting." - exit 1 - fi -} - -health() { - SELECTED_SUBACTION=$(gum choose --header "Choose a setting to change:" "${SERVER_HEALTH_SETTINGS_LIST[@]}") - - if [[ "$SELECTED_SUBACTION" = " 🩺 Check disk(s) health" ]]; then - echo "Some future logic here" - elif [[ "$SELECTED_SUBACTION" = " ⛑️ Check service(s) health" ]]; then - echo "Some future logic here" - elif [[ "$SELECTED_SUBACTION" = " 🌐 Check connectivity" ]]; then - echo "Some future logic here" - else - echo -e "\n\n ❌ Unexpected bug. Please contact the developer. Aborting." - exit 1 - fi -} - -email() { - SELECTED_SUBACTION=$(gum choose --header "Choose a setting to change:" "${EMAIL_SETTINGS_LIST[@]}") - - if [[ "$SELECTED_SUBACTION" = " ⚙️ Change the server's email SMTP settings" ]]; then - echo "Some future logic here" - elif [[ "$SELECTED_SUBACTION" = " 📧 Change your personal email" ]]; then - echo "Some future logic here" - else - echo -e "\n\n ❌ Unexpected bug. Please contact the developer. Aborting." - exit 1 - fi -} - -passwords() { - SELECTED_SUBACTION=$(gum choose --header "Choose a setting to change:" "${PASSWORD_SETTINGS_LIST[@]}") - - if [[ "$SELECTED_SUBACTION" = " 👁️ Display the server's configuration credentials" ]]; then - echo "Some future logic here" - elif [[ "$SELECTED_SUBACTION" = " 🔧 Change the numbus-admin's password" ]]; then - echo "Some future logic here" - elif [[ "$SELECTED_SUBACTION" = " 🔑 Add or remove SSH keys" ]]; then - echo "Some future logic here" - elif [[ "$SELECTED_SUBACTION" = " ⚙️ Change Cloudflare API token" ]]; then - echo "Some future logic here" - else - echo -e "\n\n ❌ Unexpected bug. Please contact the developer. Aborting." - exit 1 - fi -} - -configuration_export() { - echo "Some future logic here" -} - -### --> Main logic -set -euo pipefail - -fastfetch --logo nixos --structure '' - -cat <