From e6442b2442494c19a45996e4d1c8c04134d9d710 Mon Sep 17 00:00:00 2001 From: goeranh Date: Fri, 20 Mar 2026 17:01:11 +0100 Subject: [PATCH 01/42] add auth and mail as containers --- hosts/auth/authentik.nix | 75 +++++++++++++++ hosts/auth/default.nix | 38 ++++++++ hosts/mail/default.nix | 202 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 315 insertions(+) create mode 100644 hosts/auth/authentik.nix create mode 100644 hosts/auth/default.nix create mode 100644 hosts/mail/default.nix diff --git a/hosts/auth/authentik.nix b/hosts/auth/authentik.nix new file mode 100644 index 0000000..0e04762 --- /dev/null +++ b/hosts/auth/authentik.nix @@ -0,0 +1,75 @@ +{ + config, + lib, + pkgs, + ... +}: +{ + users.groups.authentik = { }; + users.users.authentik = { + isSystemUser = true; + extraGroups = [ "docker" ]; + group = "authentik"; + }; + + virtualisation.docker.enable = true; + + systemd.services = { + authentik-secrets-setup = { + enable = true; + }; + }; + services.authentik-ldap = { + enable = true; + environmentFile = "/var/lib/authentik-ldap-env"; + }; + services.authentik = { + enable = true; + # The environmentFile needs to be on the target host! + # Best use something like sops-nix or agenix to manage it + environmentFile = "/var/lib/authentik_secret"; + settings = { + email = { + host = "mail.${config.networking.domain}"; + port = 25; + username = "authentik@${config.networking.domain}"; + use_tls = false; + use_ssl = false; + from = "authentik@${config.networking.domain}"; + }; + disable_startup_analytics = true; + avatars = "initials"; + }; + }; + + systemd.services.authentik-secrets-generator = { + enable = true; + requiredBy = [ + "authentik-secrets-setup.service" + "authentik-worker.service" + ]; + script = '' + echo "AUTHENTIK_SECRET_KEY=$(${pkgs.openssl}/bin/openssl rand -hex 32)" > /var/lib/authentik_secret + ''; + }; + + services.nginx = { + enable = true; + virtualHosts = { + "auth.${config.networking.domain}" = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://localhost:9000"; + proxyWebsockets = true; + recommendedProxySettings = true; + extraConfig = '' + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + ''; + }; + }; + }; + }; +} + diff --git a/hosts/auth/default.nix b/hosts/auth/default.nix new file mode 100644 index 0000000..e4ba74b --- /dev/null +++ b/hosts/auth/default.nix @@ -0,0 +1,38 @@ +{ + config, + lib, + pkgs, + modulesPath, + ... +}: +{ + imports = [ + "${modulesPath}/virtualisation/proxmox-lxc.nix" + ./authentik.nix + ]; + + networking = { + hostName = "auth"; + domain = lib.mkForce "test.htw.stura-dresden.de"; + interfaces.eth0.ipv4.addresses = [ + { + address = "141.56.51.96"; + prefixLength = 24; + } + ]; + + defaultGateway = { + address = "141.56.51.254"; + interface = "eth0"; + }; + + firewall.allowedTCPPorts = [ + 80 + 443 + 3389 + ]; + }; + + system.stateVersion = "25.05"; +} + diff --git a/hosts/mail/default.nix b/hosts/mail/default.nix new file mode 100644 index 0000000..e4f81ec --- /dev/null +++ b/hosts/mail/default.nix @@ -0,0 +1,202 @@ +{ + config, + lib, + pkgs, + modulesPath, + ... +}: +let + generatedAliases = pkgs.writeText "generated-aliases" ( + lib.concatStringsSep "\n" ( + lib.mapCartesianProduct + ({ aliases, domain }: "${aliases}@${domain} root@test.htw.stura-dresden.de") + { + aliases = [ + "abuse" + "hostmaster" + "noreply" + "postmaster" + "webmaster" + ]; + domain = config.mailserver.domains; + } + ) + ); + +in +{ + imports = [ + "${modulesPath}/virtualisation/proxmox-lxc.nix" + ]; + + security.pam.loginLimits = [ + { + domain = "*"; + type = "soft"; + item = "nofile"; + value = "8192"; + } + ]; + + networking = { + hostName = "mail"; + domain = lib.mkForce "test.htw.stura-dresden.de"; + interfaces.ens18.ipv4.addresses = [ + { + address = "141.56.51.95"; + prefixLength = 24; + } + ]; + + defaultGateway = { + address = "141.56.51.254"; + interface = "eth0"; + }; + }; + + services.nginx.virtualHosts = { + "lists.${config.networking.domain}" = { + enableACME = true; + forceSSL = true; + # locations."/" = { + # proxyPass = "http://127.0.0.1:18507"; + # }; + }; + }; + services.automx2 = { + enable = true; + domain = "${config.networking.domain}"; + settings = { + automx2 = { + db_uri = "sqlite:////var/lib/automx2/db.sqlite"; + proxy_count = 1; + }; + }; + }; + services.mailman = { + enable = true; + hyperkitty = { + enable = true; + }; + serve.enable = true; + webHosts = [ + "lists.${config.networking.domain}" + ]; + }; + + services.mailman.siteOwner = "mailman@${config.networking.domain}"; + mailserver = { + enable = true; + fqdn = "mail.${config.networking.domain}"; + domains = [ + "${config.networking.domain}" + "lists.${config.networking.domain}" + ]; + ldap = { + enable = true; + bind = { + # dn = "cn=dovecot,ou=users,DC=test,DC=htw,DC=stura-dresden,DC=de"; + dn = "cn=ldapuser,ou=users,dc=ldap,dc=goauthentik,dc=io"; + passwordFile = "/var/lib/dovecot_ldap_passwd"; + }; + dovecot = { + userFilter = "(&(objectClass=posixAccount)(mail=%u))"; + passFilter = "(&(objectClass=posixAccount)(mail=%u))"; + userAttrs = "cn"; + }; + postfix = { + filter = "(|(&(objectClass=posixAccount)(mail=%s))(&(objectClass=posixAccount)(cn=%s)))"; + mailAttribute = "mail"; + uidAttribute = "cn"; + }; + #searchBase = "DC=test,DC=htw,DC=stura-dresden,DC=de"; + searchBase = "DC=ldap,DC=goauthentik,DC=io"; + uris = [ + "ldap://auth.test.htw.stura-dresden.de:3389" + ]; + }; + + certificateScheme = "acme-nginx"; + enableImap = true; + enableImapSsl = true; + enableManageSieve = true; + enableSubmission = true; + enableSubmissionSsl = true; + extraVirtualAliases = { }; + lmtpSaveToDetailMailbox = "no"; # DOS potential + mailboxes = { + Drafts = { + auto = "subscribe"; + specialUse = "Drafts"; + }; + Sent = { + auto = "subscribe"; + specialUse = "Sent"; + }; + Spam = { + auto = "subscribe"; + specialUse = "Junk"; + }; + Trash = { + auto = "subscribe"; + specialUse = "Trash"; + }; + }; + maxConnectionsPerUser = 10; + messageSizeLimit = 10 * 1000 * 1024; # 10 MiB + + stateVersion = 3; + }; + + # services.dovecot2.mailLocation = lib.mkForce "maildir:/var/vmail/%n"; + services.postfix = + let + submissionOptions = { + # hash:/etc/postfix/virtual, + smtpd_sender_login_maps = lib.mkForce "ldap:/run/postfix/ldap-sender-login-map.cf"; + smtpd_client_restrictions = "permit_sasl_authenticated,reject"; + }; + in + { + masterConfig = { + submission = { + args = [ "-v" ]; + }; + submissions = { + args = [ "-v" ]; + }; + }; + settings.main = { + unknown_local_recipient_reject_code = 550; + relay_domains = [ + "hash:/var/lib/mailman/data/postfix_domains" + ]; + transport_maps = [ + "hash:/var/lib/mailman/data/postfix_lmtp" + ]; + local_recipient_maps = [ + "hash:/var/lib/mailman/data/postfix_lmtp" + ]; + }; + # mapFiles = { + # "valias" = lib.mkForce "/var/lib/postfix/valias"; + # "virtual" = lib.mkForce "/var/lib/postfix/virtual"; + # }; + submissionOptions = submissionOptions; + submissionsOptions = submissionOptions; + }; + + security.acme.acceptTerms = true; + security.acme.defaults.email = "cert@stura.htw-dresden.de"; + + networking.firewall.allowedTCPPorts = [ + 25 + 80 + 443 + 597 + ]; + + system.stateVersion = "24.11"; + +} + From 43cfebcec6527e3a6b8e797e52a18668570d1574 Mon Sep 17 00:00:00 2001 From: goeranh Date: Fri, 20 Mar 2026 17:17:21 +0100 Subject: [PATCH 02/42] disable dhcp --- hosts/auth/default.nix | 2 +- hosts/mail/default.nix | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/hosts/auth/default.nix b/hosts/auth/default.nix index e4ba74b..3df3a1d 100644 --- a/hosts/auth/default.nix +++ b/hosts/auth/default.nix @@ -14,6 +14,7 @@ networking = { hostName = "auth"; domain = lib.mkForce "test.htw.stura-dresden.de"; + useDHCP = false; interfaces.eth0.ipv4.addresses = [ { address = "141.56.51.96"; @@ -35,4 +36,3 @@ system.stateVersion = "25.05"; } - diff --git a/hosts/mail/default.nix b/hosts/mail/default.nix index e4f81ec..fa90494 100644 --- a/hosts/mail/default.nix +++ b/hosts/mail/default.nix @@ -41,6 +41,7 @@ in networking = { hostName = "mail"; domain = lib.mkForce "test.htw.stura-dresden.de"; + useDHCP = false; interfaces.ens18.ipv4.addresses = [ { address = "141.56.51.95"; From 2fa576a302e4919c61d641017e866e858e91aff1 Mon Sep 17 00:00:00 2001 From: goeranh Date: Sat, 21 Mar 2026 18:03:50 +0100 Subject: [PATCH 03/42] init sops for mail and auth --- .sops.yaml | 47 ++++++++++--------------------------- flake.nix | 1 + hosts/auth/default.nix | 7 ++++++ hosts/auth/secrets.sops.yml | 27 +++++++++++++++++++++ hosts/mail/default.nix | 6 +++++ hosts/mail/secrets.sops.yml | 25 ++++++++++++++++++++ 6 files changed, 79 insertions(+), 34 deletions(-) create mode 100644 hosts/auth/secrets.sops.yml create mode 100644 hosts/mail/secrets.sops.yml diff --git a/.sops.yaml b/.sops.yaml index fd76726..66644ad 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -1,38 +1,17 @@ -# SOPS configuration for StuRa HTW Dresden infrastructure -# -# This file defines which keys can decrypt which secrets. -# Add GPG public keys (.asc files) or age keys to keys/hosts/ and keys/users/ -# to grant decryption access to hosts and users respectively. - keys: - # Admin/user keys - add GPG public keys here - # Example: - # - &user_admin_key age1... or pgp fingerprint + - &goeranh age1qp7w80k3qtj79xsl0gwsfrkm037xrlnhm6th7tcyrvufh3szzp6s2pe7ra + - &mail age156ak7kc79tuwpv0hk9atl5dg27jqs6ddfqxvr9m4twqgsr23lgvsdmyfpr + - &auth age1njnkkr489hfmpn337zna2k3z66y9086t7cpcmz2vn68p4x43aujs6wh0g5 - # Host keys - add host-specific keys here - # Example: - # - &host_proxy_key age1... or pgp fingerprint - # - &host_git_key age1... or pgp fingerprint -# Define which keys can access which files creation_rules: - # Default rule: all secrets can be decrypted by admin keys - - path_regex: secrets/.*\.yaml$ - # key_groups: - # - pgp: - # - *user_admin_key - # - age: - # - *user_admin_key - - # Host-specific secrets (example) - # - path_regex: secrets/proxy/.*\.yaml$ - # key_groups: - # - pgp: - # - *user_admin_key - # - *host_proxy_key - - # - path_regex: secrets/git/.*\.yaml$ - # key_groups: - # - pgp: - # - *user_admin_key - # - *host_git_key + - path_regex: hosts/mail/secrets.sops.yml$ + key_groups: + - age: + - *mail + - *goeranh + - path_regex: hosts/auth/secrets.sops.yml$ + key_groups: + - age: + - *auth + - *goeranh diff --git a/flake.nix b/flake.nix index 2d1426d..53bdc81 100644 --- a/flake.nix +++ b/flake.nix @@ -196,6 +196,7 @@ disko.nixosModules.disko authentik.nixosModules.default mailserver.nixosModules.mailserver + sops.nixosModules.default { _module.args = { inherit self modulesPath; }; } diff --git a/hosts/auth/default.nix b/hosts/auth/default.nix index 3df3a1d..0d135dc 100644 --- a/hosts/auth/default.nix +++ b/hosts/auth/default.nix @@ -6,6 +6,13 @@ ... }: { + sops = { + defaultSopsFile = ./secrets.sops.yml; + secrets = { + "auth/env-file".owner = "authentik"; + "auth/ldap-env-file".owner = "authentik"; + }; + }; imports = [ "${modulesPath}/virtualisation/proxmox-lxc.nix" ./authentik.nix diff --git a/hosts/auth/secrets.sops.yml b/hosts/auth/secrets.sops.yml new file mode 100644 index 0000000..45c456a --- /dev/null +++ b/hosts/auth/secrets.sops.yml @@ -0,0 +1,27 @@ +auth: + env-file: ENC[AES256_GCM,data:WDJ3daYCxybublm8VWO8W5HHmYYWKOcw81f+fQ0Vz78EOvbYI+SgEwnuAd/0/eeGkTPEJPSCfbymArs+YRTdibgO5y/34jdN0DOVQetZLPXrDbcZ/Sg=,iv:bykKdvkgmxwgptkGHKH4rnFknPA0PTrW+mEqIzIYERk=,tag:8UKhLz/VoPiXckcIEBfrLg==,type:str] + ldap-env-file: ENC[AES256_GCM,data:CpgiiUin3hj8+aykcSU2rasaCFt/CAC5lK3Ek7zxzw6hYCkhwxIc9a4Xfy9SxSQtASJ5dOOrOaa8gA1ahf4Z1g/1981fhxlQPeJd9PlJFgdL4CP5P6ZrPBKZKgygnreUo6HC7Rfc9x2CRmnDhQvMVUmQL9akZRNYasX+9IlRyKmLSFmi35IuryFhVLwfjfECmq51/Xo2WYzjWrayfFuOpS0jHWicQxXvXq6QcLvqmbk5euXiHDkFXOXcwMRr6mAompDAKa9BKXqcRDbxOWqzJ1gflEJvOJi249PeYFo+poTK1CUtBCTejFo=,iv:P1xN6wq5oeba1LSEn6UiArOka37alV/PhI5kOmpfDG0=,tag:Xisd5elHQ8mhvE6YEbCuLg==,type:str] +sops: + age: + - recipient: age1njnkkr489hfmpn337zna2k3z66y9086t7cpcmz2vn68p4x43aujs6wh0g5 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHRmV2dGt1UXZ3M2RKd24y + V0x4MzZyYUh0aDVwQ1NmOCtyOHR6Z1c0R1ZNCi80Nk9PZFVTcVFIQjlZVXJNeXBN + TC9td05ZeWVVTCtFSWhqazN6bFF3akkKLS0tIEV3YzdRUDA5Q2dBd2JWUWNqOTU4 + SnZtdVd4Q3lCaStJTnV4U2cvZUZEMlkK85XYSh6VbDFPKPIhKBKtkErGtgsHjXxy + kq14EXwfZnnBlR76JMQgPvSLrDLdj+4tDIVcuE4JplCoSvbGKckGww== + -----END AGE ENCRYPTED FILE----- + - recipient: age1qp7w80k3qtj79xsl0gwsfrkm037xrlnhm6th7tcyrvufh3szzp6s2pe7ra + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkQm5nUHkzZExKOXNzNjk4 + Y1JURVJwNXhFUGZJak8vbEtCNnE2dHFuNVVNClJHQ3E2RGJkbUtlMDNwcy9Ib01Q + dG9nRTVJejkySTdlb2IrbHF4Z3ZMTmcKLS0tIHUwNndGdW9EaWwyNmRUb2NQU2Vs + MC9VSmVqVlVHRlJ4NXozUkQ4ZDVEVlkKbfVoBNsral3n7rG7ujUgdQXF68EVB+4G + MKMuOiY05QGBViLYyKh1jioHv6nds1hCuc2vpLNB3J0KT3I2q/a0VQ== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-21T16:42:34Z" + mac: ENC[AES256_GCM,data:i9hTUqbrmc2mD8PAbCe2gWern4ArMIkTQWN7eaJcsjZ9m6LZjOQFpnrpgPg6fj3hazgnFn86veNvQGe/J50NLnwj2FCyF3jKG3xkc7rKa9fyD0Yz0XnpbNKtDb2YGxwyBmLsnnyl6sdpyvPipZYCfwM+bhB8OERIXVXKwbZOn1A=,iv:dKI/NsMcVBNBOw0kYEQqrgfdvLKDg4NM/yRBYDqXIxU=,tag:xkg0z7IUy2m4ivosB925vQ==,type:str] + unencrypted_suffix: _unencrypted + version: 3.12.1 diff --git a/hosts/mail/default.nix b/hosts/mail/default.nix index fa90494..6d3c388 100644 --- a/hosts/mail/default.nix +++ b/hosts/mail/default.nix @@ -25,6 +25,12 @@ let in { + sops = { + defaultSopsFile = ./secrets.sops.yml; + secrets = { + "ldap_passwd".owner = "dovecot2"; + }; + }; imports = [ "${modulesPath}/virtualisation/proxmox-lxc.nix" ]; diff --git a/hosts/mail/secrets.sops.yml b/hosts/mail/secrets.sops.yml new file mode 100644 index 0000000..8a51068 --- /dev/null +++ b/hosts/mail/secrets.sops.yml @@ -0,0 +1,25 @@ +ldap_passwd: ENC[AES256_GCM,data:wAtRF+7QNgkHAKoQVYZeepshAo/dHuGBC3L15svZ5NVpqaTAtWKIVz/tT/SkjxjC2OXTkzUxin4JMGS6,iv:RELJtuCRLPyqzxUqN2KYTI5/P4fiQALRVtr+xZmKUOY=,tag:2ZS1jmAxw3dohAC6zJLUCQ==,type:str] +sops: + age: + - recipient: age156ak7kc79tuwpv0hk9atl5dg27jqs6ddfqxvr9m4twqgsr23lgvsdmyfpr + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsenVrS0tkTWZRY2xDZklO + WTcwaENIY2I1bTFGMEZZVzBoeUNrT2RESmhFCnZXU2M1SjlGQWo0OEp0TzI0c21u + UkNuNEdQQldQdy9uSzhveEM2eFZrRUkKLS0tIGV4S3lreHJPVS96VUZ6SXRaSklW + MUE4eXN0bkNkU0dCckppdldvV2V4dHcKdKh6ekq6hB5pCUAEPdASqsxqAKZDwzCv + NyS2jitHo9XBtMQVJg4PmNcoRs5XLdqy2tP8upnGelj0B/Q9D+dhag== + -----END AGE ENCRYPTED FILE----- + - recipient: age1qp7w80k3qtj79xsl0gwsfrkm037xrlnhm6th7tcyrvufh3szzp6s2pe7ra + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRVlVrdXhGMDRxMjhPb3Nv + c3lBS25OKzJIaWhHWHpKQXo0N1dFTnZLaHdnClVFVTFPVE1rNFVEclFVc3VjQVhu + SjF6Nnp6dE9oRUJYUVVnOWVpVE11WVkKLS0tIEJ0aVJzejROMHFPK1JQbkJjbUdi + bGU3WWhVMGJ2LzI4N2E1Zy9RNnJ2V2MK4UQPwE5GUVTGvnuZ9knQ+BHmzmRLA1V5 + SinlJfHcs+9B7haHzAekDdNqZgEUh2tblabHqq/vNWzd0rWpK31Dww== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-21T16:02:33Z" + mac: ENC[AES256_GCM,data:FCxkzhMTplghsBfPMSR1LeIKcVRZ4o6sfmZjTQFvgJyecHM81zytxisUCGLqJb4/80Im+eUhHw8Pq+UrF3N7R/YtPsVWTaVzCguS4A0WVpEiOPmikTAekV0/6pyYJcYlnuIi9xQ55+ud1lE9Iq0u+S58MvcpdsRhh/SH+jbTFlc=,iv:HrC5aEwJZka9uYFhfS7MPnqlwHzI9CMpUipXbOlenDY=,tag:tNzURnfJ9+9+UJsn92YUXg==,type:str] + unencrypted_suffix: _unencrypted + version: 3.12.1 From e3a9a391c2a1b6a8d578ae6274e37c7c569ca831 Mon Sep 17 00:00:00 2001 From: goeranh Date: Sat, 21 Mar 2026 18:04:08 +0100 Subject: [PATCH 04/42] use secret files --- hosts/auth/authentik.nix | 17 +++++++++++++---- hosts/mail/default.nix | 7 ++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/hosts/auth/authentik.nix b/hosts/auth/authentik.nix index 0e04762..4ae125b 100644 --- a/hosts/auth/authentik.nix +++ b/hosts/auth/authentik.nix @@ -19,15 +19,24 @@ enable = true; }; }; + users.groups.authentik-ldap = {}; + users.users.authentik-ldap = { + isSystemUser = true; + group = "authentik-ldap"; + }; + systemd.services.authentik-ldap.serviceConfig = { + DynamicUser = lib.mkForce false; + User = "authentik-ldap"; + }; services.authentik-ldap = { enable = true; - environmentFile = "/var/lib/authentik-ldap-env"; + environmentFile = config.sops.secrets."auth/ldap-env-file".path; + # environmentFile = "/var/lib/authentik-ldap-env"; }; services.authentik = { enable = true; - # The environmentFile needs to be on the target host! - # Best use something like sops-nix or agenix to manage it - environmentFile = "/var/lib/authentik_secret"; + # environmentFile = "/var/lib/authentik_secret"; + environmentFile = config.sops.secrets."auth/env-file".path; settings = { email = { host = "mail.${config.networking.domain}"; diff --git a/hosts/mail/default.nix b/hosts/mail/default.nix index 6d3c388..a532988 100644 --- a/hosts/mail/default.nix +++ b/hosts/mail/default.nix @@ -103,8 +103,9 @@ in enable = true; bind = { # dn = "cn=dovecot,ou=users,DC=test,DC=htw,DC=stura-dresden,DC=de"; - dn = "cn=ldapuser,ou=users,dc=ldap,dc=goauthentik,dc=io"; - passwordFile = "/var/lib/dovecot_ldap_passwd"; + dn = "cn=mail,ou=users,dc=mail,dc=htw,dc=stura-dresden,dc=de"; + # passwordFile = "/var/lib/dovecot_ldap_passwd"; + passwordFile = config.sops.secrets.ldap_passwd.path; }; dovecot = { userFilter = "(&(objectClass=posixAccount)(mail=%u))"; @@ -117,7 +118,7 @@ in uidAttribute = "cn"; }; #searchBase = "DC=test,DC=htw,DC=stura-dresden,DC=de"; - searchBase = "DC=ldap,DC=goauthentik,DC=io"; + searchBase = "dc=mail,dc=htw,dc=stura-dresden,dc=de"; uris = [ "ldap://auth.test.htw.stura-dresden.de:3389" ]; From 26d56a1dfe5c3690a12ec6f86850f38485e34c4e Mon Sep 17 00:00:00 2001 From: goeranh Date: Sat, 21 Mar 2026 18:23:28 +0100 Subject: [PATCH 05/42] update dovecot ldap credentials --- hosts/mail/default.nix | 2 +- hosts/mail/secrets.sops.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hosts/mail/default.nix b/hosts/mail/default.nix index a532988..c4bf5f3 100644 --- a/hosts/mail/default.nix +++ b/hosts/mail/default.nix @@ -103,7 +103,7 @@ in enable = true; bind = { # dn = "cn=dovecot,ou=users,DC=test,DC=htw,DC=stura-dresden,DC=de"; - dn = "cn=mail,ou=users,dc=mail,dc=htw,dc=stura-dresden,dc=de"; + dn = "cn=dovecot,ou=users,dc=mail,dc=htw,dc=stura-dresden,dc=de"; # passwordFile = "/var/lib/dovecot_ldap_passwd"; passwordFile = config.sops.secrets.ldap_passwd.path; }; diff --git a/hosts/mail/secrets.sops.yml b/hosts/mail/secrets.sops.yml index 8a51068..b9d0b6a 100644 --- a/hosts/mail/secrets.sops.yml +++ b/hosts/mail/secrets.sops.yml @@ -1,4 +1,4 @@ -ldap_passwd: ENC[AES256_GCM,data:wAtRF+7QNgkHAKoQVYZeepshAo/dHuGBC3L15svZ5NVpqaTAtWKIVz/tT/SkjxjC2OXTkzUxin4JMGS6,iv:RELJtuCRLPyqzxUqN2KYTI5/P4fiQALRVtr+xZmKUOY=,tag:2ZS1jmAxw3dohAC6zJLUCQ==,type:str] +ldap_passwd: ENC[AES256_GCM,data:adUZCZcYfoxBQm3e4YeeXcQJSZjB3+v2zSNy7q0Ao39aDQMH5H0w4o9MXTREkPHW53JejC2ivo8Zl3yUhkeYRw==,iv:XB25CmtUGf+PeSsHtr+CA/HIfZq1IrOBPPQD3/r6Kc4=,tag:A/WGViM/Ix7n6mhjnbCtZg==,type:str] sops: age: - recipient: age156ak7kc79tuwpv0hk9atl5dg27jqs6ddfqxvr9m4twqgsr23lgvsdmyfpr @@ -19,7 +19,7 @@ sops: bGU3WWhVMGJ2LzI4N2E1Zy9RNnJ2V2MK4UQPwE5GUVTGvnuZ9knQ+BHmzmRLA1V5 SinlJfHcs+9B7haHzAekDdNqZgEUh2tblabHqq/vNWzd0rWpK31Dww== -----END AGE ENCRYPTED FILE----- - lastmodified: "2026-03-21T16:02:33Z" - mac: ENC[AES256_GCM,data:FCxkzhMTplghsBfPMSR1LeIKcVRZ4o6sfmZjTQFvgJyecHM81zytxisUCGLqJb4/80Im+eUhHw8Pq+UrF3N7R/YtPsVWTaVzCguS4A0WVpEiOPmikTAekV0/6pyYJcYlnuIi9xQ55+ud1lE9Iq0u+S58MvcpdsRhh/SH+jbTFlc=,iv:HrC5aEwJZka9uYFhfS7MPnqlwHzI9CMpUipXbOlenDY=,tag:tNzURnfJ9+9+UJsn92YUXg==,type:str] + lastmodified: "2026-03-21T17:05:32Z" + mac: ENC[AES256_GCM,data:A2tbQ8obTjzKeISAbDy0Sqi+WvpqZwkKSW2PmV67V2u/svNfC7C/ebNHp6p0I9N97y026WzboXnRwon7M1jaJ8dPn2hqGReZIIHW5w5rBK0uAeEH5wCMnNGslox4D7+L27zc4VZMK4tjFP6F7EKkq7TIjf+HzEYW+kpbqM2erVo=,iv:EKa3JBlDiU/FcF2T/hQtmaFlYiAbFIlytR3fSfJjVBc=,tag:B4N/4XxhdtNYKTRT1O+UyA==,type:str] unencrypted_suffix: _unencrypted version: 3.12.1 From 9c10e99502766fe490b80ed061b9e07d3e1f304b Mon Sep 17 00:00:00 2001 From: goeranh Date: Sat, 21 Mar 2026 21:27:14 +0100 Subject: [PATCH 06/42] wireguard network connection proxy->v6proxy works connection mail->v6proxy blocked --- .sops.yaml | 12 +++++++++++ hosts/mail/default.nix | 23 ++++++++++++++++++++ hosts/mail/secrets.sops.yml | 5 +++-- hosts/proxy/default.nix | 32 ++++++++++++++++++++++++++++ hosts/proxy/secrets.sops.yml | 25 ++++++++++++++++++++++ hosts/v6proxy/default.nix | 38 ++++++++++++++++++++++++++++++++++ hosts/v6proxy/secrets.sops.yml | 25 ++++++++++++++++++++++ 7 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 hosts/proxy/secrets.sops.yml create mode 100644 hosts/v6proxy/secrets.sops.yml diff --git a/.sops.yaml b/.sops.yaml index 66644ad..07b1f6b 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -2,6 +2,8 @@ keys: - &goeranh age1qp7w80k3qtj79xsl0gwsfrkm037xrlnhm6th7tcyrvufh3szzp6s2pe7ra - &mail age156ak7kc79tuwpv0hk9atl5dg27jqs6ddfqxvr9m4twqgsr23lgvsdmyfpr - &auth age1njnkkr489hfmpn337zna2k3z66y9086t7cpcmz2vn68p4x43aujs6wh0g5 + - &v6proxy age1gl8zmw86jkrkr7kaqugdyhvdhdrnfd72smndz2kfh4a6ec6s9yxsyrecu6 + - &proxy age1g9fnxzalnqtse29xjdrvcsrnrknp8t2s7xrle73fce0jcg7r3czsj524p4 creation_rules: @@ -15,3 +17,13 @@ creation_rules: - age: - *auth - *goeranh + - path_regex: hosts/v6proxy/secrets.sops.yml$ + key_groups: + - age: + - *v6proxy + - *goeranh + - path_regex: hosts/proxy/secrets.sops.yml$ + key_groups: + - age: + - *proxy + - *goeranh diff --git a/hosts/mail/default.nix b/hosts/mail/default.nix index c4bf5f3..61b9766 100644 --- a/hosts/mail/default.nix +++ b/hosts/mail/default.nix @@ -29,6 +29,7 @@ in defaultSopsFile = ./secrets.sops.yml; secrets = { "ldap_passwd".owner = "dovecot2"; + "wireguard-key".owner = "systemd-network"; }; }; imports = [ @@ -59,6 +60,28 @@ in address = "141.56.51.254"; interface = "eth0"; }; + wireguard = { + enable = true; + interfaces = { + sturauplink = { + privateKeyFile = config.sops.secrets."wireguard-key".path; + ips = [ + "10.100.0.20/24" + "fd28:6691:1921:6299::20/64" + ]; + peers = [ + # mail.test.htw.stura-dresden.de + { + endpoint = "hetzner.test.htw.stura-dresden.de:51820"; + allowedIPs = [ + "10.100.0.1/24" + ]; + publicKey = "Tg/SNniezzF4DUnvUl1/JxQwS18POrUR20UmkQDt+X0="; + } + ]; + }; + }; + }; }; services.nginx.virtualHosts = { diff --git a/hosts/mail/secrets.sops.yml b/hosts/mail/secrets.sops.yml index b9d0b6a..a90cdf0 100644 --- a/hosts/mail/secrets.sops.yml +++ b/hosts/mail/secrets.sops.yml @@ -1,4 +1,5 @@ ldap_passwd: ENC[AES256_GCM,data:adUZCZcYfoxBQm3e4YeeXcQJSZjB3+v2zSNy7q0Ao39aDQMH5H0w4o9MXTREkPHW53JejC2ivo8Zl3yUhkeYRw==,iv:XB25CmtUGf+PeSsHtr+CA/HIfZq1IrOBPPQD3/r6Kc4=,tag:A/WGViM/Ix7n6mhjnbCtZg==,type:str] +wireguard-key: ENC[AES256_GCM,data:5EWg5yF1CDKIusFwONVSzxSMM0cfOzyUYcWQ0f8xTHZ7bViAw8HbjJpRI4o=,iv:UNTv+994Q5VscsjgWS4ppkHX0gPy7vc/qmRCYKvR8CE=,tag:i8ydlyJSfIUj81j78EX5Fg==,type:str] sops: age: - recipient: age156ak7kc79tuwpv0hk9atl5dg27jqs6ddfqxvr9m4twqgsr23lgvsdmyfpr @@ -19,7 +20,7 @@ sops: bGU3WWhVMGJ2LzI4N2E1Zy9RNnJ2V2MK4UQPwE5GUVTGvnuZ9knQ+BHmzmRLA1V5 SinlJfHcs+9B7haHzAekDdNqZgEUh2tblabHqq/vNWzd0rWpK31Dww== -----END AGE ENCRYPTED FILE----- - lastmodified: "2026-03-21T17:05:32Z" - mac: ENC[AES256_GCM,data:A2tbQ8obTjzKeISAbDy0Sqi+WvpqZwkKSW2PmV67V2u/svNfC7C/ebNHp6p0I9N97y026WzboXnRwon7M1jaJ8dPn2hqGReZIIHW5w5rBK0uAeEH5wCMnNGslox4D7+L27zc4VZMK4tjFP6F7EKkq7TIjf+HzEYW+kpbqM2erVo=,iv:EKa3JBlDiU/FcF2T/hQtmaFlYiAbFIlytR3fSfJjVBc=,tag:B4N/4XxhdtNYKTRT1O+UyA==,type:str] + lastmodified: "2026-03-21T18:05:57Z" + mac: ENC[AES256_GCM,data:NJM8uwSGIrjy4t+3AwNxp2e569ArH/cnRDipsHnTTQYV5NJLOTtwoFnTqVHBSREc2Sh38gXKye1ncwS3IG5CMsF1nsLOL/+Y9mUqQkLeWeld6Kal8c99yIr2oz8Hk4JTJt4j2C8/aNFhqu62VF7F6JNElWq2F3J5TPKPHRbE9yY=,iv:mj18t2s9hqNV4ore9T4R4jOgUGPuXGqwW91M9Uoh6aQ=,tag:v6T7LXjLQGoc9leFI5zY0g==,type:str] unencrypted_suffix: _unencrypted version: 3.12.1 diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index 3a727f3..37d7951 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -6,6 +6,12 @@ ... }: { + sops = { + defaultSopsFile = ./secrets.sops.yml; + secrets = { + "wireguard-key".owner = "systemd-network"; + }; + }; imports = [ ./hardware-configuration.nix ./hetzner-disk.nix @@ -13,6 +19,7 @@ networking = { hostName = "proxy"; + nameservers = [ "141.56.51.1" ]; interfaces.ens18.ipv4.addresses = [ { address = "141.56.51.1"; @@ -37,6 +44,30 @@ nftables = { enable = true; }; + wireguard = { + enable = true; + interfaces = { + sturauplink = { + privateKeyFile = config.sops.secrets."wireguard-key".path; + ips = [ + "10.100.0.2/24" + "fd28:6691:1921:6299::2/64" + ]; + listenPort = 51820; + peers = [ + # mail.test.htw.stura-dresden.de + { + endpoint = "hetzner.test.htw.stura-dresden.de:51820"; + allowedIPs = [ + "10.100.0.0/24" + ]; + persistentKeepalive = 30; + publicKey = "Tg/SNniezzF4DUnvUl1/JxQwS18POrUR20UmkQDt+X0="; + } + ]; + }; + }; + }; }; # wenn instanzen in die flake migriert sind könnte man das autogenerierien @@ -255,6 +286,7 @@ proxy IN AAAA 2a01:4f8:1c19:96f8::1 ; Auto-generated CNAME records for all subdomains pointing to proxy + hetzner.test IN A 178.104.18.93 ${lib.foldlAttrs ( prev: name: value: let diff --git a/hosts/proxy/secrets.sops.yml b/hosts/proxy/secrets.sops.yml new file mode 100644 index 0000000..207a35b --- /dev/null +++ b/hosts/proxy/secrets.sops.yml @@ -0,0 +1,25 @@ +wireguard-key: ENC[AES256_GCM,data:tEKd+iwfyabTj/spqh08Um3FX4grLeffTxCvBivkXrNqIzOymBdcgQL4IJ4=,iv:Z2sr5yzxTKXgBgfcd3LWB9jT2fX3uRpX07r4yMplSNY=,tag:IWgiEjjbHbIUORhwKjTM6g==,type:str] +sops: + age: + - recipient: age1g9fnxzalnqtse29xjdrvcsrnrknp8t2s7xrle73fce0jcg7r3czsj524p4 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXcUhhSlVQcHgvUEtDa0E2 + UU1ON3NiUUlHTXFUOEdNeUdGVWNVTWRRNW0wCmhTVnJONlZSMmt2OVJiMys5bnM2 + TDZPMExYaWlKSVFPVERnS1QvVTJlNXMKLS0tIElTYmxHNTFPSmNXYnkrY2RtRUVL + WHBCYWhtSWt1QW9hbEFwVmdqWUxjUmMKpqfV/bJVfyDI2Wa+jlwsXMx3tNV9G0S2 + VhmmpDnEJn6UDWAMYxNv0g3rtfhBkb2HyCtANNVQ7QROua9WHzJjlg== + -----END AGE ENCRYPTED FILE----- + - recipient: age1qp7w80k3qtj79xsl0gwsfrkm037xrlnhm6th7tcyrvufh3szzp6s2pe7ra + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBVVUVkdDljcForNEJ2WmNm + N0QvTWhQWXQ1VHh5b0pCZFQ3aGxXSGY2bXprCmpEV2l6bkxnUDByNVZaVVR6N2lE + OG1sYkJrQmFVWW1vWXRZL1A2S29MejQKLS0tIEFKbkRmdWM0QW9vVlJWZElXSUcw + b1pCMjNIN1padE5JNVpZNFYwMnZGd00KM415cr6nuN6zfhDcfXFN2lMDWogLwDSE + Kq/ykUSuN9IU6AhslgBNRCmJRVHIzCmu5dU5NVZeqN1YT/EyAbEcyw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-21T18:56:03Z" + mac: ENC[AES256_GCM,data:v1RkpxjvgLHS3OOA2aEG+uJ3yWpOvJLwFA5jRBRtMoMvrBD8O8sikzWJUczQnpw85F/ieFqK6RdT8SBA9lIuPXYMRRS8icHI2a8P+zwySsWsnzc9UaJjjvKtkYo9nnPNCM36HAFOKHiAzBm7FWMt1Tl+WQMyVCWLXCN7ao0MjIo=,iv:8xCrY7QOhW5Mc/AWWXFocqwTUD9qvH4dLYYtnsU6PHw=,tag:09Nw7qFfjefrv0jBwaFINA==,type:str] + unencrypted_suffix: _unencrypted + version: 3.12.1 diff --git a/hosts/v6proxy/default.nix b/hosts/v6proxy/default.nix index 6dd17b3..a87195b 100644 --- a/hosts/v6proxy/default.nix +++ b/hosts/v6proxy/default.nix @@ -6,6 +6,12 @@ ... }: { + sops = { + defaultSopsFile = ./secrets.sops.yml; + secrets = { + "wireguard-key".owner = "systemd-network"; + }; + }; imports = [ ./hardware-configuration.nix ./hetzner-disk.nix @@ -48,6 +54,37 @@ nftables = { enable = true; }; + wireguard = { + enable = true; + interfaces = { + sturauplink = { + listenPort = 51820; + privateKeyFile = config.sops.secrets."wireguard-key".path; + ips = [ + "10.100.0.1/24" + "fd28:6691:1921:6299::1/64" + ]; + peers = [ + # mail.test.htw.stura-dresden.de + { + allowedIPs = [ + "10.100.0.20/32" + ]; + publicKey = "9Ep/YZLbnGEVWHgVmmwq2Sv/8awwGaHdwiSuIUkWtnk="; + } + # proxy.htw.stura-dresden.de + { + allowedIPs = [ + "10.100.0.2/32" + "fd28:6691:1921:6299::2/64" + ]; + endpoint = "141.56.51.1:51820"; + publicKey = "pUHtAHCDHVQBnqtlIgTkEMHbxXpQmVA0HhxiFUrUb0U="; + } + ]; + }; + }; + }; }; # wenn instanzen in die flake migriert sind könnte man das autogenerierien @@ -102,6 +139,7 @@ }; environment.systemPackages = with pkgs; [ + wireguard-tools ]; system.stateVersion = "25.11"; diff --git a/hosts/v6proxy/secrets.sops.yml b/hosts/v6proxy/secrets.sops.yml new file mode 100644 index 0000000..46628d1 --- /dev/null +++ b/hosts/v6proxy/secrets.sops.yml @@ -0,0 +1,25 @@ +wireguard-key: ENC[AES256_GCM,data:K3UoCWtF2rL8uCzmu8yn4sHKHOrcKmnNBvRQdC9Ph3fWMdDqNqh0jwSByjQ=,iv:feFxNykRK1RJ6EPPVXqXtEVmXeGez4PwJ9h7m1KYUIE=,tag:hSTf/gAUVSjI1GburqRDVA==,type:str] +sops: + age: + - recipient: age1gl8zmw86jkrkr7kaqugdyhvdhdrnfd72smndz2kfh4a6ec6s9yxsyrecu6 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsbVd3OUNCMUI3eUI2QlVa + WFNjVUpXYVlLdUxiSzhQdHhhRWRpWEhzV1IwCkdYMG5DOXBxTnMwNFpYM1FweDNp + ZXd2aXJaNWxOYXRnaW1nSjdNQVpQOU0KLS0tIEY4Q1JqV1FSekVwc0prNjRCUDdm + cmpLdW1abFR5SlhxZnpJdnBlNjJQOGMK+JcLyiSCfhVPnhqpqTzB7flFWTff3GcK + 9779AvKVnhsDb5LDPOi4Ah5gAJfq+JZ/+IiTUqk0a4AWuN9PiyTMGA== + -----END AGE ENCRYPTED FILE----- + - recipient: age1qp7w80k3qtj79xsl0gwsfrkm037xrlnhm6th7tcyrvufh3szzp6s2pe7ra + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBncnVRVi91OWsxejJiS0Y0 + L2licWRJQ1pGTlZOMEM0VHdyOWlFbEgyRENVCmwxSndQamRZM2NKbW14TTI4aFBV + MHQ3YkJwNUhkWlJNSTB2RFBpZEswT28KLS0tIC9EVUxvYk04ek5xc1d4TXl5RFVD + MkFyQkxCWDdWQjUxQ0QwcjlScGxPWWMKtzYvXoSSPGhVFlwzdtZylu3eTE5EKxqO + OIq9IOOujV3K1dzj5uwmCI+EoEasOMLy7Sa4++1WZmRVmVxFa91/gw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-21T17:41:20Z" + mac: ENC[AES256_GCM,data:f94ubkkhUDMkvEPEYYGVg1mahaMmXqAdMcF9Vl16jj7FQTvJy9GCg+1F7eBOu0endpcTQo2a/apd2u7tnzA0IE3CfXo2U8d8aun6yTxxn9qopnxypP2v6mGDHsGbaUI3r+/ZgLXtGDDN+gS/zyu06CPFq/TdLnmcO9zuXAeBmWc=,iv:5VEsRV20A56FKNRQlgojY5TQLhW+kgotQBPgElZY+uQ=,tag:K13Owxl3MDwf5n9soXxiXA==,type:str] + unencrypted_suffix: _unencrypted + version: 3.12.1 From ca8c213e74dc79af533c10915b65cd4a3d385ac4 Mon Sep 17 00:00:00 2001 From: oxce Date: Fri, 27 Mar 2026 18:11:47 +0100 Subject: [PATCH 07/42] =?UTF-8?q?=C3=84nderung=20der=20adresse=20vom=20smt?= =?UTF-8?q?p=20mailserver?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hosts/redmine/default.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hosts/redmine/default.nix b/hosts/redmine/default.nix index d327168..6bc3d5e 100644 --- a/hosts/redmine/default.nix +++ b/hosts/redmine/default.nix @@ -90,7 +90,9 @@ services.redmine.settings.production.email_delivery = { delivery_method = ":smtp"; smtp_settings = { - address = "mail.${config.networking.domain}"; + # @tan 27-03-2026: muss an "alten" mailserver senden + #address = "mail.${config.networking.domain}"; + address = "mail.stura.htw-dresden.de"; port = 25; }; #### Alternativ waere vielleicht auch das Versand von Mails durch das Programm sendmail (als lokale Installation) moeglich. From fe6650622f2436b6eaef483e643b917f208cb122 Mon Sep 17 00:00:00 2001 From: goeranh Date: Fri, 10 Apr 2026 15:38:30 +0200 Subject: [PATCH 08/42] haproxy maxconn --- hosts/proxy/default.nix | 102 +++++++++++++++++++++++++++++++++++----- 1 file changed, 90 insertions(+), 12 deletions(-) diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index 3a727f3..52c9d82 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -39,6 +39,52 @@ }; }; + # Phase 1: Kernel-Level TCP Tuning + boot.kernel.sysctl = { + # Connection tracking - prevents "table full" errors + "net.netfilter.nf_conntrack_max" = 262144; # Conservative limit matching current kernel + "net.netfilter.nf_conntrack_buckets" = 65536; # 4:1 ratio + + # Reduce connection tracking timeouts (defaults are excessive) + "net.netfilter.nf_conntrack_tcp_timeout_established" = 600; # 10 min (down from 5 days) + "net.netfilter.nf_conntrack_tcp_timeout_time_wait" = 30; # 30s + "net.netfilter.nf_conntrack_tcp_timeout_close_wait" = 15; # 15s + "net.netfilter.nf_conntrack_tcp_timeout_fin_wait" = 30; # 30s + + # TCP connection handling + "net.core.somaxconn" = 65535; # Must be >= HAProxy maxconn + "net.core.netdev_max_backlog" = 16384; + "net.ipv4.tcp_max_syn_backlog" = 8192; + + # TCP buffer auto-tuning (16MB max) + "net.ipv4.tcp_rmem" = "4096 87380 16777216"; + "net.ipv4.tcp_wmem" = "4096 65536 16777216"; + "net.core.rmem_max" = 16777216; + "net.core.wmem_max" = 16777216; + + # TCP optimization + "net.ipv4.tcp_fin_timeout" = 15; + "net.ipv4.tcp_keepalive_time" = 300; # 5 min + "net.ipv4.tcp_keepalive_probes" = 3; + "net.ipv4.tcp_keepalive_intvl" = 15; + + # TCP Fast Open + "net.ipv4.tcp_fastopen" = 3; + + # BBR congestion control for better throughput + "net.ipv4.tcp_congestion_control" = "bbr"; + "net.core.default_qdisc" = "fq"; + + # Ephemeral port range + "net.ipv4.ip_local_port_range" = "10000 65535"; + + # TIME_WAIT socket reuse + "net.ipv4.tcp_tw_reuse" = 1; + }; + + # Enable BBR kernel module + boot.kernelModules = [ "tcp_bbr" ]; + # wenn instanzen in die flake migriert sind könnte man das autogenerierien services = let @@ -345,20 +391,37 @@ enable = true; config = '' global - # schreibe globalen log ins journal ip -> app + # schreibe globalen log ins journal ip -> app log /dev/log format raw local0 - maxconn 50000 - # man könnte metriken über einen socket file statt einen lokalen port machen für user permission control - # stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners - tune.bufsize 32762 + maxconn 60000 # Safe limit below kernel conntrack (262144) + + # Buffer optimizations (Phase 2) + tune.bufsize 32768 # Power of 2 (was 32762) + tune.maxrewrite 8192 + + # Connection handling + tune.maxaccept 500 # Prevent accept starvation + tune.maxpollevents 300 + + # TCP buffer sizes (64KB) + tune.rcvbuf.client 65536 + tune.rcvbuf.server 65536 + tune.sndbuf.client 65536 + tune.sndbuf.server 65536 defaults log global mode tcp option tcplog - timeout connect 5s - timeout client 30s - timeout server 30s + + # Optimized timeouts (Phase 5) + timeout connect 3s # Reduce from 5s + timeout client 60s # Increase from 30s + timeout server 60s # Increase from 30s + timeout queue 5s # Prevent indefinite queueing + + # Performance + option splice-auto # Zero-copy kernel splicing # stats seite zeigt backend connection status, wenn check gesetzt ist frontend stats @@ -366,13 +429,18 @@ mode http stats enable stats uri /stats - stats refresh 10s + stats refresh 5s # Reduce from 10s for real-time monitoring stats show-legends stats show-node stats show-modules + stats admin if TRUE # Enable admin operations frontend http-in bind *:80 + maxconn 60000 + backlog 8192 + option dontlognull + option http-keep-alive # Reuse connections for redirects # hier wird eine regel pro domain aus der forwarder liste generiert ${lib.foldlAttrs ( @@ -413,10 +481,17 @@ frontend sni_router bind *:443 mode tcp - # mehrere pakete puffern und connection beenden wenn es kein ssl handshake sieht - tcp-request inspect-delay 1s + + # Reduce inspection delay - SNI is in first packet (Phase 3) + tcp-request inspect-delay 500ms # Was 1s tcp-request content accept if { req_ssl_hello_type 1 } + # Connection handling + option clitcpka # Enable client TCP keep-alive + maxconn 60000 + backlog 16384 # Increase from default 1024 + option dontlognull # Skip logging of monitoring probes + # tcp redirect der anwendung basierend auf ssl_sni handshake parameter ${lib.foldlAttrs ( prev: name: value: @@ -447,7 +522,10 @@ server ${name} ${value.dest}:${builtins.toString value.httpPort} backend ${name}_443 mode tcp - server ${name} ${value.dest}:${builtins.toString value.httpsPort} check + option tcpka # Enable server TCP keep-alive (Phase 4) + timeout server 60s # Increase from 30s for long-lived HTTPS + timeout connect 3s # Reduce from 5s (local network) + server ${name} ${value.dest}:${builtins.toString value.httpsPort} check inter 3000 rise 2 fall 3 maxconn 5000 '' ) "" forwards} From 9041fe3d699cbbbf9d0a822a87ec76a821399809 Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 08:56:40 +0200 Subject: [PATCH 09/42] conditionally send proxy protocol --- hosts/proxy/default.nix | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index 52c9d82..8c1b49c 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -98,108 +98,126 @@ domain = "docs.adm.htw.stura-dresden.de"; httpPort = 8080; httpsPort = 8443; + sendProxy = false; }; plone = { dest = "141.56.51.3"; domain = "stura.htw-dresden.de"; httpPort = 80; httpsPort = 443; + sendProxy = false; }; plone_alt = { dest = "141.56.51.3"; domain = "www.stura.htw-dresden.de"; httpPort = 80; httpsPort = 443; + sendProxy = false; }; plone_neu = { dest = "141.56.51.3"; domain = "www.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; + sendProxy = false; }; plone_neu2 = { dest = "141.56.51.3"; domain = "htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; + sendProxy = false; }; tix = { dest = "141.56.51.220"; domain = "tix.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; + sendProxy = false; }; post = { dest = "141.56.51.56"; domain = "post.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; + sendProxy = false; }; vot = { dest = "141.56.51.57"; domain = "vot.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; + sendProxy = false; }; mail = { dest = "141.56.51.14"; domain = "mail.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; + sendProxy = false; }; lists = { dest = "141.56.51.14"; domain = "lists.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; + sendProxy = false; }; dat = { dest = "141.56.51.17"; domain = "dat.stu.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; + sendProxy = false; }; pro = { dest = "141.56.51.15"; domain = "pro.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; + sendProxy = false; }; cloud = { dest = "141.56.51.16"; domain = "cloud.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; + sendProxy = false; }; wiki = { dest = "141.56.51.13"; domain = "wiki.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; + sendProxy = false; }; beach = { dest = "141.56.51.51"; domain = "beach.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; + sendProxy = false; }; studicloud = { dest = "141.56.51.17"; domain = "dat.stu.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; + sendProxy = false; }; bbb = { dest = "141.56.51.94"; domain = "bbb.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; + sendProxy = false; }; bbb-test = { dest = "141.56.51.94"; domain = "bbb.test.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; + sendProxy = false; }; } # zusätzlich zu den oben definierten wird hier noch ein redirect für jeden nginx virtualhost in diese flake generiert @@ -218,6 +236,10 @@ prev // (builtins.foldl' ( val: vhost: + let + proxyProtocol = if self.nixosConfigurations.${name}.config.services.nginx.virtualHosts.${vhost}.listen == [] then false else + true; + in val // { "${vhost}" = { @@ -225,6 +247,7 @@ domain = vhost; httpsPort = 443; httpPort = 80; + sendProxy = proxyProtocol; }; } ) { } vhosts) @@ -519,13 +542,13 @@ backend ${name}_80 mode http - server ${name} ${value.dest}:${builtins.toString value.httpPort} + server ${name} ${value.dest}:${builtins.toString value.httpPort} ${if value.sendProxy == true then "send-proxy-v2" else ""} backend ${name}_443 mode tcp option tcpka # Enable server TCP keep-alive (Phase 4) timeout server 60s # Increase from 30s for long-lived HTTPS timeout connect 3s # Reduce from 5s (local network) - server ${name} ${value.dest}:${builtins.toString value.httpsPort} check inter 3000 rise 2 fall 3 maxconn 5000 + server ${name} ${value.dest}:${builtins.toString value.httpsPort} ${if value.sendProxy == true then "send-proxy-v2" else ""} check inter 3000 rise 2 fall 3 maxconn 5000 '' ) "" forwards} From a96f976be1ba4fb059aba8290656b1bb91b7ac0e Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 09:02:20 +0200 Subject: [PATCH 10/42] does not work on port 80 with acme --- hosts/proxy/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index 8c1b49c..200ede2 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -542,7 +542,7 @@ backend ${name}_80 mode http - server ${name} ${value.dest}:${builtins.toString value.httpPort} ${if value.sendProxy == true then "send-proxy-v2" else ""} + server ${name} ${value.dest}:${builtins.toString value.httpPort} backend ${name}_443 mode tcp option tcpka # Enable server TCP keep-alive (Phase 4) From 279e1064270102934fb8607be70b7c2af7769fcb Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 09:17:36 +0200 Subject: [PATCH 11/42] fix cloud duplicate --- hosts/proxy/default.nix | 7 ------- 1 file changed, 7 deletions(-) diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index 200ede2..2400a9a 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -177,13 +177,6 @@ httpsPort = 443; sendProxy = false; }; - cloud = { - dest = "141.56.51.16"; - domain = "cloud.htw.stura-dresden.de"; - httpPort = 80; - httpsPort = 443; - sendProxy = false; - }; wiki = { dest = "141.56.51.13"; domain = "wiki.htw.stura-dresden.de"; From 582822cd5b9a5a11c227d7438670a08da8d1d012 Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 09:45:47 +0200 Subject: [PATCH 12/42] remove explicit proxy, its in this flake --- hosts/proxy/default.nix | 7 ------- 1 file changed, 7 deletions(-) diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index 2400a9a..1d79967 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -170,13 +170,6 @@ httpsPort = 443; sendProxy = false; }; - pro = { - dest = "141.56.51.15"; - domain = "pro.htw.stura-dresden.de"; - httpPort = 80; - httpsPort = 443; - sendProxy = false; - }; wiki = { dest = "141.56.51.13"; domain = "wiki.htw.stura-dresden.de"; From 5b2eb482dfc9165b3af084ee7817146603374ce3 Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 10:24:30 +0200 Subject: [PATCH 13/42] formatting in proxy --- hosts/proxy/default.nix | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index 1d79967..b92bea6 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -222,10 +222,15 @@ prev // (builtins.foldl' ( val: vhost: - let - proxyProtocol = if self.nixosConfigurations.${name}.config.services.nginx.virtualHosts.${vhost}.listen == [] then false else + let + proxyProtocol = + if + self.nixosConfigurations.${name}.config.services.nginx.virtualHosts.${vhost}.listen == [ ] + then + false + else true; - in + in val // { "${vhost}" = { @@ -534,7 +539,9 @@ option tcpka # Enable server TCP keep-alive (Phase 4) timeout server 60s # Increase from 30s for long-lived HTTPS timeout connect 3s # Reduce from 5s (local network) - server ${name} ${value.dest}:${builtins.toString value.httpsPort} ${if value.sendProxy == true then "send-proxy-v2" else ""} check inter 3000 rise 2 fall 3 maxconn 5000 + server ${name} ${value.dest}:${builtins.toString value.httpsPort} ${ + if value.sendProxy == true then "send-proxy-v2" else "" + } check inter 3000 rise 2 fall 3 maxconn 5000 '' ) "" forwards} From f91ac73b72b4cfe19e10731e1bf491585bf32c8d Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 10:26:33 +0200 Subject: [PATCH 14/42] enable proxy protocol in nextcloud --- hosts/nextcloud/default.nix | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/hosts/nextcloud/default.nix b/hosts/nextcloud/default.nix index 304becf..80c0bb3 100644 --- a/hosts/nextcloud/default.nix +++ b/hosts/nextcloud/default.nix @@ -87,6 +87,11 @@ recommendedProxySettings = true; recommendedTlsSettings = true; + commonHttpConfig = '' + real_ip_header proxy_protocol; + set_real_ip_from 141.56.51.1/32; + ''; + logError = '' /dev/null emerg ''; @@ -94,9 +99,21 @@ virtualHosts.${config.networking.fqdn} = { forceSSL = true; enableACME = true; - extraConfig = '' - access_log off; - ''; + listen = [ + { + port = 80; + addr = "0.0.0.0"; + } + { + port = 443; + addr = "0.0.0.0"; + ssl = true; + proxyProtocol = true; + } + ]; + # extraConfig = '' + # access_log off; + # ''; }; # virtualHosts."cloud.htw.stura-dresden.de" = { # forceSSL = true; From 29cff6eee846a586360439a72c84c0d04904b934 Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 10:26:46 +0200 Subject: [PATCH 15/42] enable proxy protocol for wiki --- hosts/proxy/default.nix | 2 +- hosts/wiki/default.nix | 23 +++++++++++++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index b92bea6..a806790 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -175,7 +175,7 @@ domain = "wiki.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; - sendProxy = false; + sendProxy = true; }; beach = { dest = "141.56.51.51"; diff --git a/hosts/wiki/default.nix b/hosts/wiki/default.nix index bd8bbb6..c73a5cb 100644 --- a/hosts/wiki/default.nix +++ b/hosts/wiki/default.nix @@ -99,6 +99,17 @@ services.mediawiki.database.passwordFile = "/var/lib/mediawiki/mediawiki-dbpassword"; + services.httpd = { + extraModules = [ "remoteip" ]; + + extraConfig = '' + # Trust HAProxy's address (adjust to your HAProxy IP/subnet) + RemoteIPProxyProtocol On + # RemoteIPProxyProtocolExceptions 127.0.0.1 ::1 + + RemoteIPTrustedProxy 141.56.51.1/32 + ''; + }; #### 2024-02-17 vater: #### trace: warning: The option `services.mediawiki.virtualHost' defined in `/etc/nixos/configuration.nix' has been renamed to `services.mediawiki.httpd.virtualHost'. # services.mediawiki.virtualHost.hostName = "wiki.stura.htw-dresden.de"; @@ -150,8 +161,8 @@ Lockdown = pkgs.fetchzip { # url = "https://extdist.wmflabs.org/dist/extensions/Lockdown-REL1_43-7ac8966.tar.gz"; # url = "https://extdist.wmflabs.org/dist/extensions/Lockdown-REL1_44-af1f4df.tar.gz"; - url = "https://extdist.wmflabs.org/dist/extensions/Lockdown-REL1_45-a46dbea.tar.gz"; - sha256 = "sha256-zTTpbQiqudLILPSzmKGjKr6wZjh0YUttGmqwjPpAToc="; + url = "https://extdist.wmflabs.org/dist/extensions/CategoryLockdown-REL1_45-a715472.tar.gz"; + sha256 = "sha256-1gl5m9xkmLrdjoR0M13gcQHLtZt4Bt0PUXDiDEqjpvk="; }; #### Hinzufuegen der Erweiterung ConfirmEdit fuer eine zusaetzliche Bestaetigung bei Bearbeitungen, etwa um Herausforderungen (aka CAPTCHA) zu stellen @@ -168,8 +179,8 @@ #### Hinzufuegen der Erweiterung ContributionScores fuer eine Statistik von Beitraegen nach Beitragenden #### https://www.mediawiki.org/wiki/Extension:ContributionScores ContributionScores = pkgs.fetchzip { - url = "https://extdist.wmflabs.org/dist/extensions/ContributionScores-REL1_45-cd4c94b.tar.gz"; - sha256 = "sha256-8ClNtEQ66deKM1DsRYaaZ3KlRl4yCt6UhpXcozRQzQ8="; + url = "https://extdist.wmflabs.org/dist/extensions/ContributionCredits-REL1_45-22c28de.tar.gz"; + sha256 = "sha256-9T67jCEYQyU7P9sN7tYbnevU5+FX6Y1nydXGEdzQS9k="; }; #### Hinzufuegen der Erweiterung Interwiki fuer das Verwenden von Verweisen als eine Art Namensraum, wie beispielweise auf Wikipedia oder selbst festgelegte Verweise @@ -190,8 +201,8 @@ #### https://www.mediawiki.org/wiki/Extension:UserMerge UserMerge = pkgs.fetchzip { # url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_43-ed4a689.tar.gz"; - url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_45-446566b.tar.gz"; - sha256 = "sha256-DTDKlzet3lThh/sRLucyb8b9lhK5FYZ+dMgwrThFFBM="; + url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_45-437c211.tar.gz"; + sha256 = "sha256-DWdcvubqZkvtywuDEOjui68WYuETt5hGpJJlpZ+pJgE="; }; }; From 334c977988b70d573ae581b4d49c2895d7428135 Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 10:26:54 +0200 Subject: [PATCH 16/42] enable proxy protocol for redmine --- hosts/redmine/default.nix | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/hosts/redmine/default.nix b/hosts/redmine/default.nix index 6bc3d5e..3e3e183 100644 --- a/hosts/redmine/default.nix +++ b/hosts/redmine/default.nix @@ -137,10 +137,26 @@ services.nginx.appendHttpConfig = '' access_log off; ''; + services.nginx.commonHttpConfig = '' + real_ip_header proxy_protocol; + set_real_ip_from 141.56.51.1/32; + ''; #### Anscheinend kann mit nix nur die Konfiguration fuer eine konkrete (manuelle) Konfiguration fuer den Dienst web server. services.nginx.virtualHosts."${config.networking.fqdn}" = { #### https://search.nixos.org/options?show=services.nginx.virtualHosts..default + listen = [ + { + port = 80; + addr = "0.0.0.0"; + } + { + port = 443; + addr = "0.0.0.0"; + ssl = true; + proxyProtocol = true; + } + ]; default = true; locations."/" = { proxyPass = "http://127.0.0.1:${toString config.services.redmine.port}"; From 641feb1b847956faa4f012571cae53c055cbb612 Mon Sep 17 00:00:00 2001 From: goeranh Date: Fri, 20 Mar 2026 16:23:34 +0100 Subject: [PATCH 17/42] monitoring host# --- hosts/monitoring/default.nix | 205 +++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 hosts/monitoring/default.nix diff --git a/hosts/monitoring/default.nix b/hosts/monitoring/default.nix new file mode 100644 index 0000000..e92c246 --- /dev/null +++ b/hosts/monitoring/default.nix @@ -0,0 +1,205 @@ +{ + config, + lib, + pkgs, + modulesPath, + ... +}: +{ + imports = [ + "${modulesPath}/virtualisation/proxmox-lxc.nix" + ]; + + networking = { + hostName = "monitoring"; + fqdn = "monitoring.adm.htw.stura-dresden.de"; + interfaces.eth0.ipv4.addresses = [ + { + address = "141.56.51.20"; + prefixLength = 24; + } + ]; + defaultGateway = { + address = "141.56.51.254"; + interface = "eth0"; + }; + firewall = { + enable = true; + allowedTCPPorts = [ + 80 + 443 + ]; + }; + }; + + # Loki - Log aggregation system + services.loki = { + enable = true; + configuration = { + auth_enabled = false; + server = { + http_listen_port = 3100; + grpc_listen_port = 9096; + }; + common = { + path_prefix = "/var/lib/loki"; + storage.filesystem = { + chunks_directory = "/var/lib/loki/chunks"; + rules_directory = "/var/lib/loki/rules"; + }; + replication_factor = 1; + ring = { + instance_addr = "127.0.0.1"; + kvstore.store = "inmemory"; + }; + }; + schema_config = { + configs = [ + { + from = "2024-01-01"; + store = "tsdb"; + object_store = "filesystem"; + schema = "v13"; + index = { + prefix = "index_"; + period = "24h"; + }; + } + ]; + }; + }; + }; + + # Mimir - Scalable metrics storage + services.mimir = { + enable = true; + configuration = { + multitenancy_enabled = false; + blocks_storage = { + backend = "filesystem"; + filesystem = { + dir = "/var/lib/mimir/data"; + }; + }; + compactor = { + data_dir = "/var/lib/mimir/compactor"; + }; + distributor = { + ring = { + kvstore = { + store = "memberlist"; + }; + }; + }; + ingester = { + ring = { + kvstore = { + store = "memberlist"; + }; + replication_factor = 1; + }; + }; + ruler_storage = { + backend = "filesystem"; + filesystem = { + dir = "/var/lib/mimir/rules"; + }; + }; + server = { + http_listen_port = 9009; + grpc_listen_port = 9095; + }; + store_gateway = { + sharding_ring = { + replication_factor = 1; + }; + }; + }; + }; + + # Grafana - Visualization and dashboarding + services.grafana = { + enable = true; + settings = { + server = { + http_addr = "127.0.0.1"; + http_port = 3000; + domain = "monitoring.adm.htw.stura-dresden.de"; + root_url = "https://monitoring.adm.htw.stura-dresden.de"; + }; + security = { + admin_user = "admin"; + admin_password = "$__file{/var/lib/grafana/admin_password}"; + }; + }; + provision = { + enable = true; + datasources.settings.datasources = [ + { + name = "Mimir"; + type = "prometheus"; + url = "http://localhost:9009/prometheus"; + isDefault = true; + } + { + name = "Loki"; + type = "loki"; + url = "http://localhost:3100"; + } + ]; + }; + }; + + # Nginx reverse proxy with ACME certificates + services.nginx = { + enable = true; + + virtualHosts."logs.adm.htw.stura-dresden.de" = { + forceSSL = true; + enableACME = true; + locations."/" = { + proxyPass = "http://127.0.0.1:3100"; + proxyWebsockets = true; + extraConfig = '' + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + ''; + }; + }; + + virtualHosts."metrics.adm.htw.stura-dresden.de" = { + forceSSL = true; + enableACME = true; + locations."/" = { + proxyPass = "http://127.0.0.1:9009"; + extraConfig = '' + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + ''; + }; + }; + + virtualHosts."monitoring.adm.htw.stura-dresden.de" = { + forceSSL = true; + enableACME = true; + locations."/" = { + proxyPass = "http://127.0.0.1:3000"; + proxyWebsockets = true; + extraConfig = '' + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + ''; + }; + }; + }; + + services.openssh.enable = true; + + system.stateVersion = "25.11"; +} From 9beef4e01368ea73ff794a292df5c6efa959f1f9 Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 08:33:08 +0200 Subject: [PATCH 18/42] use recommended proxy settings --- hosts/monitoring/default.nix | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/hosts/monitoring/default.nix b/hosts/monitoring/default.nix index e92c246..2dbfbf1 100644 --- a/hosts/monitoring/default.nix +++ b/hosts/monitoring/default.nix @@ -160,12 +160,7 @@ locations."/" = { proxyPass = "http://127.0.0.1:3100"; proxyWebsockets = true; - extraConfig = '' - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - ''; + recommendedProxySettings = true; }; }; @@ -174,12 +169,7 @@ enableACME = true; locations."/" = { proxyPass = "http://127.0.0.1:9009"; - extraConfig = '' - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - ''; + recommendedProxySettings = true; }; }; @@ -189,12 +179,7 @@ locations."/" = { proxyPass = "http://127.0.0.1:3000"; proxyWebsockets = true; - extraConfig = '' - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - ''; + recommendedProxySettings = true; }; }; }; From d435d8d48780a84629f2babf016b283eac77392a Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 11:52:26 +0200 Subject: [PATCH 19/42] use three letter domains --- hosts/monitoring/default.nix | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hosts/monitoring/default.nix b/hosts/monitoring/default.nix index 2dbfbf1..a56cdb4 100644 --- a/hosts/monitoring/default.nix +++ b/hosts/monitoring/default.nix @@ -124,8 +124,8 @@ server = { http_addr = "127.0.0.1"; http_port = 3000; - domain = "monitoring.adm.htw.stura-dresden.de"; - root_url = "https://monitoring.adm.htw.stura-dresden.de"; + domain = "mon.adm.htw.stura-dresden.de"; + root_url = "https://mon.adm.htw.stura-dresden.de"; }; security = { admin_user = "admin"; @@ -154,7 +154,7 @@ services.nginx = { enable = true; - virtualHosts."logs.adm.htw.stura-dresden.de" = { + virtualHosts."log.adm.htw.stura-dresden.de" = { forceSSL = true; enableACME = true; locations."/" = { @@ -164,7 +164,7 @@ }; }; - virtualHosts."metrics.adm.htw.stura-dresden.de" = { + virtualHosts."met.adm.htw.stura-dresden.de" = { forceSSL = true; enableACME = true; locations."/" = { @@ -173,7 +173,7 @@ }; }; - virtualHosts."monitoring.adm.htw.stura-dresden.de" = { + virtualHosts."mon.adm.htw.stura-dresden.de" = { forceSSL = true; enableACME = true; locations."/" = { From 5ef710f8f270d70d388cbe38029ae5bb90919a27 Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 11:52:40 +0200 Subject: [PATCH 20/42] dont generate domains, doesnt work for mon.adm.htw for example --- hosts/proxy/default.nix | 74 ++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index a806790..9c09af9 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -295,43 +295,43 @@ "127.0.0.1" ]; listenOnIpv6 = [ ]; - zones = { - "htw.stura-dresden.de" = { - master = true; - file = pkgs.writeText "htw.stura-dresden.de.zone" '' - $TTL 3600 - @ IN SOA proxy.htw.stura-dresden.de. hostmaster.htw.stura-dresden.de. ( - 2026031301 ; Serial (YYYYMMDDNN) - 3600 ; Refresh (1 hour) - 1800 ; Retry (30 minutes) - 604800 ; Expire (1 week) - 86400 ) ; Minimum TTL (1 day) - - ; Name servers - @ IN NS proxy.htw.stura-dresden.de. - - ; Proxy host - main IPv4 gateway - proxy IN A 141.56.51.1 - proxy IN AAAA 2a01:4f8:1c19:96f8::1 - - ; Auto-generated CNAME records for all subdomains pointing to proxy - ${lib.foldlAttrs ( - prev: name: value: - let - zoneSuffix = ".htw.stura-dresden.de"; - # Check if this domain belongs to our zone - isInZone = lib.hasSuffix zoneSuffix value.domain; - # Extract subdomain by removing the zone suffix - subdomain = lib.removeSuffix zoneSuffix value.domain; - in - if isInZone && subdomain != "" && subdomain != "htw.stura-dresden.de" then - prev + "${subdomain}${" "}IN${" "}CNAME${" "}proxy.htw.stura-dresden.de.\n" - else - prev - ) "" forwards} - ''; - }; - }; + # zones = { + # "htw.stura-dresden.de" = { + # master = true; + # file = pkgs.writeText "htw.stura-dresden.de.zone" '' + # $TTL 3600 + # @ IN SOA proxy.htw.stura-dresden.de. hostmaster.htw.stura-dresden.de. ( + # 2026031301 ; Serial (YYYYMMDDNN) + # 3600 ; Refresh (1 hour) + # 1800 ; Retry (30 minutes) + # 604800 ; Expire (1 week) + # 86400 ) ; Minimum TTL (1 day) + # + # ; Name servers + # @ IN NS proxy.htw.stura-dresden.de. + # + # ; Proxy host - main IPv4 gateway + # proxy IN A 141.56.51.1 + # proxy IN AAAA 2a01:4f8:1c19:96f8::1 + # + # ; Auto-generated CNAME records for all subdomains pointing to proxy + # ${lib.foldlAttrs ( + # prev: name: value: + # let + # zoneSuffix = ".htw.stura-dresden.de"; + # # Check if this domain belongs to our zone + # isInZone = lib.hasSuffix zoneSuffix value.domain; + # # Extract subdomain by removing the zone suffix + # subdomain = lib.removeSuffix zoneSuffix value.domain; + # in + # if isInZone && subdomain != "" && subdomain != "htw.stura-dresden.de" then + # prev + "${subdomain}${" "}IN${" "}CNAME${" "}proxy.htw.stura-dresden.de.\n" + # else + # prev + # ) "" forwards} + # ''; + # }; + # }; }; # Chrony NTP server for the internal network From ef8607e38e0d203e791ac139f0224e424e499004 Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 11:52:57 +0200 Subject: [PATCH 21/42] include monitoring module per default --- flake.nix | 1 + modules/monitoring.nix | 96 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 modules/monitoring.nix diff --git a/flake.nix b/flake.nix index 2d1426d..f0f177e 100644 --- a/flake.nix +++ b/flake.nix @@ -193,6 +193,7 @@ [ ./hosts/${input} ./default.nix + ./modules/monitoring.nix disko.nixosModules.disko authentik.nixosModules.default mailserver.nixosModules.mailserver diff --git a/modules/monitoring.nix b/modules/monitoring.nix new file mode 100644 index 0000000..09a1bf7 --- /dev/null +++ b/modules/monitoring.nix @@ -0,0 +1,96 @@ +{ pkgs, lib, config, ... }: +let + cfg = config.stura.monitoring; +in { + options.stura.monitoring = { + extraLogFiles = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = []; + description = "Additional log file paths for vector to scrape and forward to Loki."; + example = [ "/var/log/nginx/access.log" "/var/log/nginx/error.log" ]; + }; + + extraGroups = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = []; + description = "Supplementary groups added to the vector systemd service to allow reading protected log files."; + example = [ "nginx" "postfix" ]; + }; + }; + + config = { + networking.hosts = { + "141.56.51.20" = [ + "mon.adm.htw.stura-dresden.de" + "log.adm.htw.stura-dresden.de" + "met.adm.htw.stura-dresden.de" + ]; + }; + services.vector = { + enable = true; + settings = { + sources = { + host_metrics = { + type = "host_metrics"; + collectors = [ "cpu" "disk" "filesystem" "load" "memory" "network" ]; + }; + + journald_logs = { + type = "journald"; + include_units = []; # empty = collect all units + }; + } // lib.optionalAttrs (cfg.extraLogFiles != [] || config.services.nginx.enable) { + extra_log_files = { + type = "file"; + include = lib.optional config.services.nginx.enable "/var/log/nginx/access.log" + ++ cfg.extraLogFiles; + }; + }; + + transforms = { + add_host_label_metrics = { + type = "remap"; + inputs = [ "host_metrics" ]; + source = '' + .tags.host = get_hostname!() + ''; + }; + + add_host_label_logs = { + type = "remap"; + inputs = [ "journald_logs" ] ++ lib.optional (cfg.extraLogFiles != [] || config.services.nginx.enable) "extra_log_files"; + source = '' + .host = get_hostname!() + ''; + }; + }; + + sinks = { + mimir = { + type = "prometheus_remote_write"; + inputs = [ "add_host_label_metrics" ]; + endpoint = "https://metrics.adm.htw.stura-dresden.de/api/v1/push"; + tls.verify_certificate = false; + }; + + loki = { + type = "loki"; + inputs = [ "add_host_label_logs" ]; + endpoint = "https://log.adm.htw.stura-dresden.de"; + labels = { + host = "{{ host }}"; + unit = "{{ _SYSTEMD_UNIT }}"; + }; + tls.verify_certificate = false; + encoding.codec = "json"; + }; + }; + }; + }; + + systemd.services.vector.serviceConfig.SupplementaryGroups = + [ "systemd-journal" ] + ++ lib.optional config.services.nginx.enable "nginx" + ++ cfg.extraGroups; + }; +} From e9fe620fa9ca3746c9de9aef51987fedac8e29d1 Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 12:01:36 +0200 Subject: [PATCH 22/42] increase mimir and loki rate limits --- hosts/monitoring/default.nix | 11 +++++++++++ modules/monitoring.nix | 1 + 2 files changed, 12 insertions(+) diff --git a/hosts/monitoring/default.nix b/hosts/monitoring/default.nix index a56cdb4..12f214c 100644 --- a/hosts/monitoring/default.nix +++ b/hosts/monitoring/default.nix @@ -53,6 +53,12 @@ kvstore.store = "inmemory"; }; }; + limits_config = { + ingestion_rate_mb = 32; + ingestion_burst_size_mb = 64; + per_stream_rate_limit = "32MB"; + per_stream_rate_limit_burst = "64MB"; + }; schema_config = { configs = [ { @@ -109,6 +115,11 @@ http_listen_port = 9009; grpc_listen_port = 9095; }; + limits = { + ingestion_rate = 100000; + ingestion_burst_size = 200000; + max_global_series_per_user = 0; + }; store_gateway = { sharding_ring = { replication_factor = 1; diff --git a/modules/monitoring.nix b/modules/monitoring.nix index 09a1bf7..33834ae 100644 --- a/modules/monitoring.nix +++ b/modules/monitoring.nix @@ -20,6 +20,7 @@ in { config = { networking.hosts = { + # rewrite these host entries on each system, this does not go through proxy "141.56.51.20" = [ "mon.adm.htw.stura-dresden.de" "log.adm.htw.stura-dresden.de" From e7cba90a4594bcf014652330b3ee6bc0ff992dfd Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 12:10:18 +0200 Subject: [PATCH 23/42] fix vector settings --- modules/monitoring.nix | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/monitoring.nix b/modules/monitoring.nix index 33834ae..86f7573 100644 --- a/modules/monitoring.nix +++ b/modules/monitoring.nix @@ -62,6 +62,7 @@ in { inputs = [ "journald_logs" ] ++ lib.optional (cfg.extraLogFiles != [] || config.services.nginx.enable) "extra_log_files"; source = '' .host = get_hostname!() + .unit = string(."_SYSTEMD_UNIT") ?? "file" ''; }; }; @@ -70,7 +71,7 @@ in { mimir = { type = "prometheus_remote_write"; inputs = [ "add_host_label_metrics" ]; - endpoint = "https://metrics.adm.htw.stura-dresden.de/api/v1/push"; + endpoint = "https://met.adm.htw.stura-dresden.de/api/v1/push"; tls.verify_certificate = false; }; @@ -80,7 +81,7 @@ in { endpoint = "https://log.adm.htw.stura-dresden.de"; labels = { host = "{{ host }}"; - unit = "{{ _SYSTEMD_UNIT }}"; + unit = "{{ unit }}"; }; tls.verify_certificate = false; encoding.codec = "json"; From fd02a136efb40ecba78ef564644f0c2345dc6d87 Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 13:06:04 +0200 Subject: [PATCH 24/42] scrape haproxy metrics --- hosts/proxy/default.nix | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index 9c09af9..83306c5 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -448,6 +448,7 @@ stats show-node stats show-modules stats admin if TRUE # Enable admin operations + http-request use-service prometheus-exporter if { path /metrics } frontend http-in bind *:80 @@ -547,8 +548,27 @@ ) "" forwards} ''; }; + vector.settings = { + sources.haproxy_metrics = { + type = "prometheus_scrape"; + endpoints = [ "http://127.0.0.1:8404/metrics" ]; + scrape_interval_secs = 15; + }; + transforms.add_host_label_haproxy = { + type = "remap"; + inputs = [ "haproxy_metrics" ]; + source = '' + .tags.host = get_hostname!() + ''; + }; + sinks.mimir.inputs = lib.mkForce [ + "add_host_label_metrics" + "add_host_label_haproxy" + ]; + }; }; + environment.systemPackages = with pkgs; [ ]; From dd2aa96e251a0fdd8ae0619938b2dd72ac8dd4ff Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 13:07:13 +0200 Subject: [PATCH 25/42] fix mimir --- hosts/monitoring/default.nix | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/hosts/monitoring/default.nix b/hosts/monitoring/default.nix index 12f214c..bf2b501 100644 --- a/hosts/monitoring/default.nix +++ b/hosts/monitoring/default.nix @@ -81,6 +81,12 @@ enable = true; configuration = { multitenancy_enabled = false; + memberlist = { + bind_addr = [ "0.0.0.0" ]; + bind_port = 7946; + advertise_addr = "141.56.51.20"; + join_members = [ "141.56.51.20:7946" ]; + }; blocks_storage = { backend = "filesystem"; filesystem = { @@ -92,16 +98,12 @@ }; distributor = { ring = { - kvstore = { - store = "memberlist"; - }; + kvstore.store = "memberlist"; }; }; ingester = { ring = { - kvstore = { - store = "memberlist"; - }; + kvstore.store = "memberlist"; replication_factor = 1; }; }; @@ -123,6 +125,7 @@ store_gateway = { sharding_ring = { replication_factor = 1; + kvstore.store = "memberlist"; }; }; }; From 93e27dd3e5da7a886114c7db60606e9ed98c481f Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 13:07:21 +0200 Subject: [PATCH 26/42] receive proxmox logs --- hosts/monitoring/default.nix | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/hosts/monitoring/default.nix b/hosts/monitoring/default.nix index bf2b501..2438b1f 100644 --- a/hosts/monitoring/default.nix +++ b/hosts/monitoring/default.nix @@ -28,6 +28,8 @@ allowedTCPPorts = [ 80 443 + 4317 # OTLP gRPC (Proxmox) + 4318 # OTLP HTTP (Proxmox) ]; }; }; @@ -198,6 +200,25 @@ }; }; + # Vector - receive OpenTelemetry data from Proxmox and forward to Loki/Mimir + services.vector.settings = { + sources.proxmox_otlp = { + type = "opentelemetry"; + grpc.address = "0.0.0.0:4317"; + http.address = "0.0.0.0:4318"; + }; + + sinks.mimir.inputs = lib.mkForce [ + "add_host_label_metrics" + "proxmox_otlp.metrics" + ]; + + sinks.loki.inputs = lib.mkForce [ + "add_host_label_logs" + "proxmox_otlp.logs" + ]; + }; + services.openssh.enable = true; system.stateVersion = "25.11"; From 53c592abd9e5e52f7d32a7ba3861ede6a4a7b35f Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 13:52:57 +0200 Subject: [PATCH 27/42] add extra inputs option for the loki and mimir sinks --- modules/monitoring.nix | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/modules/monitoring.nix b/modules/monitoring.nix index 86f7573..c46b660 100644 --- a/modules/monitoring.nix +++ b/modules/monitoring.nix @@ -16,6 +16,20 @@ in { description = "Supplementary groups added to the vector systemd service to allow reading protected log files."; example = [ "nginx" "postfix" ]; }; + + extraMetricInputs = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = []; + description = "Additional vector component IDs to feed into the mimir sink alongside host_metrics."; + example = [ "proxmox_normalize_metrics" ]; + }; + + extraLogInputs = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = []; + description = "Additional vector component IDs to feed into the loki sink alongside journald_logs."; + example = [ "proxmox_normalize_logs" ]; + }; }; config = { @@ -70,14 +84,15 @@ in { sinks = { mimir = { type = "prometheus_remote_write"; - inputs = [ "add_host_label_metrics" ]; + inputs = [ "add_host_label_metrics" ] ++ cfg.extraMetricInputs; endpoint = "https://met.adm.htw.stura-dresden.de/api/v1/push"; tls.verify_certificate = false; + healthcheck.enabled = false; }; loki = { type = "loki"; - inputs = [ "add_host_label_logs" ]; + inputs = [ "add_host_label_logs" ] ++ cfg.extraLogInputs; endpoint = "https://log.adm.htw.stura-dresden.de"; labels = { host = "{{ host }}"; From e1530c606f70b6946dfade296ff66d088b811d52 Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 13:53:12 +0200 Subject: [PATCH 28/42] use extra input sink options --- hosts/monitoring/default.nix | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/hosts/monitoring/default.nix b/hosts/monitoring/default.nix index 2438b1f..e0dbcaa 100644 --- a/hosts/monitoring/default.nix +++ b/hosts/monitoring/default.nix @@ -208,15 +208,28 @@ http.address = "0.0.0.0:4318"; }; - sinks.mimir.inputs = lib.mkForce [ - "add_host_label_metrics" - "proxmox_otlp.metrics" - ]; + transforms.proxmox_normalize_logs = { + type = "remap"; + inputs = [ "proxmox_otlp.logs" ]; + source = '' + .host = string(.resources."host.name") ?? "proxmox" + .unit = string(.attributes."service.name") ?? "proxmox" + ''; + }; - sinks.loki.inputs = lib.mkForce [ - "add_host_label_logs" - "proxmox_otlp.logs" - ]; + transforms.proxmox_normalize_metrics = { + type = "remap"; + inputs = [ "proxmox_otlp.metrics" ]; + source = '' + .tags.host = string(.resources."host.name") ?? "proxmox" + ''; + }; + + }; + + stura.monitoring = { + extraMetricInputs = [ "proxmox_normalize_metrics" ]; + extraLogInputs = [ "proxmox_normalize_logs" ]; }; services.openssh.enable = true; From 9a5716f2df8fcaf4ab184cca21c4ab5692f61b8d Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 14:10:33 +0200 Subject: [PATCH 29/42] increase max series for queries --- hosts/monitoring/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/hosts/monitoring/default.nix b/hosts/monitoring/default.nix index e0dbcaa..f3c6829 100644 --- a/hosts/monitoring/default.nix +++ b/hosts/monitoring/default.nix @@ -60,6 +60,7 @@ ingestion_burst_size_mb = 64; per_stream_rate_limit = "32MB"; per_stream_rate_limit_burst = "64MB"; + max_query_series = 100000; }; schema_config = { configs = [ From c31063ca5632a0f3185fdbcbf185dacd49fd33c0 Mon Sep 17 00:00:00 2001 From: goeranh Date: Mon, 20 Apr 2026 14:28:13 +0200 Subject: [PATCH 30/42] purge logs and metrics after 4 weeks --- hosts/monitoring/default.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hosts/monitoring/default.nix b/hosts/monitoring/default.nix index f3c6829..e30daba 100644 --- a/hosts/monitoring/default.nix +++ b/hosts/monitoring/default.nix @@ -61,6 +61,12 @@ per_stream_rate_limit = "32MB"; per_stream_rate_limit_burst = "64MB"; max_query_series = 100000; + retention_period = "672h"; # 28 days + }; + compactor = { + retention_enabled = true; + working_directory = "/var/lib/loki/compactor"; + delete_request_store = "filesystem"; }; schema_config = { configs = [ @@ -124,6 +130,7 @@ ingestion_rate = 100000; ingestion_burst_size = 200000; max_global_series_per_user = 0; + compactor_blocks_retention_period = "672h"; # 28 days }; store_gateway = { sharding_ring = { From 6ea03616924ad33265ecfba30baed55d00443f5d Mon Sep 17 00:00:00 2001 From: goeranh Date: Tue, 21 Apr 2026 09:06:13 +0200 Subject: [PATCH 31/42] send proxy protocol from hetzner --- hosts/v6proxy/default.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hosts/v6proxy/default.nix b/hosts/v6proxy/default.nix index 6dd17b3..270ef2c 100644 --- a/hosts/v6proxy/default.nix +++ b/hosts/v6proxy/default.nix @@ -39,6 +39,7 @@ "1.1.1.1" ]; firewall = { + enable = true; allowedTCPPorts = [ 22 80 @@ -96,7 +97,7 @@ server proxy 141.56.51.1:80 backend http_443 mode tcp - server proxy 141.56.51.1:443 + server proxy 141.56.51.1:443 send-proxy-v2 ''; }; }; From 1ba340e2a41433588ca803dc20e070c09f411da7 Mon Sep 17 00:00:00 2001 From: goeranh Date: Tue, 21 Apr 2026 11:34:10 +0200 Subject: [PATCH 32/42] process metrics --- modules/monitoring.nix | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/modules/monitoring.nix b/modules/monitoring.nix index c46b660..30cba16 100644 --- a/modules/monitoring.nix +++ b/modules/monitoring.nix @@ -47,7 +47,16 @@ in { sources = { host_metrics = { type = "host_metrics"; - collectors = [ "cpu" "disk" "filesystem" "load" "memory" "network" ]; + collectors = [ + "cpu" + "disk" + "filesystem" + "load" + "host" + "memory" + "network" + "process" + ]; }; journald_logs = { @@ -68,6 +77,7 @@ in { inputs = [ "host_metrics" ]; source = '' .tags.host = get_hostname!() + del(.tags.command) ''; }; From c89b6e7ee9daf7843ad0570ae5046998ca599a54 Mon Sep 17 00:00:00 2001 From: goeranh Date: Tue, 21 Apr 2026 11:34:31 +0200 Subject: [PATCH 33/42] accept accept v6proxy proxy protocol --- hosts/proxy/default.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index 83306c5..90ee580 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -452,6 +452,7 @@ frontend http-in bind *:80 + tcp-request connection expect-proxy layer4 if { src 178.104.18.93 } maxconn 60000 backlog 8192 option dontlognull @@ -496,6 +497,7 @@ frontend sni_router bind *:443 mode tcp + tcp-request connection expect-proxy layer4 if { src 178.104.18.93 } # Reduce inspection delay - SNI is in first packet (Phase 3) tcp-request inspect-delay 500ms # Was 1s From c0c528ae293b64cff6680a8c9893099e4898b9ec Mon Sep 17 00:00:00 2001 From: goeranh Date: Tue, 21 Apr 2026 11:35:06 +0200 Subject: [PATCH 34/42] geoip haproxy --- hosts/proxy/default.nix | 51 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index 90ee580..44f37d5 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -551,17 +551,54 @@ ''; }; vector.settings = { + enrichment_tables.geoip_table = { + type = "mmdb"; + path = "/var/lib/GeoIP/GeoLite2-City.mmdb"; + }; sources.haproxy_metrics = { type = "prometheus_scrape"; endpoints = [ "http://127.0.0.1:8404/metrics" ]; scrape_interval_secs = 15; }; - transforms.add_host_label_haproxy = { - type = "remap"; - inputs = [ "haproxy_metrics" ]; - source = '' - .tags.host = get_hostname!() - ''; + transforms = { + add_host_label_haproxy = { + type = "remap"; + inputs = [ "haproxy_metrics" ]; + source = '' + .tags.host = get_hostname!() + ''; + }; + haproxy_logs_filter = { + type = "filter"; + inputs = [ "journald_logs" ]; + condition = ''."_SYSTEMD_UNIT" == "haproxy.service"''; + }; + haproxy_logs_parse = { + type = "remap"; + inputs = [ "haproxy_logs_filter" ]; + source = '' + .host = get_hostname!() + .unit = "haproxy" + # IPv4: "1.2.3.4:port" IPv6: "[2001:db8::1]:port" + parsed, err = parse_regex(.message, r'^(?:\[(?P[0-9a-fA-F:]+)\]|(?P[\d.]+)):\d+') + if err == null { + if is_null(parsed.ipv6) { + .client_ip = parsed.ipv4 + } else { + .client_ip = parsed.ipv6 + } + } + ''; + }; + haproxy_geoip = { + type = "remap"; + inputs = [ "haproxy_logs_parse" ]; + source = '' + if exists(.client_ip) && !is_null(.client_ip) { + .geoip = get_enrichment_table_record("geoip_table", {"ip": string!(.client_ip)}) ?? {} + } + ''; + }; }; sinks.mimir.inputs = lib.mkForce [ "add_host_label_metrics" @@ -571,6 +608,8 @@ }; + stura.monitoring.extraLogInputs = [ "haproxy_geoip" ]; + environment.systemPackages = with pkgs; [ ]; From ed10898adbf815662f600174f1cbe1fb42d5ed26 Mon Sep 17 00:00:00 2001 From: goeranh Date: Fri, 24 Apr 2026 14:42:39 +0200 Subject: [PATCH 35/42] flake.lock: Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'authentik': 'github:nix-community/authentik-nix/7e4730351fb6df479c46a1bf7e23d46a0b0c5d46?narHash=sha256-hcstQ1Z9aQSJM3AVCLb0/OPTicbME9nhP01GiPrOjZM%3D' (2026-03-07) → 'github:nix-community/authentik-nix/4370b561c8bafb59773ce3a518506bcf1161dbdb?narHash=sha256-JvvWVbXJYSY8qOReMbAOD4lxcN2cjKV6lg/jLz8CEuY%3D' (2026-04-13) • Updated input 'authentik/authentik-src': 'github:goauthentik/authentik/0dccbd4193c45c581e9fb7cd89df0c1487510f1f?narHash=sha256-0Vpf1hj9C8r%2BrhrCgwoNazpQ%2BmwgjdjDhuoKCxYQFWw%3D' (2026-03-03) → 'github:goauthentik/authentik/5249546862986202b901c2afd860992ec48c6ef6?narHash=sha256-Xq7JGI/8ppIydIuWd9KRJKUrh7UpeniwvZ4NAtXbYJ4%3D' (2026-04-07) • Updated input 'disko': 'github:nix-community/disko/7b9f7f88ab3b339f8142dc246445abb3c370d3d3?narHash=sha256-khlHllTsovXgT2GZ0WxT4%2BRvuMjNeR5OW0UYeEHPYQo%3D' (2026-03-09) → 'github:nix-community/disko/32f4236bfc141ae930b5ba2fb604f561fed5219d?narHash=sha256-gC9Cp5ibBmGD5awCA9z7xy6MW6iJufhazTYJOiGlCUI%3D' (2026-04-19) • Updated input 'mailserver': 'git+https://gitlab.com/simple-nixos-mailserver/nixos-mailserver?ref=nixos-25.11&rev=9cdd6869e513df8153db4b920c8f15d394e150f7' (2026-03-12) → 'git+https://gitlab.com/simple-nixos-mailserver/nixos-mailserver?ref=nixos-25.11&rev=25e6dbb8fca3b6e779c5a46fd03bd760b2165bb5' (2026-03-19) • Updated input 'mailserver/flake-compat': 'github:edolstra/flake-compat/f387cd2afec9419c8ee37694406ca490c3f34ee5?narHash=sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4%3D' (2025-10-27) → 'github:edolstra/flake-compat/5edf11c44bc78a0d334f6334cdaf7d60d732daab?narHash=sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns%3D' (2025-12-29) • Updated input 'mailserver/git-hooks': 'github:cachix/git-hooks.nix/7275fa67fbbb75891c16d9dee7d88e58aea2d761?narHash=sha256-YG19IyrTdnVn0l3DvcUYm85u3PaqBt6tI6VvolcuHnA%3D' (2025-11-16) → 'github:cachix/git-hooks.nix/8baab586afc9c9b57645a734c820e4ac0a604af9?narHash=sha256-JDqZMgxUTCq85ObSaFw0HhE%2BlvdOre1lx9iI6vYyOEs%3D' (2026-03-07) • Updated input 'mailserver/nixpkgs': 'github:NixOS/nixpkgs/a320ce8e6e2cc6b4397eef214d202a50a4583829?narHash=sha256-6zddwDs2n%2Bn01l%2B1TG6PlyokDdXzu/oBmEejcH5L5%2BA%3D' (2025-11-24) → 'github:NixOS/nixpkgs/826430a188181a750ffa5948daff334039c5d741?narHash=sha256-JW2/QPyCVzmouqEp1H9kNa8JXd7xEhlam9sy3TYfhDY%3D' (2026-03-18) • Updated input 'nixpkgs': 'github:nixos/nixpkgs/0590cd39f728e129122770c029970378a79d076a?narHash=sha256-BHoB/XpbqoZkVYZCfXJXfkR%2BGXFqwb/4zbWnOr2cRcU%3D' (2026-03-11) → 'github:nixos/nixpkgs/10e7ad5bbcb421fe07e3a4ad53a634b0cd57ffac?narHash=sha256-vl3dkhlE5gzsItuHoEMVe%2BDlonsK%2B0836LIRDnm6MXQ%3D' (2026-04-21) • Updated input 'sops': 'github:Mic92/sops-nix/d1ff3b1034d5bab5d7d8086a7803c5a5968cd784?narHash=sha256-M3zEnq9OElB7zqc%2BmjgPlByPm1O5t2fbUrH3t/Hm5Ag%3D' (2026-03-09) → 'github:Mic92/sops-nix/bef289e2248991f7afeb95965c82fbcd8ff72598?narHash=sha256-DRFGPfFV6hbrfO9a1PH1FkCi7qR5FgjSqsQGGvk1rdI%3D' (2026-04-21) --- flake.lock | 58 +++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/flake.lock b/flake.lock index 9ed7807..4e0f8b8 100644 --- a/flake.lock +++ b/flake.lock @@ -15,11 +15,11 @@ "uv2nix": "uv2nix" }, "locked": { - "lastModified": 1772909021, - "narHash": "sha256-hcstQ1Z9aQSJM3AVCLb0/OPTicbME9nhP01GiPrOjZM=", + "lastModified": 1776085803, + "narHash": "sha256-JvvWVbXJYSY8qOReMbAOD4lxcN2cjKV6lg/jLz8CEuY=", "owner": "nix-community", "repo": "authentik-nix", - "rev": "7e4730351fb6df479c46a1bf7e23d46a0b0c5d46", + "rev": "4370b561c8bafb59773ce3a518506bcf1161dbdb", "type": "github" }, "original": { @@ -47,16 +47,16 @@ "authentik-src": { "flake": false, "locked": { - "lastModified": 1772567399, - "narHash": "sha256-0Vpf1hj9C8r+rhrCgwoNazpQ+mwgjdjDhuoKCxYQFWw=", + "lastModified": 1775573258, + "narHash": "sha256-Xq7JGI/8ppIydIuWd9KRJKUrh7UpeniwvZ4NAtXbYJ4=", "owner": "goauthentik", "repo": "authentik", - "rev": "0dccbd4193c45c581e9fb7cd89df0c1487510f1f", + "rev": "5249546862986202b901c2afd860992ec48c6ef6", "type": "github" }, "original": { "owner": "goauthentik", - "ref": "version/2026.2.1", + "ref": "version/2026.2.2", "repo": "authentik", "type": "github" } @@ -84,11 +84,11 @@ ] }, "locked": { - "lastModified": 1773025010, - "narHash": "sha256-khlHllTsovXgT2GZ0WxT4+RvuMjNeR5OW0UYeEHPYQo=", + "lastModified": 1776613567, + "narHash": "sha256-gC9Cp5ibBmGD5awCA9z7xy6MW6iJufhazTYJOiGlCUI=", "owner": "nix-community", "repo": "disko", - "rev": "7b9f7f88ab3b339f8142dc246445abb3c370d3d3", + "rev": "32f4236bfc141ae930b5ba2fb604f561fed5219d", "type": "github" }, "original": { @@ -116,11 +116,11 @@ "flake-compat_2": { "flake": false, "locked": { - "lastModified": 1761588595, - "narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=", + "lastModified": 1767039857, + "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", "owner": "edolstra", "repo": "flake-compat", - "rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5", + "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", "type": "github" }, "original": { @@ -181,11 +181,11 @@ ] }, "locked": { - "lastModified": 1763319842, - "narHash": "sha256-YG19IyrTdnVn0l3DvcUYm85u3PaqBt6tI6VvolcuHnA=", + "lastModified": 1772893680, + "narHash": "sha256-JDqZMgxUTCq85ObSaFw0HhE+lvdOre1lx9iI6vYyOEs=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "7275fa67fbbb75891c16d9dee7d88e58aea2d761", + "rev": "8baab586afc9c9b57645a734c820e4ac0a604af9", "type": "github" }, "original": { @@ -224,11 +224,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1773313890, - "narHash": "sha256-NXm/kOAk7HLziH1uWaUbNb9MhDS8yxFfQ8fMK5eN8/A=", + "lastModified": 1773912645, + "narHash": "sha256-QHzRqq6gh+t3F/QU9DkP7X63dDDcuIQmaDz12p7ANTg=", "ref": "nixos-25.11", - "rev": "9cdd6869e513df8153db4b920c8f15d394e150f7", - "revCount": 842, + "rev": "25e6dbb8fca3b6e779c5a46fd03bd760b2165bb5", + "revCount": 843, "type": "git", "url": "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver" }, @@ -297,11 +297,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1764020296, - "narHash": "sha256-6zddwDs2n+n01l+1TG6PlyokDdXzu/oBmEejcH5L5+A=", + "lastModified": 1773831496, + "narHash": "sha256-JW2/QPyCVzmouqEp1H9kNa8JXd7xEhlam9sy3TYfhDY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a320ce8e6e2cc6b4397eef214d202a50a4583829", + "rev": "826430a188181a750ffa5948daff334039c5d741", "type": "github" }, "original": { @@ -313,11 +313,11 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1773222311, - "narHash": "sha256-BHoB/XpbqoZkVYZCfXJXfkR+GXFqwb/4zbWnOr2cRcU=", + "lastModified": 1776734388, + "narHash": "sha256-vl3dkhlE5gzsItuHoEMVe+DlonsK+0836LIRDnm6MXQ=", "owner": "nixos", "repo": "nixpkgs", - "rev": "0590cd39f728e129122770c029970378a79d076a", + "rev": "10e7ad5bbcb421fe07e3a4ad53a634b0cd57ffac", "type": "github" }, "original": { @@ -393,11 +393,11 @@ ] }, "locked": { - "lastModified": 1773096132, - "narHash": "sha256-M3zEnq9OElB7zqc+mjgPlByPm1O5t2fbUrH3t/Hm5Ag=", + "lastModified": 1776771786, + "narHash": "sha256-DRFGPfFV6hbrfO9a1PH1FkCi7qR5FgjSqsQGGvk1rdI=", "owner": "Mic92", "repo": "sops-nix", - "rev": "d1ff3b1034d5bab5d7d8086a7803c5a5968cd784", + "rev": "bef289e2248991f7afeb95965c82fbcd8ff72598", "type": "github" }, "original": { From 590f42d5d96e838b008423937cb09c80bf30318c Mon Sep 17 00:00:00 2001 From: goeranh Date: Wed, 29 Apr 2026 18:42:20 +0200 Subject: [PATCH 36/42] enable proxy protocol for plone backends --- hosts/proxy/default.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index 44f37d5..40740fb 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -105,28 +105,28 @@ domain = "stura.htw-dresden.de"; httpPort = 80; httpsPort = 443; - sendProxy = false; + sendProxy = true; }; plone_alt = { dest = "141.56.51.3"; domain = "www.stura.htw-dresden.de"; httpPort = 80; httpsPort = 443; - sendProxy = false; + sendProxy = true; }; plone_neu = { dest = "141.56.51.3"; domain = "www.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; - sendProxy = false; + sendProxy = true; }; plone_neu2 = { dest = "141.56.51.3"; domain = "htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; - sendProxy = false; + sendProxy = true; }; tix = { dest = "141.56.51.220"; From b2ac4a6ac167b3771a9826696a7a962cb105105c Mon Sep 17 00:00:00 2001 From: goeranh Date: Thu, 30 Apr 2026 17:50:22 +0200 Subject: [PATCH 37/42] haproxy acme rule ordering --- hosts/proxy/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index 40740fb..a6108bb 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -475,8 +475,8 @@ prev: name: value: prev + '' - use_backend ${name}_80 if is_${name} http-request redirect scheme https code 301 if !is_acme is_${name} + use_backend ${name}_80 if is_${name} '' ) "" forwards} From 1e5cd756528f79676a85c5de0ef10146b2935748 Mon Sep 17 00:00:00 2001 From: goeranh Date: Thu, 30 Apr 2026 17:59:32 +0200 Subject: [PATCH 38/42] set http mode for port 80 --- hosts/proxy/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index a6108bb..8bba097 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -452,6 +452,7 @@ frontend http-in bind *:80 + mode http tcp-request connection expect-proxy layer4 if { src 178.104.18.93 } maxconn 60000 backlog 8192 From 855cd7bd9bb200b09036d2d3da3eb339a856b35d Mon Sep 17 00:00:00 2001 From: goeranh Date: Fri, 1 May 2026 23:16:24 +0200 Subject: [PATCH 39/42] fix build failure because of new upstream release --- hosts/wiki/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hosts/wiki/default.nix b/hosts/wiki/default.nix index c73a5cb..179780d 100644 --- a/hosts/wiki/default.nix +++ b/hosts/wiki/default.nix @@ -201,8 +201,8 @@ #### https://www.mediawiki.org/wiki/Extension:UserMerge UserMerge = pkgs.fetchzip { # url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_43-ed4a689.tar.gz"; - url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_45-437c211.tar.gz"; - sha256 = "sha256-DWdcvubqZkvtywuDEOjui68WYuETt5hGpJJlpZ+pJgE="; + url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_45-433f6c2.tar.gz"; + sha256 = "sha256-JyY4pJNBKQ9bOKrilPWCheZ5ihWwPM6ZJ0qHsZ3coPk="; }; }; From d0a8fb0c091f59d1139accb72d7857a06df6e0d1 Mon Sep 17 00:00:00 2001 From: goeranh Date: Fri, 1 May 2026 23:54:32 +0200 Subject: [PATCH 40/42] enable nginx access logs for now --- hosts/redmine/default.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hosts/redmine/default.nix b/hosts/redmine/default.nix index 3e3e183..2bbd398 100644 --- a/hosts/redmine/default.nix +++ b/hosts/redmine/default.nix @@ -134,9 +134,9 @@ #### Der StuRa speichert nicht! services.nginx.logError = ''/dev/null emerg''; - services.nginx.appendHttpConfig = '' - access_log off; - ''; + # services.nginx.appendHttpConfig = '' + # access_log off; + # ''; services.nginx.commonHttpConfig = '' real_ip_header proxy_protocol; set_real_ip_from 141.56.51.1/32; From 66d68577101ed1deae245de93775f5b03440ebb0 Mon Sep 17 00:00:00 2001 From: goeranh Date: Sat, 2 May 2026 00:29:06 +0200 Subject: [PATCH 41/42] use nftables on all haproxy host for better blacklisting --- hosts/proxy/default.nix | 96 +++++++++++++++++++++++++++++++++------ hosts/v6proxy/default.nix | 84 ++++++++++++++++++++++++++++++---- 2 files changed, 157 insertions(+), 23 deletions(-) diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index 8bba097..7fa2238 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -20,22 +20,49 @@ } ]; defaultGateway.address = "141.56.51.254"; - firewall = { - allowedTCPPorts = [ - 22 - 53 # DNS - 80 - 443 - 1005 - 2142 - ]; - allowedUDPPorts = [ - 53 # DNS - 123 # NTP - ]; - }; + firewall.enable = false; nftables = { enable = true; + ruleset = '' + table inet filter { + set blacklist4 { + type ipv4_addr + flags interval + # manage: nft add element inet filter blacklist4 { 1.2.3.0/24 } + } + + set blacklist6 { + type ipv6_addr + flags interval + # manage: nft add element inet filter blacklist6 { 2001:db8::/32 } + } + + chain input { + type filter hook input priority filter; policy drop; + + iif "lo" accept + ct state established,related accept + + ip saddr @blacklist4 drop + ip6 saddr @blacklist6 drop + + # public ports + tcp dport { 80, 443, 1005, 2142 } accept + + # lan-only: dns and ntp + ip saddr 141.56.51.0/24 tcp dport 53 accept + ip saddr 141.56.51.0/24 udp dport { 53, 123 } accept + } + + chain forward { + type filter hook forward priority filter; policy drop; + } + + chain output { + type filter hook output priority filter; policy accept; + } + } + ''; }; }; @@ -611,6 +638,47 @@ stura.monitoring.extraLogInputs = [ "haproxy_geoip" ]; + users.users.root.packages = [ + (pkgs.writeShellScriptBin "nft-blacklist" '' + set -euo pipefail + + usage() { + echo "Usage: nft-blacklist " + echo " add - add entry to blacklist set" + echo " del - remove entry from blacklist set" + exit 1 + } + + [[ $# -ne 2 ]] && usage + + ACTION="$1" + ADDR="$2" + + if [[ "$ADDR" == *:* ]]; then + SET="blacklist6" + elif [[ "$ADDR" == *.* ]]; then + SET="blacklist4" + else + echo "Error: cannot determine address family for '$ADDR'" >&2 + exit 1 + fi + + case "$ACTION" in + add) + ${pkgs.nftables}/bin/nft add element inet filter "$SET" "{ $ADDR }" + echo "Added $ADDR to $SET" + ;; + del) + ${pkgs.nftables}/bin/nft delete element inet filter "$SET" "{ $ADDR }" + echo "Removed $ADDR from $SET" + ;; + *) + usage + ;; + esac + '') + ]; + environment.systemPackages = with pkgs; [ ]; diff --git a/hosts/v6proxy/default.nix b/hosts/v6proxy/default.nix index 270ef2c..39e2521 100644 --- a/hosts/v6proxy/default.nix +++ b/hosts/v6proxy/default.nix @@ -38,16 +38,44 @@ "9.9.9.9" "1.1.1.1" ]; - firewall = { - enable = true; - allowedTCPPorts = [ - 22 - 80 - 443 - ]; - }; + firewall.enable = false; nftables = { enable = true; + ruleset = '' + table inet filter { + set blacklist4 { + type ipv4_addr + flags interval + # manage at runtime: nft add element inet filter blacklist4 { 1.2.3.0/24 } + } + + set blacklist6 { + type ipv6_addr + flags interval + # manage at runtime: nft add element inet filter blacklist6 { 2001:db8::/32 } + } + + chain input { + type filter hook input priority filter; policy drop; + + iif "lo" accept + ct state established,related accept + + ip saddr @blacklist4 drop + ip6 saddr @blacklist6 drop + + tcp dport { 22, 80, 443 } accept + } + + chain forward { + type filter hook forward priority filter; policy drop; + } + + chain output { + type filter hook output priority filter; policy accept; + } + } + ''; }; }; @@ -102,7 +130,45 @@ }; }; - environment.systemPackages = with pkgs; [ + users.users.root.packages = [ + (pkgs.writeShellScriptBin "nft-blacklist" '' + set -euo pipefail + + usage() { + echo "Usage: nft-blacklist " + echo " add - add entry to blacklist set" + echo " del - remove entry from blacklist set" + exit 1 + } + + [[ $# -ne 2 ]] && usage + + ACTION="$1" + ADDR="$2" + + if [[ "$ADDR" == *:* ]]; then + SET="blacklist6" + elif [[ "$ADDR" == *.* ]]; then + SET="blacklist4" + else + echo "Error: cannot determine address family for '$ADDR'" >&2 + exit 1 + fi + + case "$ACTION" in + add) + ${pkgs.nftables}/bin/nft add element inet filter "$SET" "{ $ADDR }" + echo "Added $ADDR to $SET" + ;; + del) + ${pkgs.nftables}/bin/nft delete element inet filter "$SET" "{ $ADDR }" + echo "Removed $ADDR from $SET" + ;; + *) + usage + ;; + esac + '') ]; system.stateVersion = "25.11"; From 03795a46a76499a5ab512cd749c8128a27756d06 Mon Sep 17 00:00:00 2001 From: goeranh Date: Sun, 3 May 2026 14:19:43 +0200 Subject: [PATCH 42/42] allow all local connections --- hosts/proxy/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index 7fa2238..e688417 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -43,6 +43,7 @@ iif "lo" accept ct state established,related accept + ip saddr 141.56.51.0/24 accept ip saddr @blacklist4 drop ip6 saddr @blacklist6 drop