From fe6650622f2436b6eaef483e643b917f208cb122 Mon Sep 17 00:00:00 2001 From: goeranh Date: Fri, 10 Apr 2026 15:38:30 +0200 Subject: [PATCH] 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}