# Fault-Tolerant Proxy Load Balancing for n8n in Docker: Fixing DNS Timeouts and Access Errors
Running n8n through a single proxy is an architectural vulnerability. If the IP gets blocked or the proxy server fails, all workflows grind to a halt. The only reliable fix is deploying a pool of proxies with automatic failover and round-robin balancing. This guide walks you through setting up 3proxy in a Docker stack, resolving critical DNS errors and permissions issues, and verifying the full chain's reliability.
Fault-Tolerant Proxy Pool Architecture
Instead of connecting n8n directly to Telegram or other external APIs, we insert a local 3proxy container acting as a gateway. It handles HTTP/HTTPS requests from n8n on port 3128 and distributes them across a predefined list of external SOCKS5 proxies. Key benefits:
- Automatic failover: If one node goes down, traffic instantly shifts to the next available proxy.
- Transparency for n8n: No workflow changes needed—just set a single proxy address in environment variables.
- IP leak protection: If all external proxies fail, connections are forcibly dropped, preventing traffic from leaking out via the server's real IP.
The setup uses docker-compose, with both services (n8n and 3proxy) in a custom network. This ensures stable internal routing without exposing ports on the host.
Setting Up docker-compose.yml and the 3proxy Config File
Start with this basic stack. Note the user: "0:0" parameter—it's essential for 3proxy to work inside the container, as the process needs privileges to bind network ports and read config from volumes.
version: '3.8'
services:
n8n:
image: docker.n8n.io/n8nio/n8n:latest
container_name: n8n
environment:
- HTTP_PROXY=http://3proxy:3128
- HTTPS_PROXY=http://3proxy:3128
- http_proxy=http://3proxy:3128
- https_proxy=http://3proxy:3128
networks:
- n8n_net
3proxy:
image: ghcr.io/z3apa3a/3proxy:latest
container_name: 3proxy
restart: always
user: "0:0"
volumes:
- ./3proxy.cfg:/etc/3proxy/3proxy.cfg
networks:
- n8n_net
networks:
n8n_net:
name: n8n_net
The core balancing logic goes in 3proxy.cfg. Here's a minimal working config with comments:
daemon
log /var/log/3proxy.log D
logformat "L%t.%. %N.%p %E %U %C:%c %R:%r %O %I %h %T"
# Use Docker's DNS resolver, not an external one (e.g., 8.8.8.8)
nserver 127.0.0.11
nscache 65536
timeouts 1 5 30 60 180 1800 15 60
# Enable ACL — without this, parent chains are ignored
auth iponly
# Allow must come BEFORE declaring parent
allow *
# Pool of external proxies (round-robin)
parent 1000 socks5 IP_PROXY_1 PORT_1 LOGIN_1 PASS_1
parent 1000 socks5 IP_PROXY_2 PORT_2 LOGIN_2 PASS_2
parent 1000 socks5 IP_PROXY_3 PORT_3 LOGIN_3 PASS_3
# Deny direct outbound if all proxies are unavailable
deny * * 0.0.0.0/0
# Launch HTTP proxy on port 3128
proxy -p3128 -a
flush
Diagnosing and Fixing Common Errors
On first launch, you'll hit three typical issues. Solving them is key to a stable system.
Error 1: DNS Timeouts (26 Seconds per Request)
Symptoms: n8n hangs on every request for exactly 26 seconds, then either gets a response or times out.
Cause: The config points to an external DNS server (e.g., nserver 8.8.8.8), but the 3proxy container can't reach the internet outside Docker's custom network. DNS queries go nowhere and wait for timeout.
Fix: Switch to Docker's internal resolver with nserver 127.0.0.11. This address is always available in any container and forwards queries to the host system.
Error 2: Permission Denied on Container Startup
Symptoms: The 3proxy container crashes right after starting, with logs showing inability to bind ports or read the config.
Cause: The official 3proxy image runs as a non-privileged user by default, which can't bind ports below 1024 or access mounted volumes.
Fix: Explicitly set user: "0:0" in docker-compose for the 3proxy service. This runs the process as root in the container's isolated namespace—safe since networking is restricted.
Error 3: Traffic Bypassing the Proxy Pool
Symptoms: n8n works, but outbound IP checks show the server's real address, not a proxy. The balancer ignores parent directives.
Causes and Fixes:
- Wrong directive order:
allow *must come strictly before the firstparent, or the parser throws aChaining errorand disables chaining. - ACL disabled:
auth nonefully disables access control, breaking forwarding logic. Useauth iponlyinstead. - No fallback protection: Without
deny 0.0.0.0/0, the system can leak direct traffic if the entire pool fails. This line ensures connections drop rather than falling back to the default route.
Verifying System Functionality
Once set up, confirm traffic flows through the balancer and proxy pool. Use these two checks:
- Check 3proxy logs:
```
docker compose logs --tail 20 3proxy
```
Look for entries like [NNN] CONNECT ...—they confirm requests are accepted and forwarded. If you see Permission denied, revisit the user: "0:0" setting.
- End-to-end test from n8n:
```
docker compose exec n8n curl -Ivx http://3proxy:3128 https://api.telegram.org
```
Expect an HTTP 200 OK and headers. If it hangs, DNS is the issue (nserver). If Connection refused, ensure 3proxy is running and port 3128 is open.
Optionally, add logrotate 1000000 5 to the 3proxy config for size-based log rotation to avoid filling the disk.
Key Takeaways
- Docker DNS must always point to 127.0.0.11, or you'll get 26-second timeouts.
- Container user permissions are critical: Without
user: "0:0", 3proxy can't bind port 3128. - Directive order in 3proxy config matters:
allow *beforeparent,auth iponlyovernone. - IP leak protection is essential:
deny 0.0.0.0/0blocks direct traffic on full proxy failure. - Round-robin balancing is built into 3proxy—no extra tools or scripts needed.
This setup keeps n8n running smoothly even with partial infrastructure failures. Changes are transparent to workflows—just point to the local proxy once, and routing handles the rest automatically.
— Editorial Team
No comments yet.