diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 120000 index 0000000..ca60d86 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1 @@ +/nix/store/1w2s62i701n28sj08gn1445qr4v3vijp-pre-commit-config.json \ No newline at end of file diff --git a/flake.lock b/flake.lock index 4e0f8b8..c4d6b5e 100644 --- a/flake.lock +++ b/flake.lock @@ -15,11 +15,11 @@ "uv2nix": "uv2nix" }, "locked": { - "lastModified": 1776085803, - "narHash": "sha256-JvvWVbXJYSY8qOReMbAOD4lxcN2cjKV6lg/jLz8CEuY=", + "lastModified": 1772909021, + "narHash": "sha256-hcstQ1Z9aQSJM3AVCLb0/OPTicbME9nhP01GiPrOjZM=", "owner": "nix-community", "repo": "authentik-nix", - "rev": "4370b561c8bafb59773ce3a518506bcf1161dbdb", + "rev": "7e4730351fb6df479c46a1bf7e23d46a0b0c5d46", "type": "github" }, "original": { @@ -47,16 +47,16 @@ "authentik-src": { "flake": false, "locked": { - "lastModified": 1775573258, - "narHash": "sha256-Xq7JGI/8ppIydIuWd9KRJKUrh7UpeniwvZ4NAtXbYJ4=", + "lastModified": 1772567399, + "narHash": "sha256-0Vpf1hj9C8r+rhrCgwoNazpQ+mwgjdjDhuoKCxYQFWw=", "owner": "goauthentik", "repo": "authentik", - "rev": "5249546862986202b901c2afd860992ec48c6ef6", + "rev": "0dccbd4193c45c581e9fb7cd89df0c1487510f1f", "type": "github" }, "original": { "owner": "goauthentik", - "ref": "version/2026.2.2", + "ref": "version/2026.2.1", "repo": "authentik", "type": "github" } @@ -84,11 +84,11 @@ ] }, "locked": { - "lastModified": 1776613567, - "narHash": "sha256-gC9Cp5ibBmGD5awCA9z7xy6MW6iJufhazTYJOiGlCUI=", + "lastModified": 1773025010, + "narHash": "sha256-khlHllTsovXgT2GZ0WxT4+RvuMjNeR5OW0UYeEHPYQo=", "owner": "nix-community", "repo": "disko", - "rev": "32f4236bfc141ae930b5ba2fb604f561fed5219d", + "rev": "7b9f7f88ab3b339f8142dc246445abb3c370d3d3", "type": "github" }, "original": { @@ -118,11 +118,27 @@ "locked": { "lastModified": 1767039857, "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", - "owner": "edolstra", + "owner": "NixOS", "repo": "flake-compat", "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", "type": "github" }, + "original": { + "owner": "NixOS", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_3": { + "flake": false, + "locked": { + "lastModified": 1761588595, + "narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5", + "type": "github" + }, "original": { "owner": "edolstra", "repo": "flake-compat", @@ -170,13 +186,9 @@ }, "git-hooks": { "inputs": { - "flake-compat": [ - "mailserver", - "flake-compat" - ], + "flake-compat": "flake-compat_2", "gitignore": "gitignore", "nixpkgs": [ - "mailserver", "nixpkgs" ] }, @@ -194,7 +206,54 @@ "type": "github" } }, + "git-hooks_2": { + "inputs": { + "flake-compat": [ + "mailserver", + "flake-compat" + ], + "gitignore": "gitignore_2", + "nixpkgs": [ + "mailserver", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1763319842, + "narHash": "sha256-YG19IyrTdnVn0l3DvcUYm85u3PaqBt6tI6VvolcuHnA=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "7275fa67fbbb75891c16d9dee7d88e58aea2d761", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, "gitignore": { + "inputs": { + "nixpkgs": [ + "git-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_2": { "inputs": { "nixpkgs": [ "mailserver", @@ -219,16 +278,16 @@ "mailserver": { "inputs": { "blobs": "blobs", - "flake-compat": "flake-compat_2", - "git-hooks": "git-hooks", + "flake-compat": "flake-compat_3", + "git-hooks": "git-hooks_2", "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1773912645, - "narHash": "sha256-QHzRqq6gh+t3F/QU9DkP7X63dDDcuIQmaDz12p7ANTg=", + "lastModified": 1773313890, + "narHash": "sha256-NXm/kOAk7HLziH1uWaUbNb9MhDS8yxFfQ8fMK5eN8/A=", "ref": "nixos-25.11", - "rev": "25e6dbb8fca3b6e779c5a46fd03bd760b2165bb5", - "revCount": 843, + "rev": "9cdd6869e513df8153db4b920c8f15d394e150f7", + "revCount": 842, "type": "git", "url": "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver" }, @@ -297,11 +356,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1773831496, - "narHash": "sha256-JW2/QPyCVzmouqEp1H9kNa8JXd7xEhlam9sy3TYfhDY=", + "lastModified": 1764020296, + "narHash": "sha256-6zddwDs2n+n01l+1TG6PlyokDdXzu/oBmEejcH5L5+A=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "826430a188181a750ffa5948daff334039c5d741", + "rev": "a320ce8e6e2cc6b4397eef214d202a50a4583829", "type": "github" }, "original": { @@ -313,11 +372,11 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1776734388, - "narHash": "sha256-vl3dkhlE5gzsItuHoEMVe+DlonsK+0836LIRDnm6MXQ=", + "lastModified": 1773222311, + "narHash": "sha256-BHoB/XpbqoZkVYZCfXJXfkR+GXFqwb/4zbWnOr2cRcU=", "owner": "nixos", "repo": "nixpkgs", - "rev": "10e7ad5bbcb421fe07e3a4ad53a634b0cd57ffac", + "rev": "0590cd39f728e129122770c029970378a79d076a", "type": "github" }, "original": { @@ -381,6 +440,7 @@ "inputs": { "authentik": "authentik", "disko": "disko", + "git-hooks": "git-hooks", "mailserver": "mailserver", "nixpkgs": "nixpkgs_3", "sops": "sops" @@ -393,11 +453,11 @@ ] }, "locked": { - "lastModified": 1776771786, - "narHash": "sha256-DRFGPfFV6hbrfO9a1PH1FkCi7qR5FgjSqsQGGvk1rdI=", + "lastModified": 1773096132, + "narHash": "sha256-M3zEnq9OElB7zqc+mjgPlByPm1O5t2fbUrH3t/Hm5Ag=", "owner": "Mic92", "repo": "sops-nix", - "rev": "bef289e2248991f7afeb95965c82fbcd8ff72598", + "rev": "d1ff3b1034d5bab5d7d8086a7803c5a5968cd784", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index f0f177e..c4a2649 100644 --- a/flake.nix +++ b/flake.nix @@ -18,6 +18,10 @@ url = "github:nix-community/disko"; inputs.nixpkgs.follows = "nixpkgs"; }; + git-hooks = { + url = "github:cachix/git-hooks.nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = @@ -28,6 +32,7 @@ mailserver, disko, sops, + git-hooks, }: let sshkeys = [ @@ -42,6 +47,12 @@ devShells.x86_64-linux.default = let pkgs = nixpkgs.legacyPackages.x86_64-linux; + pre-commit-check = git-hooks.lib.x86_64-linux.run { + src = ./.; + hooks = { + nixfmt-rfc-style.enable = true; + }; + }; in pkgs.mkShell { # Import GPG keys from keys directory @@ -53,11 +64,15 @@ # Isolate sops GPG keys to .git/gnupg (optional) # sopsCreateGPGHome = true; + shellHook = '' + ${pre-commit-check.shellHook} + ''; + nativeBuildInputs = [ sops.packages.x86_64-linux.sops-import-keys-hook ]; - buildInputs = [ + buildInputs = pre-commit-check.enabledPackages ++ [ pkgs.sops ]; }; @@ -193,7 +208,6 @@ [ ./hosts/${input} ./default.nix - ./modules/monitoring.nix disko.nixosModules.disko authentik.nixosModules.default mailserver.nixosModules.mailserver diff --git a/hosts/monitoring/default.nix b/hosts/monitoring/default.nix deleted file mode 100644 index e30daba..0000000 --- a/hosts/monitoring/default.nix +++ /dev/null @@ -1,246 +0,0 @@ -{ - 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 - 4317 # OTLP gRPC (Proxmox) - 4318 # OTLP HTTP (Proxmox) - ]; - }; - }; - - # 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"; - }; - }; - limits_config = { - ingestion_rate_mb = 32; - ingestion_burst_size_mb = 64; - 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 = [ - { - 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; - 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 = { - 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; - }; - limits = { - ingestion_rate = 100000; - ingestion_burst_size = 200000; - max_global_series_per_user = 0; - compactor_blocks_retention_period = "672h"; # 28 days - }; - store_gateway = { - sharding_ring = { - replication_factor = 1; - kvstore.store = "memberlist"; - }; - }; - }; - }; - - # Grafana - Visualization and dashboarding - services.grafana = { - enable = true; - settings = { - server = { - http_addr = "127.0.0.1"; - http_port = 3000; - domain = "mon.adm.htw.stura-dresden.de"; - root_url = "https://mon.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."log.adm.htw.stura-dresden.de" = { - forceSSL = true; - enableACME = true; - locations."/" = { - proxyPass = "http://127.0.0.1:3100"; - proxyWebsockets = true; - recommendedProxySettings = true; - }; - }; - - virtualHosts."met.adm.htw.stura-dresden.de" = { - forceSSL = true; - enableACME = true; - locations."/" = { - proxyPass = "http://127.0.0.1:9009"; - recommendedProxySettings = true; - }; - }; - - virtualHosts."mon.adm.htw.stura-dresden.de" = { - forceSSL = true; - enableACME = true; - locations."/" = { - proxyPass = "http://127.0.0.1:3000"; - proxyWebsockets = true; - recommendedProxySettings = true; - }; - }; - }; - - # 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"; - }; - - transforms.proxmox_normalize_logs = { - type = "remap"; - inputs = [ "proxmox_otlp.logs" ]; - source = '' - .host = string(.resources."host.name") ?? "proxmox" - .unit = string(.attributes."service.name") ?? "proxmox" - ''; - }; - - 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; - - system.stateVersion = "25.11"; -} diff --git a/hosts/nextcloud/default.nix b/hosts/nextcloud/default.nix index 80c0bb3..304becf 100644 --- a/hosts/nextcloud/default.nix +++ b/hosts/nextcloud/default.nix @@ -87,11 +87,6 @@ recommendedProxySettings = true; recommendedTlsSettings = true; - commonHttpConfig = '' - real_ip_header proxy_protocol; - set_real_ip_from 141.56.51.1/32; - ''; - logError = '' /dev/null emerg ''; @@ -99,21 +94,9 @@ virtualHosts.${config.networking.fqdn} = { forceSSL = true; enableACME = true; - listen = [ - { - port = 80; - addr = "0.0.0.0"; - } - { - port = 443; - addr = "0.0.0.0"; - ssl = true; - proxyProtocol = true; - } - ]; - # extraConfig = '' - # access_log off; - # ''; + extraConfig = '' + access_log off; + ''; }; # virtualHosts."cloud.htw.stura-dresden.de" = { # forceSSL = true; diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index e688417..897e27e 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -20,99 +20,25 @@ } ]; defaultGateway.address = "141.56.51.254"; - firewall.enable = false; + firewall = { + allowedTCPPorts = [ + 22 + 53 # DNS + 80 + 443 + 1005 + 2142 + ]; + allowedUDPPorts = [ + 53 # DNS + 123 # NTP + ]; + }; 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 141.56.51.0/24 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; - } - } - ''; }; }; - # 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 @@ -126,112 +52,96 @@ 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 = true; }; plone_alt = { dest = "141.56.51.3"; domain = "www.stura.htw-dresden.de"; httpPort = 80; httpsPort = 443; - sendProxy = true; }; plone_neu = { dest = "141.56.51.3"; domain = "www.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; - sendProxy = true; }; plone_neu2 = { dest = "141.56.51.3"; domain = "htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; - sendProxy = true; }; 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; + }; + cloud = { + dest = "141.56.51.16"; + domain = "cloud.htw.stura-dresden.de"; + httpPort = 80; + httpsPort = 443; }; wiki = { dest = "141.56.51.13"; domain = "wiki.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; - sendProxy = true; }; 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 @@ -250,15 +160,6 @@ prev // (builtins.foldl' ( val: vhost: - let - proxyProtocol = - if - self.nixosConfigurations.${name}.config.services.nginx.virtualHosts.${vhost}.listen == [ ] - then - false - else - true; - in val // { "${vhost}" = { @@ -266,7 +167,6 @@ domain = vhost; httpsPort = 443; httpPort = 80; - sendProxy = proxyProtocol; }; } ) { } vhosts) @@ -323,43 +223,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 @@ -433,37 +333,20 @@ 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 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 + 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 defaults log global mode tcp option tcplog - - # 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 + timeout connect 5s + timeout client 30s + timeout server 30s # stats seite zeigt backend connection status, wenn check gesetzt ist frontend stats @@ -471,21 +354,13 @@ mode http stats enable stats uri /stats - stats refresh 5s # Reduce from 10s for real-time monitoring + stats refresh 10s stats show-legends 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 - mode http - tcp-request connection expect-proxy layer4 if { src 178.104.18.93 } - 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 ( @@ -504,8 +379,8 @@ prev: name: value: prev + '' - http-request redirect scheme https code 301 if !is_acme is_${name} use_backend ${name}_80 if is_${name} + http-request redirect scheme https code 301 if !is_acme is_${name} '' ) "" forwards} @@ -526,18 +401,10 @@ 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 + # mehrere pakete puffern und connection beenden wenn es kein ssl handshake sieht + tcp-request inspect-delay 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: @@ -568,118 +435,14 @@ server ${name} ${value.dest}:${builtins.toString value.httpPort} 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} ${ - 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} check '' ) "" forwards} ''; }; - 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!() - ''; - }; - 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" - "add_host_label_haproxy" - ]; - }; }; - - 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/redmine/default.nix b/hosts/redmine/default.nix index 2bbd398..d327168 100644 --- a/hosts/redmine/default.nix +++ b/hosts/redmine/default.nix @@ -90,9 +90,7 @@ services.redmine.settings.production.email_delivery = { delivery_method = ":smtp"; smtp_settings = { - # @tan 27-03-2026: muss an "alten" mailserver senden - #address = "mail.${config.networking.domain}"; - address = "mail.stura.htw-dresden.de"; + address = "mail.${config.networking.domain}"; port = 25; }; #### Alternativ waere vielleicht auch das Versand von Mails durch das Programm sendmail (als lokale Installation) moeglich. @@ -134,29 +132,13 @@ #### Der StuRa speichert nicht! services.nginx.logError = ''/dev/null emerg''; - # services.nginx.appendHttpConfig = '' - # access_log off; - # ''; - services.nginx.commonHttpConfig = '' - real_ip_header proxy_protocol; - set_real_ip_from 141.56.51.1/32; + services.nginx.appendHttpConfig = '' + access_log off; ''; #### 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}"; diff --git a/hosts/v6proxy/default.nix b/hosts/v6proxy/default.nix index 39e2521..6dd17b3 100644 --- a/hosts/v6proxy/default.nix +++ b/hosts/v6proxy/default.nix @@ -38,44 +38,15 @@ "9.9.9.9" "1.1.1.1" ]; - firewall.enable = false; + firewall = { + allowedTCPPorts = [ + 22 + 80 + 443 + ]; + }; 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; - } - } - ''; }; }; @@ -125,50 +96,12 @@ server proxy 141.56.51.1:80 backend http_443 mode tcp - server proxy 141.56.51.1:443 send-proxy-v2 + server proxy 141.56.51.1:443 ''; }; }; - 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; [ ]; system.stateVersion = "25.11"; diff --git a/hosts/wiki/default.nix b/hosts/wiki/default.nix index 179780d..bd8bbb6 100644 --- a/hosts/wiki/default.nix +++ b/hosts/wiki/default.nix @@ -99,17 +99,6 @@ 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"; @@ -161,8 +150,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/CategoryLockdown-REL1_45-a715472.tar.gz"; - sha256 = "sha256-1gl5m9xkmLrdjoR0M13gcQHLtZt4Bt0PUXDiDEqjpvk="; + url = "https://extdist.wmflabs.org/dist/extensions/Lockdown-REL1_45-a46dbea.tar.gz"; + sha256 = "sha256-zTTpbQiqudLILPSzmKGjKr6wZjh0YUttGmqwjPpAToc="; }; #### Hinzufuegen der Erweiterung ConfirmEdit fuer eine zusaetzliche Bestaetigung bei Bearbeitungen, etwa um Herausforderungen (aka CAPTCHA) zu stellen @@ -179,8 +168,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/ContributionCredits-REL1_45-22c28de.tar.gz"; - sha256 = "sha256-9T67jCEYQyU7P9sN7tYbnevU5+FX6Y1nydXGEdzQS9k="; + url = "https://extdist.wmflabs.org/dist/extensions/ContributionScores-REL1_45-cd4c94b.tar.gz"; + sha256 = "sha256-8ClNtEQ66deKM1DsRYaaZ3KlRl4yCt6UhpXcozRQzQ8="; }; #### Hinzufuegen der Erweiterung Interwiki fuer das Verwenden von Verweisen als eine Art Namensraum, wie beispielweise auf Wikipedia oder selbst festgelegte Verweise @@ -201,8 +190,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-433f6c2.tar.gz"; - sha256 = "sha256-JyY4pJNBKQ9bOKrilPWCheZ5ihWwPM6ZJ0qHsZ3coPk="; + url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_45-446566b.tar.gz"; + sha256 = "sha256-DTDKlzet3lThh/sRLucyb8b9lhK5FYZ+dMgwrThFFBM="; }; }; diff --git a/modules/monitoring.nix b/modules/monitoring.nix deleted file mode 100644 index 30cba16..0000000 --- a/modules/monitoring.nix +++ /dev/null @@ -1,123 +0,0 @@ -{ 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" ]; - }; - - 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 = { - 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" - "met.adm.htw.stura-dresden.de" - ]; - }; - services.vector = { - enable = true; - settings = { - sources = { - host_metrics = { - type = "host_metrics"; - collectors = [ - "cpu" - "disk" - "filesystem" - "load" - "host" - "memory" - "network" - "process" - ]; - }; - - 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!() - del(.tags.command) - ''; - }; - - add_host_label_logs = { - type = "remap"; - inputs = [ "journald_logs" ] ++ lib.optional (cfg.extraLogFiles != [] || config.services.nginx.enable) "extra_log_files"; - source = '' - .host = get_hostname!() - .unit = string(."_SYSTEMD_UNIT") ?? "file" - ''; - }; - }; - - sinks = { - mimir = { - type = "prometheus_remote_write"; - 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" ] ++ cfg.extraLogInputs; - endpoint = "https://log.adm.htw.stura-dresden.de"; - labels = { - host = "{{ host }}"; - unit = "{{ unit }}"; - }; - tls.verify_certificate = false; - encoding.codec = "json"; - }; - }; - }; - }; - - systemd.services.vector.serviceConfig.SupplementaryGroups = - [ "systemd-journal" ] - ++ lib.optional config.services.nginx.enable "nginx" - ++ cfg.extraGroups; - }; -}