ctucx.git: nixfiles

ctucx' nixfiles

commit 7b018f51feb735c228c925221151f7df8c360df2
parent df63f323f44c6e6df393e1789d37f7dc3bd98daa
Author: Leah (ctucx) <git@ctu.cx>
Date: Tue, 16 May 2023 13:46:07 +0200

machines: bind local services to ipv6 only on all hosts
25 files changed, 145 insertions(+), 128 deletions(-)
diff --git a/configurations/linux/services/prometheus-exporters.nix b/configurations/linux/services/prometheus-exporters.nix
@@ -4,13 +4,13 @@
 
   services = {
     prometheus.exporters.node.enable = true;
-    prometheus.exporters.node.listenAddress = "127.0.0.1";
+    prometheus.exporters.node.listenAddress = "[::1]";
     prometheus.exporters.node.enabledCollectors = [
       "systemd" "processes"
     ];
 
     prometheus.exporters.systemd.enable = true;
-    prometheus.exporters.systemd.listenAddress = "127.0.0.1";
+    prometheus.exporters.systemd.listenAddress = "[::1]";
 
     nginx = {
       enable = true;

@@ -18,8 +18,8 @@
         enableACME = lib.mkDefault true;
         forceSSL   = lib.mkDefault true;
         kTLS       = lib.mkDefault true;
-        locations."/node-exporter".proxyPass    = "http://127.0.0.1:9100/metrics";
-        locations."/systemd-exporter".proxyPass = "http://127.0.0.1:9558/metrics";
+        locations."/node-exporter".proxyPass    = "http://[::1]:9100/metrics";
+        locations."/systemd-exporter".proxyPass = "http://[::1]:9558/metrics";
       };
     };
   };
diff --git a/configurations/linux/services/restic-server.nix b/configurations/linux/services/restic-server.nix
@@ -3,7 +3,7 @@
 {
 
   age.secrets.restic-server-htpasswd = {
-    file  = ../../../secrets + "/${config.networking.hostName}/restic-server-htpasswd.age";
+    file  = ./. + "/../../../secrets/${config.networking.hostName}/restic-server-htpasswd.age";
     owner = "nginx";
   };
 

@@ -14,7 +14,7 @@
   services = {
     restic.server = {
       enable        = true;
-      listenAddress = "127.0.0.1:8000";
+      listenAddress = "[::1]:8000";
       appendOnly    = true;
       extraFlags    = [ "--no-auth" ];
       dataDir       = "/var/lib/restic";

@@ -27,7 +27,7 @@
         forceSSL   = lib.mkDefault true;
         kTLS       = lib.mkDefault true;
         locations."/" = {
-          proxyPass   = "http://127.0.0.1:8000/";
+          proxyPass   = "http://[::1]:8000/";
           extraConfig = ''
             client_max_body_size 10G;
             auth_basic           Auth;
diff --git a/configurations/linux/services/syncthing-nginx.nix b/configurations/linux/services/syncthing-nginx.nix
@@ -12,7 +12,7 @@
 
   services = {
     syncthing = {
-      guiAddress = "127.0.0.1:8384";
+      guiAddress = "[::1]:8384";
       extraOptions.gui.insecureSkipHostcheck = true;
     };
 

@@ -22,7 +22,7 @@
         enableACME = true;
         forceSSL   = true;
         kTLS       = true;
-        locations."/".proxyPass = "http://127.0.0.1:8384/";
+        locations."/".proxyPass = "http://[::1]:8384/";
       };
     };
   };
diff --git a/machines/briefkasten/gotosocial.nix b/machines/briefkasten/gotosocial.nix
@@ -38,10 +38,10 @@ in {
       account-domain   = "fedi.home.ctu.cx";
       protocol         = "https";
 
-      bind-address     = "127.0.0.1";
+      bind-address     = "[::1]";
       port             = 8085;
 
-      trusted-proxies  = [ "127.0.0.1/32" "172.17.0.0/24" ];
+      trusted-proxies  = [ "::1/128" "172.17.0.0/24" ];
 
       db-type          = "sqlite";
       db-address       = "/var/lib/gotosocial/db.sqlite";

@@ -70,60 +70,39 @@ in {
     forceSSL   = lib.mkIf config.networking.usePBBUplink true;
     kTLS       = lib.mkIf config.networking.usePBBUplink true;
     locations  = {
-      "= /".return    = "307 /@leah";
-
-      "@backend".extraConfig = ''
-        proxy_pass http://127.0.0.1:8085;
-
-        proxy_set_header Host $host;
-        proxy_set_header Upgrade $http_upgrade;
-        proxy_set_header Connection "upgrade";
-        proxy_set_header X-Forwarded-For $remote_addr;
-        proxy_set_header X-Forwarded-Proto $scheme;
-      '';
-
-      "~ /.well-known/(webfinger|host-meta)$".extraConfig = ''
-        proxy_pass http://127.0.0.1:8085;
-
-        proxy_set_header Host $host;
-        proxy_set_header X-Forwarded-For $remote_addr;
-        proxy_set_header X-Forwarded-Proto $scheme;
-
-        proxy_cache gotosocial_ap_public_responses;
-        proxy_cache_background_update on;
-        proxy_cache_key $scheme://$host$uri$is_args$query_string;
-        proxy_cache_valid 200 10m;
-        proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429;
-        proxy_cache_lock on;
-
-        add_header X-Cache-Status $upstream_cache_status;
-      '';
-
-      "~ ^\/users\/(?:[a-z0-9_\.]+)\/main-key$".extraConfig = ''
-        proxy_pass http://127.0.0.1:8085;
-
-        proxy_set_header Host $host;
-        proxy_set_header X-Forwarded-For $remote_addr;
-        proxy_set_header X-Forwarded-Proto $scheme;
-
-        proxy_cache gotosocial_ap_public_responses;
-        proxy_cache_background_update on;
-        proxy_cache_key $scheme://$host$uri;
-        proxy_cache_valid 200 604800s;
-        proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429;
-        proxy_cache_lock on;
-
-        add_header X-Cache-Status $upstream_cache_status;
-      '';
-
-      "/fileserver/".extraConfig = ''
-        alias ${config.services.gotosocial.settings.storage-local-base-path}/;
-        add_header Cache-Control "public, immutable";
-        expires max;
-
-        autoindex off;
-        try_files $uri @fileserver;
-      '';
+      "= /".return = "307 /@leah";
+
+      "/" = {
+        proxyPass       = "http://[::1]:8085/";
+        proxyWebsockets = true;
+      };
+
+      "~ /.well-known/(webfinger|host-meta)$" = {
+        proxyPass   = "http://[::1]:8085";
+        extraConfig = ''
+          proxy_cache gotosocial_ap_public_responses;
+          proxy_cache_background_update on;
+          proxy_cache_key $scheme://$host$uri$is_args$query_string;
+          proxy_cache_valid 200 10m;
+          proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429;
+          proxy_cache_lock on;
+          add_header X-Cache-Status $upstream_cache_status;
+        '';
+      };
+
+      "~ ^\/users\/(?:[a-z0-9_\.]+)\/main-key$" = {
+        proxyPass   = "http://[::1]:8085";
+        extraConfig = ''
+          proxy_cache gotosocial_ap_public_responses;
+          proxy_cache_background_update on;
+          proxy_cache_key $scheme://$host$uri;
+          proxy_cache_valid 200 604800s;
+          proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429;
+          proxy_cache_lock on;
+
+          add_header X-Cache-Status $upstream_cache_status;
+        '';
+      };
 
       "/assets/".extraConfig = ''
         alias ${config.services.gotosocial.package}/share/web/assets/;

@@ -132,15 +111,6 @@ in {
         add_header Cache-Control "public, immutable";
       '';
 
-      "/".extraConfig = ''
-        proxy_pass http://127.0.0.1:8085/;
-
-        proxy_set_header Host $host;
-        proxy_set_header Upgrade $http_upgrade;
-        proxy_set_header Connection "upgrade";
-        proxy_set_header X-Forwarded-For $remote_addr;
-        proxy_set_header X-Forwarded-Proto $scheme;
-      '';
     };
   };
 
diff --git a/machines/briefkasten/radicale.nix b/machines/briefkasten/radicale.nix
@@ -2,6 +2,8 @@
 
 {
 
+  dns.zones."ctu.cx".subdomains.dav.CNAME = lib.mkIf config.networking.usePBBUplink [ "${config.networking.fqdn}." ];
+
   age.secrets = {
     restic-radicale.file = ./. + "/../../secrets/${config.networking.hostName}/restic/radicale.age";
     radicale-users = {

@@ -16,15 +18,13 @@
     paths        = [ "/var/lib/radicale" ];
   };
 
-  dns.zones."ctu.cx".subdomains.dav.CNAME = lib.mkIf config.networking.usePBBUplink [ "${config.networking.fqdn}." ];
-
   systemd.services.radicale.onFailure = [ "email-notify@%i.service" ];
 
   services = {
     radicale = {
       enable = true;
       settings = {
-        server.hosts                        = [ "127.0.0.1:5232" ];
+        server.hosts                        = [ "[::1]:5232" ];
         web.type                            = "internal";
         storage.filesystem_folder           = "/var/lib/radicale/collections";
         headers.Access-Control-Allow-Origin = "*";

@@ -40,7 +40,7 @@
         enableACME = lib.mkIf config.networking.usePBBUplink true;
         forceSSL   = lib.mkIf config.networking.usePBBUplink true;
         kTLS       = lib.mkIf config.networking.usePBBUplink true;
-        locations."/".proxyPass = "http://127.0.0.1:5232/";
+        locations."/".proxyPass = "http://[::1]:5232/";
       };
     };
   };
diff --git a/machines/briefkasten/smarthome/departures2mqtt.nix b/machines/briefkasten/smarthome/departures2mqtt.nix
@@ -12,7 +12,7 @@
 
     serviceConfig = {
       Type      = "oneshot";
-      ExecStart = "${pkgs.departures2mqtt}/bin/departures2mqtt --mqtt-host=127.0.0.1 --mqtt-topic=departures2mqtt --stations=1505,2946,2187";
+      ExecStart = "${pkgs.departures2mqtt}/bin/departures2mqtt --mqtt-host=[::1] --mqtt-topic=departures2mqtt --stations=1505,2946,2187";
 
       DynamicUser = true;
 
diff --git a/machines/briefkasten/smarthome/influxdb2.nix b/machines/briefkasten/smarthome/influxdb2.nix
@@ -16,11 +16,12 @@
   };
 
   systemd.services.influxdb2 = {
-    serviceConfig.ExecStartPost = "${pkgs.bash}/bin/bash -c 'until ${pkgs.netcat}/bin/nc -z 127.0.0.1 8086; do sleep 0.2; done'";
+    serviceConfig.ExecStartPost = "${pkgs.bash}/bin/bash -c 'until ${pkgs.netcat}/bin/nc -z ::1 8086; do sleep 0.2; done'";
     onFailure                   = [ "email-notify@%i.service" ];
   };
 
   services.influxdb2.enable = true;
+  services.influxdb2.settings.http-bind-address = "[::1]:8086";
 
   services.nginx = {
     enable = true;

@@ -28,7 +29,7 @@
       enableACME = lib.mkIf config.networking.usePBBUplink true;
       forceSSL   = lib.mkIf config.networking.usePBBUplink true;
       kTLS       = lib.mkIf config.networking.usePBBUplink true;
-      locations."/".proxyPass   = "http://127.0.0.1:8086/";
+      locations."/".proxyPass   = "http://[::1]:8086/";
     };
   };
 

@@ -120,7 +121,7 @@
       RESPONSE=`curl -X POST 'https://influx.home.ctu.cx/api/v2/query?org=leah' -sS -H 'Accept:application/csv' -H 'Authorization: Token ZrTCG9n8ow-KC_x_HhwJD3VwWS208051WczuIa-3i2M3qmZETdth_XIi5FUTEVKmMXlQ015ujWLRZLjBNbINxQ==' -H 'Content-type:application/json' -d "''${REQUEST_BODY}"`
       MESSAGE=`echo "''${RESPONSE}" | tr -s '\r' '\n' | jq --slurp --raw-input -c 'split("\n") | map(select(length > 0)) | .[1:] | map(split(",")) | map([.[1],.[3],.[4]])'`
 
-      mosquitto_pub -h '127.0.0.1' -r -t 'sdm2mqtt/leah/history' -m "''${MESSAGE}"
+      mosquitto_pub -h '::1' -r -t 'sdm2mqtt/leah/history' -m "''${MESSAGE}"
     '';
   };
 
diff --git a/machines/briefkasten/smarthome/mbusd.nix b/machines/briefkasten/smarthome/mbusd.nix
@@ -12,7 +12,7 @@
     onFailure = [ "email-notify@%i.service" ];
 
     serviceConfig = {
-      ExecStart      = "${pkgs.mbusd}/bin/mbusd -d -v2 -L - -p /dev/modbus0 -s 9600 -m 8n1 -C 32 -N 3 -R 100 -W 500 -T 60";
+      ExecStart      = "${pkgs.mbusd}/bin/mbusd -d -v2 -L - -p /dev/modbus0 -s 9600 -m 8n1 -C 32 -N 3 -R 100 -W 500 -T 60 -A ::1 -P 502";
 
       Restart        = "on-failure";
       RestartSec     = "1";

@@ -33,9 +33,9 @@
       ProtectControlGroups    = true;
       ProtectHome             = true;
 
-      IPAddressAllow          = "127.0.0.0/8";
+      IPAddressAllow          = "::1/128";
 
-      RestrictAddressFamilies = "AF_INET";
+      RestrictAddressFamilies = "AF_INET6";
       RestrictNamespaces      = true;
       RestrictRealtime        = true;
 
diff --git a/machines/briefkasten/smarthome/mosquitto.nix b/machines/briefkasten/smarthome/mosquitto.nix
@@ -34,7 +34,7 @@
         }
 
         {
-          address = "127.0.0.1";
+          address = "::1";
           port    = 9005;
           users = {
             leah.passwordFile = config.age.secrets.mosquitto-passwd-leah.path;
diff --git a/machines/briefkasten/smarthome/mqtt-webui/default.nix b/machines/briefkasten/smarthome/mqtt-webui/default.nix
@@ -29,7 +29,7 @@ in {
             }}/";
           };
           "/mqtt" = {
-            proxyPass       = "http://127.0.0.1:9005";
+            proxyPass       = "http://[::1]:9005";
             proxyWebsockets = true;
           };
         };
diff --git a/machines/briefkasten/smarthome/sdm2mqtt.nix b/machines/briefkasten/smarthome/sdm2mqtt.nix
@@ -3,9 +3,9 @@
 let
   sdm2mqttConfig = {
     devices."leah" =  50;
-    modbus.host    = "127.0.0.1";
+    modbus.host    = "::1";
     modbus.port    = 502;
-    mqtt.host      = "127.0.0.1";
+    mqtt.host      = "::1";
     mqtt.port      = 1883;
     updateInterval = 5;
   };

@@ -39,9 +39,9 @@ in {
       ProtectControlGroups    = true;
       ProtectHome             = true;
 
-      IPAddressAllow          = "127.0.0.0/8";
+      IPAddressAllow          = "::1/128";
 
-      RestrictAddressFamilies = "AF_INET";
+      RestrictAddressFamilies = "AF_INET6";
       RestrictNamespaces      = true;
       RestrictRealtime        = true;
 
diff --git a/machines/briefkasten/smarthome/telegraf.nix b/machines/briefkasten/smarthome/telegraf.nix
@@ -13,7 +13,7 @@
     extraConfig = {
       inputs = {
         mqtt_consumer = {
-          servers     = [ "tcp://127.0.0.1:1883" ];
+          servers     = [ "tcp://[::1]:1883" ];
           topics      = [
             "sdm2mqtt/leah"
             "lacrosse2mqtt/+"
diff --git a/machines/briefkasten/smarthome/zigbee2mqtt.nix b/machines/briefkasten/smarthome/zigbee2mqtt.nix
@@ -1,8 +1,14 @@
-{ inputs, config, pkgs, ... }:
+{ inputs, pkgs, lib, config, ... }:
 
 {
 
+  dns.zones."ctu.cx".subdomains."zigbee2mqtt.home".CNAME = lib.mkIf config.networking.usePBBUplink [ "${config.networking.fqdn}." ];
+
   age.secrets = {
+    "zigbee2mqtt-htpasswd" = {
+      file  = ./. + "/../../../secrets/${config.networking.hostName}/zigbee2mqtt/htpasswd.age";
+      owner = "nginx";
+    };
     "zigbee2mqtt-secrets.yaml" = {
       file  = ./. + "/../../../secrets/${config.networking.hostName}/zigbee2mqtt/secrets.age";
       owner = "zigbee2mqtt";

@@ -22,6 +28,23 @@
       SUBSYSTEM=="tty", ATTRS{idVendor}=="0451", ATTRS{idProduct}=="16a8", SYMLINK+="zigbee0"
     '';
 
+    nginx = {
+      enable = true;
+      virtualHosts."zigbee2mqtt.${config.networking.domain}" = {
+        enableACME = lib.mkIf config.networking.usePBBUplink true;
+        forceSSL   = lib.mkIf config.networking.usePBBUplink true;
+        kTLS       = lib.mkIf config.networking.usePBBUplink true;
+        locations."/" = {
+          proxyPass       = "http://[::1]:8422";
+          proxyWebsockets = true;
+          extraConfig     = ''
+            auth_basic           Auth;
+            auth_basic_user_file ${config.age.secrets.zigbee2mqtt-htpasswd.path};
+          '';
+        };
+      };
+    };
+
     zigbee2mqtt = {
       enable   = true;
       package  = pkgs.zigbee2mqtt;

@@ -31,7 +54,7 @@
 
         mqtt = {
           base_topic = "zigbee2mqtt";
-          server     = "mqtt://127.0.0.1";
+          server     = "mqtt://[::1]";
         };
 
         serial = {

@@ -41,7 +64,7 @@
 
         frontend = {
           port = 8422;
-          host = config.networking.secondaryIP4;
+          host = "::1";
         };
 
         advanced = {
diff --git a/machines/briefkasten/solar-nrw/mqtt-webui/default.nix b/machines/briefkasten/solar-nrw/mqtt-webui/default.nix
@@ -28,7 +28,7 @@ in {
             }}/";
           };
           "/mqtt" = {
-            proxyPass       = "http://127.0.0.1:9005";
+            proxyPass       = "http://[::1]:9005";
             proxyWebsockets = true;
           };
         };
diff --git a/machines/briefkasten/solar-nrw/solax2mqtt.nix b/machines/briefkasten/solar-nrw/solax2mqtt.nix
@@ -38,9 +38,9 @@
       ProtectControlGroups    = true;
       ProtectHome             = true;
 
-      IPAddressAllow          = "127.0.0.0/8 192.168.178.75/32";
+      IPAddressAllow          = "192.168.178.75/32 ::1/128";
 
-      RestrictAddressFamilies = "AF_INET";
+      RestrictAddressFamilies = "AF_INET AF_INET6";
       RestrictNamespaces      = true;
       RestrictRealtime        = true;
 
diff --git a/machines/briefkasten/solar-nrw/telegraf.nix b/machines/briefkasten/solar-nrw/telegraf.nix
@@ -7,7 +7,7 @@
     extraConfig = {
       inputs = {
         mqtt_consumer = {
-          servers     = [ "tcp://127.0.0.1:1883" ];
+          servers     = [ "tcp://[::1]:1883" ];
           topics      = [
             "solax2mqtt"
           ];
diff --git a/machines/briefkasten/websites/music.home.ctu.cx.nix b/machines/briefkasten/websites/music.home.ctu.cx.nix
@@ -9,7 +9,7 @@ let
 
 in {
 
-  dns.zones."ctu.cx".subdomains."music.home".CNAME = lib.mkIf config.networking.usePBBUplink [ "${config.networking.fqdn}." ];
+  dns.zones."ctu.cx".subdomains."music.home".CNAME = lib.mkIf config.networking.usePBBUplink [  "${config.networking.fqdn}." ];
 
   fileSystems."/mnt/music_originals" = {
     device = "/nix/persist/home/leah/syncthing/Music (Originals)";

@@ -38,7 +38,7 @@ in {
         '';
 
         "~(.*)playlist.m3u$".extraConfig = ''
-          set $url http://127.0.0.1:81$1;
+          set $url http://[::1]:81$1;
           proxy_pass $url;
           proxy_set_header Domain $scheme://$host;
           proxy_hide_header 'Content-Type';

@@ -60,10 +60,10 @@ in {
     appendHttpConfig = ''
       server {
         server_name webmusic.local;
-        listen 81;
+        listen [::1]:81;
         access_log off;
 
-        allow 127.0.0.1;
+        allow ::1;
         deny all;
 
         root /mnt/music_originals;
diff --git a/machines/trabbi/grafana/default.nix b/machines/trabbi/grafana/default.nix
@@ -24,6 +24,7 @@
         server = {
           domain    = "grafana.ctu.cx";
           root_url  = "https://grafana.ctu.cx/";
+          http_addr = "[::1]";
           http_port = 3001;
         };
         security.allow_embedding = true;

@@ -82,7 +83,7 @@
         enableACME = true;
         forceSSL   = true;
         kTLS       = true;
-        locations."/".proxyPass = "http://127.0.0.1:3001/";
+        locations."/".proxyPass = "http://[::1]:3001/";
       };
     };
   };
diff --git a/machines/trabbi/mail.nix b/machines/trabbi/mail.nix
@@ -75,6 +75,8 @@
     };
   };
 
+  services.redis.servers.rspamd.bind = "::1";
+
   mailserver = {
     enable  = true;
     fqdn    = config.networking.fqdn;

@@ -83,6 +85,8 @@
     localDnsResolver    = false;
     virusScanning       = false;
 
+    redis.address       = "[::1]";
+
     certificateScheme   = 1;
     certificateFile     = "${config.security.acme.certs.${config.networking.fqdn}.directory}/fullchain.pem";
     keyFile             = "${config.security.acme.certs.${config.networking.fqdn}.directory}/key.pem";
diff --git a/machines/trabbi/matrix-synapse.nix b/machines/trabbi/matrix-synapse.nix
@@ -51,7 +51,7 @@
         url_preview_enabled             = true;
         url_preview_ip_range_blacklist  = ["127.0.0.0/8" "10.0.0.0/8" "172.16.0.0/12" "192.168.0.0/16" "100.64.0.0/10" "169.254.0.0/16" "::1/128" "fe80::/64" "fc00::/7"];
         listeners = [{
-          bind_addresses = [ "127.0.0.1" ];
+          bind_addresses = [ "::1" ];
           port           = 8008;
           type           = "http";
           tls            = false;

@@ -67,8 +67,8 @@
     matrix-sliding-sync-proxy = {
       enable = true;
       dbName = "syncv3";
-      bind = "127.0.0.1:8009";
-      server = "http://127.0.0.1:8008";
+      bind = "[::1]:8009";
+      server = "http://[::1]:8008";
       package = pkgs.matrix-sliding-sync;
     };
 

@@ -95,9 +95,9 @@
           forceSSL   = true;
           kTLS       = true;
           locations  = {
-            "/_matrix".proxyPass = "http://127.0.0.1:8008";
-            "/_matrix/client/unstable/org.matrix.msc3575/".proxyPass = "http://127.0.0.1:8009/_matrix/client/unstable/org.matrix.msc3575/";
-#            "/_synapse".proxyPass = "http://127.0.0.1:8008";
+            "/_matrix".proxyPass = "http://[::1]:8008";
+            "/_matrix/client/unstable/org.matrix.msc3575/".proxyPass = "http://[::1]:8009/_matrix/client/unstable/org.matrix.msc3575/";
+#            "/_synapse".proxyPass = "http://[::1]:8008";
 #            "/admin/".alias = "${pkgs.synapse-admin}/";
             "/".root             = pkgs.cinny.override {
               conf = {
diff --git a/machines/trabbi/prometheus.nix b/machines/trabbi/prometheus.nix
@@ -8,8 +8,11 @@
 
   services = {
     prometheus = {
-      enable        = true;
-      scrapeConfigs = [
+      enable         = true;
+      webExternalUrl = "https://prometheus.${config.networking.domain}/";
+      listenAddress  = "[::1]";
+      port           = 9090;
+      scrapeConfigs  = [
         {
           job_name        = "node-exporter";
           scrape_interval = "30s";

@@ -52,11 +55,11 @@
 
     nginx = {
       enable = true;
-      virtualHosts."prometheus.ctu.cx" = {
+      virtualHosts."prometheus.${config.networking.domain}" = {
         enableACME = true;
         forceSSL   = true;
         kTLS       = true;
-        locations."/".proxyPass   = "http://127.0.0.1:9090/";
+        locations."/".proxyPass   = "http://[::1]:9090/";
       };
     };
 
diff --git a/machines/wanderduene/rclone-restic-server.nix b/machines/wanderduene/rclone-restic-server.nix
@@ -39,7 +39,7 @@
       TimeoutStopSec = "5s";
 
       ExecReload = "/bin/kill -USR1 $MAINPID";
-      ExecStart = "${pkgs.rclone}/bin/rclone --config ${config.age.secrets.rclone-config.path} serve restic --append-only --addr 127.0.0.1:8000 hetzner-storage:";
+      ExecStart = "${pkgs.rclone}/bin/rclone --config ${config.age.secrets.rclone-config.path} serve restic --append-only --addr [::1]:8000 hetzner-storage:";
 
       PrivateTmp = true;
       PrivateDevices = true;

@@ -59,7 +59,7 @@
       forceSSL   = true;
       kTLS       = true;
       locations."/" = {
-        proxyPass   = "http://127.0.0.1:8000/";
+        proxyPass   = "http://[::1]:8000/";
         extraConfig = ''
           client_max_body_size 10G;
           auth_basic           Auth;
diff --git a/secrets/briefkasten/solar-nrw/solax2mqtt.age b/secrets/briefkasten/solar-nrw/solax2mqtt.age
@@ -1,14 +1,15 @@
 -----BEGIN AGE ENCRYPTED FILE-----
-YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRdGQvVzhReHk2S0lDTWxG
-aTdoU1RxbUEvR3k0SUtYek03SXNSWHhGUWxrCkJuaHVsVjloV25jUXFpYWoxWjZm
-VDUvbmROeFdyU3lqTjR0c2xkSGl0bG8KLT4gc3NoLWVkMjU1MTkgNGhLQ013IDlq
-aWNLb3pMNlhmamllczdoZVJ3Q0pDejVRK0tmRUtNc1J3K1M2eTg5SE0KWnN0RmQz
-bFVZRjkrczZqd2R6ckVEcEtoMUdqVkZHandpeHpBd05lbWJLVQotPiBbOW54KC1n
-cmVhc2UgOzU/K1VdNCBjIGMmPzkpdSp2IGkqCnptbGhiMGxCUEhDSW55SUhvYmQ1
-cllDUWpsdwotLS0gbEdLSUxnVFBMdm1XYTU1Y29nQXBHSklXUWtzODJzLzlqeU0z
-eFZwUDZpZwoBTX1EaZ2thGe3IFrSUpKVr4N7S8qgHF4ucQHkuvBqrPGmOxGmB5AC
-66w1+8pp3WU0GCcsWWghqx+D/+9udbR7DOCZEDinN6GPYAvNCUkEvr1uM+Fo6yB8
-4g/nxx3o+2eTSTXn15Me3MJFK1FIv/2j3kkWd40rz5gizxC0wjQEl4BFEKVS2uWZ
-dnWwyzEitUwOWZnG6z1HbhLMKeFvZmfpvc+fsHJ5T053Y9aeFlCDDviK53v1+oNo
-zbRATQ==
+YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBVL3l4RERTVWJ0OHdVODNt
+TWExSkNFVmFyQkZjeElWRDJYTTl5U0NHV0hrCm93MGhNcnFxUms4K0VnUzFSNlVU
+TTVhdFJpVUh3b3lWNzhQbVZqQTdodUEKLT4gc3NoLWVkMjU1MTkgNGhLQ013IDl0
+K21ZNUJoZndxQ3Bvc1hRTGVYRXBoZWg4ZGlGOXByczUxaGxOdjVvVFUKeS9pK2lY
+OXJjQUp3OFhhQ2ZEREtoTTdzUVd5d1NjTW1wblF0Z0k4VFdXNAotPiAsLWdyZWFz
+ZSBBdDAgKD04fGxeV0Qgaz0oWG8gQFQ1M01ACldESFB2dkJWK01YNDd4dExjVm1E
+UHhYOWRBZWJnSjJLenBrT3pWeER2b3BCZ3luZW5GV2VXeTZFZnRxeks1NWMKMFNh
+REFWdE9ZS1FoOTlKMHY2anFiT2h5bDE3SVFuc2VVcERxZ3BXU1Y1WVluaDFZWTFV
+Ci0tLSBaakk4eHJIUlFmeVZkOEwxN0dzeW4xY3NDdXFrZkNSS0svWEFNN2l5dmRF
+Crz/FtUzYCXIHG4L8eaip1TZd6fkAqixh6WMjIr/S2mKOsodKvU8KpSDc/a7MQV8
+FHatBC+nOzJduOzzfLpFFAuMI7jitpHTdAfaUyYnaM9oNej6lGpx37tMJty8iUmr
+fOEiHDubwstAv6Ysojz6ijadjLFcha3/s3fwdo+PUsiDrVWVTxjGC8h+LcwXR5yZ
+Yl1aCcaCD+zWxhvv4IfJ+3mWROvWMuX+oWH0PyDO2LyoQi0IqdWW
 -----END AGE ENCRYPTED FILE-----
diff --git a/secrets/briefkasten/zigbee2mqtt/htpasswd.age b/secrets/briefkasten/zigbee2mqtt/htpasswd.age
@@ -0,0 +1,13 @@
+-----BEGIN AGE ENCRYPTED FILE-----
+YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA4YTVkTlNTYTk0aGo5RmFD
+RUtJUnNGdW5CTlpNUXV6OHduS1FPYnViYnl3Cmg2MXBqN0ttYU0vR3kvR1RBdHhx
+QkNqTG4zS0N3MXFHNzBlRnBEOUxoOEEKLT4gc3NoLWVkMjU1MTkgNGhLQ013IFhR
+TC9jUTJOWjdTVUs1WXlDT3Boc0prT2xYM1RXVUhKZ0JBSHJTcURIakUKakhSV0h4
+c2V1a092d1VWeWtkb1dubHNCbFpMdlpqMlVLaXM1aVIwY2R5MAotPiArTl1XLC1n
+cmVhc2UgT0knIHBSalNXIFEgSFBCJnYKeUZaa0dudkI4R0o4OXMrZDhjaCsyQ2dM
+TjRLN1FObGd2TGlxQjNmRGNjUTRGalhlbk9ieXo1dWpPd2ZpMTFsNQoySUx4RVJu
+NDl5aUdBTThGaERZUXBaOWNqRXpqTVRJSlZkL0hTWVcvbWlYU2VFSnAKLS0tIHg3
+WisrQ01KV01wNjJrT2VWSXFmYVNKcUEzcFI1ZEMwaGxjelkyNHMrOUEKucFYEJvB
+44wbdpOq5qEXGg1TTABI0WTf5tRmuAnsrc13YiqONQj/5iAY5nOzDPfYhQ/AYJ8p
+7SGQvJc/QfA5v+ezC/o8
+-----END AGE ENCRYPTED FILE-----
diff --git a/secrets/secrets.nix b/secrets/secrets.nix
@@ -35,6 +35,7 @@ in {
   "briefkasten/mosquitto/passwd-nrw.age".publicKeys           = [ leah briefkasten ];
 
   "briefkasten/zigbee2mqtt/secrets.age".publicKeys            = [ leah briefkasten ];
+  "briefkasten/zigbee2mqtt/htpasswd.age".publicKeys           = [ leah briefkasten ];
 
   "briefkasten/telegraf/secrets.env.age".publicKeys           = [ leah briefkasten ];