From 2cd636b6d4a944e3fc4c006406c385ea0f1d6ddc Mon Sep 17 00:00:00 2001 From: oqyude Date: Thu, 27 Aug 2026 23:28:41 +0300 Subject: [PATCH] vds/nginx: forward real client IP to 3x-ui MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With podman bridge networking, 3x-ui no longer sees the actual client IP — it sees the bridge gateway. Without explicit proxy_set_header directives, subscription URLs, geo-rules, logs and fail2ban will all treat every request as coming from the same IP. Apply Host/X-Real-IP/X-Forwarded-For/X-Forwarded-Proto to all 3x-ui locations so the panel keeps working as if it were on host network. --- modules/vds/nginx.nix | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/modules/vds/nginx.nix b/modules/vds/nginx.nix index cb8ee78..d4a9990 100644 --- a/modules/vds/nginx.nix +++ b/modules/vds/nginx.nix @@ -6,6 +6,16 @@ }: let server = "100.64.0.0"; + # Forward real client IP/host to 3x-ui so it can manage addresses + # (subscription URLs, logs, geo-rules, fail2ban) as if it shared the + # host network. With podman bridge networking, the source IP that + # 3x-ui sees is the bridge gateway instead of the actual client. + proxyHeaders = '' + 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; + ''; in { users.users.nginx.extraGroups = [ "acme" ]; @@ -24,18 +34,22 @@ in "/" = { proxyPass = "http://localhost:2049"; proxyWebsockets = true; + extraConfig = proxyHeaders; }; "/subs/" = { proxyPass = "http://localhost:2096"; proxyWebsockets = true; + extraConfig = proxyHeaders; }; "/subsjs/" = { proxyPass = "http://localhost:2096"; proxyWebsockets = true; + extraConfig = proxyHeaders; }; "/clash/" = { proxyPass = "http://localhost:2096"; proxyWebsockets = true; + extraConfig = proxyHeaders; }; }; };