diff --git a/config-files/disks/templates/content.nix b/config-files/disks/templates/content.nix index e9621d9..d227dc4 100644 --- a/config-files/disks/templates/content.nix +++ b/config-files/disks/templates/content.nix @@ -1,4 +1,4 @@ - "content-${i}" = { + "content-${j}" = { type = "disk"; device = "${CONTENT_DISK_ID}"; content = { @@ -8,12 +8,12 @@ size = "100%"; content = { type = "luks"; - name = "crypted-content-${i}"; - settings.keyFile = "/etc/secrets/disks/content-disk-${i}"; + name = "crypted-content-${j}"; + settings.keyFile = "/etc/secrets/disks/content-disk-${j}"; content = { type = "filesystem"; format = "xfs"; - mountpoint = "/mnt/content-${i}"; + mountpoint = "/mnt/content-${j}"; }; }; }; diff --git a/config-files/disks/templates/mirror.nix b/config-files/disks/templates/mirror.nix index a69de4b..fd24f17 100644 --- a/config-files/disks/templates/mirror.nix +++ b/config-files/disks/templates/mirror.nix @@ -3,7 +3,7 @@ disk = { "content-1" = { type = "disk"; - device = "${CONTENT_DISK_1_ID}"; + device = "${CONTENT_DISK_ID}"; content = { type = "gpt"; partitions = { @@ -20,7 +20,7 @@ }; "parity-1" = { type = "disk"; - device = "${PARITY_DISK_1_ID}"; + device = "${PARITY_DISK_ID}"; content = { type = "gpt"; partitions = { diff --git a/config-files/disks/templates/parity.nix b/config-files/disks/templates/parity.nix index a8f8480..0167a5e 100644 --- a/config-files/disks/templates/parity.nix +++ b/config-files/disks/templates/parity.nix @@ -1,4 +1,4 @@ - "parity-${i}" = { + "parity-${j}" = { type = "disk"; device = "${PARITY_DISK_ID}"; content = { @@ -8,12 +8,12 @@ size = "100%"; content = { type = "luks"; - name = "crypted-parity-${i}"; - settings.keyFile = "/etc/secrets/disks/parity-disk-${i}"; + name = "crypted-parity-${j}"; + settings.keyFile = "/etc/secrets/disks/parity-disk-${j}"; content = { type = "filesystem"; format = "xfs"; - mountpoint = "/mnt/parity-${i}"; + mountpoint = "/mnt/parity-${j}"; }; }; }; diff --git a/deploy.sh b/deploy.sh index cb1a03d..809d116 100755 --- a/deploy.sh +++ b/deploy.sh @@ -52,7 +52,7 @@ necessary_credentials_with_config() { fi done - if [[ "$MISSING" == "1" ]]; then + if [[ "$MISSING" -eq "1" ]]; then exit 1 fi } @@ -159,13 +159,13 @@ files_generation() { for service in "${SELECTED_SERVICES[@]}"; do # Frigate - if [[ "$service" == "frigate" ]]; then + if [[ "$service" -eq "frigate" ]]; then echo -e "\n ✅ Adapting the docker configuration to your hardware..." FRIGATE_DEVICES_BLOCK="" - if [[ "$TARGET_GRAPHICS_RENDERER" == "true" ]]; then + if [[ "$TARGET_GRAPHICS_RENDERER" -eq "true" ]]; then FRIGATE_DEVICES_BLOCK+=" - /dev/dri:/dev/dri\n" fi - if [[ "$TARGET_USB_CORAL" == "true" ]]; then + if [[ "$TARGET_USB_CORAL" -eq "true" ]]; then FRIGATE_DEVICES_BLOCK+=" - /dev/bus/usb:/dev/bus/usb\n" fi if [[ -n "$FRIGATE_DEVICES_BLOCK" ]]; then @@ -175,7 +175,7 @@ files_generation() { sed -i.bak "/# --- frigate devices --- #/d" ./config-files/docker/compose/frigate.nix fi # Home-Assistant - elif [[ "$service" == "home-assistant" ]]; then + elif [[ "$service" -eq "home-assistant" ]]; then if [[ -n "$TARGET_ZIGBEE_DEVICE" ]]; then REPLACEMENT="devices:\n - /dev/serial/by-id/${TARGET_ZIGBEE_DEVICE}:/dev/ttyUSB0" sed -i.bak "s|# --- hass devices --- #|$REPLACEMENT|" ./config-files/docker/compose/home-assistant.nix @@ -191,19 +191,19 @@ files_generation() { chmod 0700 extra-files/mnt/config-storage/hass/mqtt/config/password.txt mosquitto_passwd -b extra-files/mnt/config-storage/hass/mqtt/config/password.txt $HOME_ASSISTANT_MQTT_USER $HOME_ASSISTANT_MQTT_PASSWORD # Passbolt - elif [[ "$service" == "passbolt" ]]; then + elif [[ "$service" -eq "passbolt" ]]; then export PASSBOLT_DB_NAME="$(xkcdpass -d "-" -n 2)" export PASSBOLT_DB_USERNAME="$(xkcdpass -d "-" -n 2)" export PASSBOLT_DB_PASSWORD="$(xkcdpass -d "-")" envsubst < config-files/docker/config/traefik/headers.yaml > extra-files/mnt/config-storage/traefik/config/conf/headers.yaml envsubst < config-files/docker/config/traefik/tls.yaml > extra-files/mnt/config-storage/traefik/config/conf/tls.yaml # Pi-Hole - elif [[ "$service" == "pi-hole" ]]; then + elif [[ "$service" -eq "pi-hole" ]]; then export FTLCONF_WEBSERVER_PASSWORD="$(xkcdpass -d "-")" # Immich - elif [[ "$service" == "immich" ]]; then + elif [[ "$service" -eq "immich" ]]; then IMMICH_DEVICES_BLOCK="" - if [[ "$TARGET_GRAPHICS_RENDERER" == "true" ]]; then + if [[ "$TARGET_GRAPHICS_RENDERER" -eq "true" ]]; then IMMICH_DEVICES_BLOCK+=" - /dev/dri:/dev/dri\n" fi if [[ -n "$IMMICH_DEVICES_BLOCK" ]]; then @@ -216,11 +216,11 @@ files_generation() { export IMMICH_DB_USERNAME="$(xkcdpass -d "-" -n 2)" export IMMICH_DB_PASSWORD="$(xkcdpass -d "-")" mkdir -p extra-files/mnt/data-storage/immich/ - elif [[ "$service" == "gitea" ]]; then + elif [[ "$service" -eq "gitea" ]]; then export GITEA_DB_NAME="$(xkcdpass -d "-" -n 2)" export GITEA_DB_USERNAME="$(xkcdpass -d "-" -n 2)" export GITEA_DB_PASSWORD="$(xkcdpass -d "-")" - elif [[ "$service" == "nextcloud" ]]; then + elif [[ "$service" -eq "nextcloud" ]]; then envsubst < config-files/docker/config/traefik/nextcloud.yaml > extra-files/mnt/config-storage/traefik/config/conf/nextcloud.yaml mkdir -p extra-files/mnt/data-storage/nextcloud/ fi @@ -271,86 +271,92 @@ disk_config_generation() { DISK_DETAILS=$(ssh_to_host 'bash -s' </dev/null | grep 'self-assessment' | awk '{print \$6}') == "PASSED" ]]; then + if [[ \$(echo "$REMOTE_PASS" | sudo -S smartctl -H /dev/\$DISK 2>/dev/null | grep 'self-assessment' | awk '{print \$6}') -eq "PASSED" ]]; then DISK_HEALTH+=("PASSED") else DISK_HEALTH+=("N/A") fi - # Disk ID - DISK_ID+=(\$(ls -l /dev/disk/by-id | grep -m1 "../../\$DISK" | awk '{print "/dev/disk/by-id/" \$9}')) - + DISK_ID+=("\$(ls -l /dev/disk/by-id | grep -m1 "../../\$DISK" | awk '{print "/dev/disk/by-id/" \$9}')") # Disk size - DISK_SIZE+=("\$(lsblk -x SIZE -d -n -o SIZE /dev/\$DISK)") + DISK_SIZE+=("\$(lsblk -x SIZE -d -n -e 7,11 -o SIZE /dev/\$DISK)") done -echo "DISK_DEVPATH=(\${DISK_DEVPATH[@]})" > /tmp/nixos-deployment-temp-file -echo "DISK_NAME=(\${DISK_NAME[@]})" >> /tmp/nixos-deployment-temp-file -echo "DISK_TYPE=(\${DISK_TYPE[@]})" >> /tmp/nixos-deployment-temp-file -echo "DISK_HEALTH=(\${DISK_HEALTH[@]})" >> /tmp/nixos-deployment-temp-file -echo "DISK_ID=(\${DISK_ID[@]})" >> /tmp/nixos-deployment-temp-file -echo "DISK_SIZE=(\${DISK_SIZE[@]})" >> /tmp/nixos-deployment-temp-file +echo "DISK_DEVPATH=(\${DISK_DEVPATH[@]})" > $TMPFILE +echo "DISK_NAME=(\${DISK_NAME[@]})" >> $TMPFILE +echo "DISK_TYPE=(\${DISK_TYPE[@]})" >> $TMPFILE +echo "DISK_HEALTH=(\${DISK_HEALTH[@]})" >> $TMPFILE +echo "DISK_ID=(\${DISK_ID[@]})" >> $TMPFILE +echo "DISK_SIZE=(\${DISK_SIZE[@]})" >> $TMPFILE EOF ) - scp -i "extra-files/home/numbus-admin/.ssh/id_ed25519" nixos@$TARGET_HOST:$TMPFILE . &> /dev/null - source nixos-deployment-temp-file && rm nixos-deployment-temp-file - - echo "DISK IDs : ${DISK_ID[@]}" + scp -i "extra-files/home/numbus-admin/.ssh/id_ed25519" nixos@$TARGET_HOST:$TMPFILE $TMPFILE &> /dev/null + source $TMPFILE && rm $TMPFILE ### --> Disk selection - TOTAL_NUMBER_OF_DISKS=${#DISK_NAME[@]} - - if [ "$TOTAL_NUMBER_OF_DISKS" -eq 0 ]; then + if [[ "${#DISK_NAME[@]}" -eq 0 ]]; then echo -e "\n\n ❌ No disks found on the target host. Aborting." exit 1 fi HEADER=$(printf " %-12s %-12s %-12s %-12s %s" "Device" "Type" "Size" "SMART" "Path") - for i in $(seq 0 $(($TOTAL_NUMBER_OF_DISKS - 1))); do - GUM_PRINTED_ELEMENT=$(printf "%-12s %-12s %-12s %-12s %s" \ - "${DISK_NAME[$i]}" "${DISK_TYPE[$i]}" "${DISK_SIZE[$i]}" \ - "${DISK_HEALTH[$i]}" "${DISK_DEVPATH[$i]}") - GUM_PRINTED_ELEMENTS+=("$GUM_PRINTED_ELEMENT") + for i in ${!DISK_NAME[@]}; do + GUM_PRINTED_ELEMENT=$(printf "%-12s %-12s %-12s %-12s %s" \ + "${DISK_NAME[${i}]}" "${DISK_TYPE[${i}]}" "${DISK_SIZE[${i}]}" \ + "${DISK_HEALTH[${i}]}" "${DISK_DEVPATH[${i}]}") + GUM_PRINTED_ELEMENTS+=("$GUM_PRINTED_ELEMENT") done gum style --foreground 212 " ➡️ Please choose one (stripe) or two (mirror) disks for your NixOS boot installation :" SELECTED_BOOT_DISK=$(gum choose --limit 2 --header "$HEADER" "${GUM_PRINTED_ELEMENTS[@]}") - NUMBER_OF_BOOT_DISKS="0" - for ((i=0; i Selection recap @@ -424,17 +386,17 @@ EOF Please review the selected disk layout before proceeding. -**Boot Disks ($NUMBER_OF_BOOT_DISKS):** -* **Boot 1:** \`$BOOT_DISK_1_ID\` -$( [[ -n "${BOOT_DISK_2_ID:-}" ]] && echo "* **Boot 2:** \`$BOOT_DISK_2_ID\`" || echo "* **Boot 2:** *Not configured*") +**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*") -**Data Disks ($NUMBER_OF_CONTENT_DISKS):** -$(for i in $(seq 1 $NUMBER_OF_CONTENT_DISKS); do disk_var="CONTENT_DISK_${i}_ID"; [[ -n "${!disk_var}" ]] && echo "* **Data $i:** \`${!disk_var}\`"; done) -$( [[ $NUMBER_OF_CONTENT_DISKS -eq 0 ]] && echo "* *Not configured*") +**Parity Disks ($PARITY_DISK_NUMBER):** +$(for i in $(seq 0 $((${#DATA_DISKS_ID[@]} - CONTENT_DISK_NUMBER))); do echo "* **Parity ${i}:** `${DATA_DISKS_ID[${i}]}`"; done) +$( [[ $PARITY_DISK_NUMBER -eq 0 ]] && echo "* *Not configured*") -**Parity Disks ($NUMBER_OF_PARITY_DISKS):** -$(for i in $(seq 1 $NUMBER_OF_PARITY_DISKS); do disk_var="PARITY_DISK_${i}_ID"; [[ -n "${!disk_var}" ]] && echo "* **Parity $i:** \`${!disk_var}\`"; done) -$( [[ $NUMBER_OF_PARITY_DISKS -eq 0 ]] && echo "* *Not configured*") +**Data Disks ($CONTENT_DISK_NUMBER):** +$(for i in $(seq $PARITY_DISK_NUMBER $((${#DATA_DISKS_ID[@]} - 1))); do echo "* **Data ${i}:** `${DATA_DISKS_ID[${i}]}`"; done) +$( [[ $CONTENT_DISK_NUMBER -eq 0 ]] && echo "* *Not configured*") EOF ) @@ -444,98 +406,98 @@ EOF ### --> Config generation echo -e "\n\n ✅ Generating disko configuration from templates..." - TEMPLATE_FILE="config-files/disks/templates/boot-${NUMBER_OF_BOOT_DISKS}.nix" + TEMPLATE_FILE="config-files/disks/templates/boot-${#BOOT_DISKS_ID[@]}.nix" (envsubst < "$TEMPLATE_FILE") > ./nix-config/disks/disko.nix echo -e "\n ✅ Generated boot disk configuration." + # 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]}" + (envsubst < "config-files/disks/templates/content.nix") >> ./nix-config/disks/disko.nix + sed -i "s|/mnt/content-1|/mnt/data-storage|" ./nix-config/disks/disko.nix # Mirror configuration - if [[ "$NUMBER_OF_CONTENT_DISKS" == 1 && "$NUMBER_OF_PARITY_DISKS" == 1 ]]; then + elif [[ "$CONTENT_DISK_NUMBER" -eq 1 && "$PARITY_DISK_NUMBER" -eq 1 ]]; then + export CONTENT_DISK_ID="${DATA_DISKS_ID[0]}" + export PARITY_DISK_ID="${DATA_DISKS_ID[1]}" (envsubst < "config-files/disks/templates/mirror.nix") >> ./nix-config/disks/disko.nix # SnapRAID configuration - elif [[ "$NUMBER_OF_CONTENT_DISKS" -gt 0 ]]; then - (envsubst < "nix-config/disks/snapraid.nix") >> ./nix-config/disks/snapraid.nix + elif [[ "$CONTENT_DISK_NUMBER" -gt 1 ]]; then + # Enable SnapRAID sed -i "s|# ./disks/snapraid.nix| ./disks/snapraid.nix|" ./nix-config/configuration.nix - for i in $(seq 1 $NUMBER_OF_CONTENT_DISKS); do - export i - LOOP_DISK="CONTENT_DISK_${i}_ID" + sed -i '$ d' ./config-files/disks/snapraid.nix + cat <> ./config-files/disks/snapraid.nix + # --> Automatic data disks unlock, generated by deploy.sh on $(date) + boot.initrd.luks.devices = { +EOF + j=0 + for i in $(seq 0 $(($CONTENT_DISK_NUMBER - 1))); do + export ((j++)) + LOOP_DISK="${DATA_DISKS_ID[${i}]}" export CONTENT_DISK_ID=${!LOOP_DISK} (envsubst < "config-files/disks/templates/content.nix") >> ./nix-config/disks/disko.nix + cat <> ./config-files/disks/snapraid.nix + "crypted-content-disk-${j}" = { + device = "${!LOOP_DISK}"; + keyFile = "/etc/secrets/disks/content-disk-${j}"; + }; +EOF done - echo -e "\n ✅ Generated $NUMBER_OF_CONTENT_DISKS data disk configuration(s)." - for i in $(seq 1 $NUMBER_OF_PARITY_DISKS); do - export i - LOOP_DISK="PARITY_DISK_${i}_ID" + echo -e "\n ✅ Generated $CONTENT_DISK_NUMBER data disk configuration(s)." + j=0 + for i in $(seq $PARITY_DISK_NUMBER $((${#DATA_DISKS_ID[@]} - 1))); do + export ((j++)) + LOOP_DISK="${DATA_DISKS_ID[${i}]}" export PARITY_DISK_ID=${!LOOP_DISK} (envsubst < "config-files/disks/templates/parity.nix") >> ./nix-config/disks/disko.nix + cat <> ./config-files/disks/snapraid.nix + "crypted-parity-disk-${j}" = { + device = "${!LOOP_DISK}"; + keyFile = "/etc/secrets/disks/parity-disk-${j}}"; + }; +EOF done - echo -e "\n ✅ Generated $NUMBER_OF_PARITY_DISKS parity disk configuration(s)." + echo -e "\n ✅ Generated $PARITY_DISK_NUMBER parity disk configuration(s)." + # Close the snapraid.nix block + cat <<'EOF' >> ./config-files/disks/snapraid.nix + # Automatic data disks unlock <-- + }; +} +EOF + cp -avu ./config-files/disks/snapraid.nix ./nix-config/disks/ fi + # Close the disko.nix block cat <<'EOF' >> ./nix-config/disks/disko.nix }; }; } EOF + echo -e "\n ✅ Final disko configuration created." + + if [[ -n "${DATA_DISKS_ID[@]}" ]]; then + for i in ${!DATA_DISKS_ID[@]}; do + if [[ "${DATA_DISKS_TYPE[${i}]}" -eq "HDD" ]]; then + DISK_ID_LIST+=("${DATA_DISKS_ID[${i}]}") + fi + done + if [[ -n "${DISK_ID_LIST[@]}" ]]; then + sed -i "s|DISK_ID_LIST|${DISK_ID_LIST[@]}|" ./config-files/disks/spindown.nix + cp -avu ./config-files/disks/spindown.nix ./nix-config/disks/spindown.nix + echo -e "\n ✅ Disk spindown configuration created." + fi + fi ### Config generation <-- -### --> Generate automatic unlock configuration - if [[ "$NUMBER_OF_CONTENT_DISKS" -gt 1 && "$NUMBER_OF_PARITY_DISKS" -gt 0 ]]; then - echo -e "\n ✅ Generating automatic disk unlocking configuration..." - sed -i '$ d' ./config-files/disks/snapraid.nix - - cat <> ./config-files/disks/snapraid.nix - # --> Automatic data disks unlock, generated by deploy.sh on $(date) - boot.initrd.luks.devices = { -EOF - - if [[ "$NUMBER_OF_CONTENT_DISKS" -gt 0 ]]; then - for i in $(seq 1 $NUMBER_OF_CONTENT_DISKS); do - LOOP_DISK="CONTENT_DISK_$i" - cat <> ./config-files/disks/snapraid.nix - "crypted-content-disk-${i}" = { - device = "${!LOOP_DISK}"; - keyFile = "/etc/secrets/disks/content-disk-${i}"; - }; -EOF - done - fi - - if [[ "$NUMBER_OF_PARITY_DISKS" -gt 0 ]]; then - for i in $(seq 1 $NUMBER_OF_PARITY_DISKS); do - LOOP_DISK="PARITY_DISK_$i" - cat <> ./config-files/disks/snapraid.nix - "crypted-parity-disk-${i}" = { - device = "${!LOOP_DISK}"; - keyFile = "/etc/secrets/disks/parity-disk-${i}"; - }; -EOF - done - fi - - cat <<'EOF' >> ./config-files/disks/snapraid.nix - # Automatic data disks unlock <-- - }; -} -EOF - fi - - cp -avu ./config-files/disks/snapraid.nix ./nix-config/disks/ - - if [[ -n "${DISK_ID_LIST[@]}" ]]; then - sed -i "s|DISK_ID_LIST|${DISK_ID_LIST[@]}|" ./config-files/disks/spindown.nix - cp -avu ./config-files/disks/spindown.nix ./nix-config/disks/spindown.nix - fi -### Generate automatic unlock configuration <-- - ### --> Generate unlock keys - for i in $NUMBER_OF_BOOT_DISKS; do + for i in ${!BOOT_DISKS_ID[@]}; do declare "/etc/secrets/disks/boot-disk-${i}=$(xkcdpass -d "-")" done - for i in $NUMBER_OF_CONTENT_DISKS; do + for i in $CONTENT_DISK_NUMBER; do declare "/etc/secrets/disks/content-disk-${i}=$(xkcdpass -d "-")" done - for i in $NUMBER_OF_PARITY_DISKS; do + for i in $PARITY_DISK_NUMBER; do declare "/etc/secrets/disks/parity-disk-${i}=$(xkcdpass -d "-")" done ### Generate unlock keys <-- @@ -630,7 +592,7 @@ sleep 1 ACTION_ANSWER=$(gum choose "[1] 🌐 Deploy NixOS on a remote machine" "[2] 💽 Deploy NixOS on a remote machine with a file configuration" "[3] 🛠️ Update a NixOS remote machine") echo $ACTION_ANSWER -if [[ "$ACTION_ANSWER" == "[1] 🌐 Deploy NixOS on a remote machine" ]]; then +if [[ "$ACTION_ANSWER" -eq "[1] 🌐 Deploy NixOS on a remote machine" ]]; then echo -e "\n ➡️ Proceeding with deployment…" gum style --border normal --margin "1" --padding "1 2" --border-foreground 212 "➡️ On the target host : start the computer and boot into the NixOS iso. Launch a console and set up a new user password." @@ -643,7 +605,7 @@ if [[ "$ACTION_ANSWER" == "[1] 🌐 Deploy NixOS on a remote machine" ]]; then disk_config_generation deploy postrun_action -elif [[ "$ACTION_ANSWER" == "[2] 💽 Deploy NixOS on a remote machine with a file configuration" ]]; then +elif [[ "$ACTION_ANSWER" -eq "[2] 💽 Deploy NixOS on a remote machine with a file configuration" ]]; then echo -e "\n ➡️ Proceeding with deployment using a config file…" gum style --border normal --margin "1" --padding "1 2" --border-foreground 212 "➡️ On the target host : start the computer and boot into the NixOS iso. Launch a console and set up a new user password." @@ -657,7 +619,7 @@ elif [[ "$ACTION_ANSWER" == "[2] 💽 Deploy NixOS on a remote machine with a fi deploy sum_up postrun_action -elif [[ "$ACTION_ANSWER" == "[3] 🛠️ Update a NixOS remote machine" ]]; then +elif [[ "$ACTION_ANSWER" -eq "[3] 🛠️ Update a NixOS remote machine" ]]; then echo -e "\n ➡️ Proceeding with update…" gum style --border normal --margin "1" --padding "1 2" --border-foreground 212 "➡️ On the target host : make sure the NixOS installation you want to update is up-and-running, accessible with SSH." diff --git a/nix-config/configuration.nix b/nix-config/configuration.nix index 6611b46..6ac132d 100644 --- a/nix-config/configuration.nix +++ b/nix-config/configuration.nix @@ -110,9 +110,6 @@ data-root = "/mnt/config-storage/docker-volumes/"; }; - # Hostname - networking.hostName = "numbus-server"; - # User account users.users.numbus-admin = { isNormalUser = true; diff --git a/nix-config/misc/networking.nix b/nix-config/misc/networking.nix index cd20141..70d2108 100644 --- a/nix-config/misc/networking.nix +++ b/nix-config/misc/networking.nix @@ -1,6 +1,9 @@ { config, pkgs, lib, ... }: { + # Hostname + networking.hostName = "numbus-server"; + # Enable networking and firewall networking.interfaces.eth0.ipv4.addresses = [ { @@ -11,7 +14,7 @@ networking.defaultGateway = "HOME_ROUTER_IP"; networking.nameservers = [ "HOME_SERVER_IP" "9.9.9.9" ]; networking.networkmanager.enable = true; -# networking.nftables.enable = false; + networking.nftables.enable = true; networking.firewall.enable = true; # networking.firewall.extraCommands = " # iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080