Repository navigation
Feature Guide L4 Proxy Hosts
Create and manage Layer 4 (TCP/UDP) stream proxies handled by Caddy.
- What L4 Proxy Hosts Do
- Create an L4 Proxy Host
- Protocol Options
- Matcher Types
- Advanced Features
- Port Management
- Examples
- Troubleshooting
L4 proxy hosts forward raw TCP or UDP traffic at the transport layer. Unlike HTTP reverse proxies (Layer 7), L4 proxies do not inspect or modify the application protocol — they simply route streams to upstream servers.
Common uses:
- Proxy database connections (MySQL, PostgreSQL, Redis)
- Forward game server traffic (UDP)
- Route TLS connections by SNI without terminating TLS
- Proxy mail servers (SMTP, IMAP)
- Load balance any TCP/UDP service
- Navigate to L4 Proxy Hosts in the sidebar
- Click Create L4 Proxy Host
- Fill in the required fields:
- Name — a descriptive label (e.g. "MySQL Primary")
-
Protocol —
TCPorUDP -
Listen Address — the port or address to listen on (e.g.
:3306,0.0.0.0:5432) -
Upstreams — one or more
host:portdestinations (e.g.db.internal:3306)
- Click Save
Reserved ports: ports 80, 443 and 2019 cannot be used for L4 proxy hosts. CPM's Caddy listens on 80/443 for regular HTTP/HTTPS proxy hosts and on 2019 for the admin API; a second L4 listener on the same port would silently split connections between the two listeners (Caddy sets
SO_REUSEPORT), causing intermittent handshake failures. The UI and API reject these ports. This also means L4 SNI passthrough for additional hostnames must use a different public port (e.g.:8443) — Caddy cannot share port 443 between its HTTP app and an independent layer4 server.
After saving, a banner appears prompting you to Apply Port Changes. This updates the Docker port mappings so Caddy can accept traffic on the configured ports.
| Protocol | Description |
|---|---|
| TCP | Bidirectional byte stream. Supports TLS termination, SNI matching, and proxy protocol. |
| UDP | Datagram forwarding. No TLS support. |
Matchers let you route traffic on the same port to different upstreams based on protocol-level signals.
| Matcher | Description | Protocol |
|---|---|---|
| None | All traffic on the listen address goes to the upstreams | TCP, UDP |
| TLS SNI | Match on the TLS Server Name Indication field. Routes encrypted traffic by hostname without terminating TLS. | TCP |
| HTTP Host | Match on the HTTP Host header (for plaintext HTTP over TCP) |
TCP |
| Proxy Protocol | Detect HAProxy proxy protocol headers from clients | TCP |
When using a matcher, provide one or more matcher values (e.g. hostnames for SNI matching).
Available for TCP only. When enabled, Caddy terminates TLS at the proxy and forwards plaintext to upstreams. Useful when upstreams don't support TLS natively.
- Send (v1/v2) — forward the original client IP to upstreams using HAProxy proxy protocol
- Receive — accept proxy protocol headers from clients (e.g. behind another load balancer)
When multiple upstreams are configured, choose a load balancing policy:
| Policy | Description |
|---|---|
random |
Random upstream selection (default) |
round_robin |
Sequential rotation through upstreams |
least_conn |
Route to the upstream with fewest active connections |
ip_hash |
Consistent hashing by client IP (sticky sessions) |
first |
Always use the first available upstream |
- Active — periodically probe upstreams on a configurable port, interval, and timeout
- Passive — track failures and latency in real time; mark upstreams unhealthy after thresholds
Override the system DNS resolver for upstream hostname resolution. Supports custom resolver addresses, fallback servers, and configurable timeout.
Resolve upstream hostnames to IP addresses at config-apply time (DNS pinning). Choose address family: ipv4, ipv6, or both.
Block or allow traffic by country, continent, ASN, CIDR, or IP — the same geo blocking engine used by HTTP proxy hosts, applied at the transport layer.
L4 proxy hosts require Docker port mappings so that external traffic can reach Caddy.
When you create, edit, or delete an L4 proxy host, a banner appears at the top of the list prompting you to apply port changes. Clicking Apply will:
- Generate a Docker Compose override file with the required port mappings
- Signal the sidecar container to restart Caddy with the new ports
- Report the result (success or error)
Note: Port changes require a brief Caddy restart. Existing HTTP proxy hosts are not affected.
- Name: MySQL Primary
- Protocol: TCP
-
Listen Address:
:3306 -
Upstreams:
db-primary.internal:3306
- Name: Game Server
- Protocol: UDP
-
Listen Address:
:27015 -
Upstreams:
game1.internal:27015,game2.internal:27015 -
Load Balancing:
round_robin
Route multiple TLS services by hostname (SNI). Note the listen address uses a dedicated port — port 443 itself belongs to CPM's HTTP/HTTPS proxy hosts and cannot be shared with an L4 host (see Reserved ports):
- Name: Mail TLS
- Protocol: TCP
-
Listen Address:
:8443 - Matcher: TLS SNI
-
Matcher Values:
mail.example.com -
Upstreams:
mail-server.internal:993
Make sure you clicked Apply Port Changes after saving. The banner at the top of the L4 Proxy Hosts list shows pending changes.
Another service is already listening on the configured port. Choose a different listen address or stop the conflicting service.
These ports are bound by CPM's own Caddy listeners (HTTP/HTTPS proxy hosts on 80/443, admin API on 2019) and cannot be used for L4 proxy hosts. This restriction exists because Caddy sets SO_REUSEPORT on every listener, so a conflicting L4 bind would not fail loudly — instead connections would be silently split between the two listeners and about half of all TLS handshakes would fail. Use a different port (e.g. :8443 for TLS SNI passthrough). L4 hosts created before this restriction may still exist; they are skipped during config generation until their listen address is changed.
Verify the listen address includes the correct port and that your firewall allows UDP traffic on that port. Docker maps UDP ports separately from TCP.
SNI matching requires the client to send a TLS ClientHello with the expected server name. Verify with:
openssl s_client -connect your-server:8443 -servername mail.example.com