Reverse Proxy: What It Is and How to Ship One With Self-Hosted Software
A reverse proxy accepts requests on behalf of one or more backend services and forwards them. Learn what reverse proxies do, which ones are common and what vendors of self-hosted software have to get right behind one.
What Is a Reverse Proxy?
A reverse proxy is a server that accepts requests on behalf of one or more backend services and forwards them. Clients only ever talk to the proxy and do not see which backend answers or where it runs.
“Reverse” sets it apart from a forward proxy, which acts for the clients. A company proxy that all outgoing web traffic passes through is a forward proxy. A reverse proxy acts for the servers and sits in front of them.
What a Reverse Proxy Does
The most common job is TLS termination. The proxy holds the certificates and decrypts HTTPS, and the backends serve plain HTTP on an internal network. Caddy and Traefik can obtain and renew the certificates through ACME by themselves.
The proxy also routes requests to different backends by hostname or path, so one public address can serve many services. When a backend runs several instances, the proxy spreads the requests across them and stops sending traffic to an instance that fails its health check. With weighted upstreams it can send a share of the traffic to a new version, which is how blue-green and canary deployments switch versions without downtime.
On the way through, a proxy can add headers, compress responses, limit request rates or require authentication before a request reaches the backend.
Common Reverse Proxies
| Proxy | Known for |
|---|---|
| Caddy | Automatic HTTPS with almost no configuration |
| Traefik | Configuration from Docker labels and Kubernetes resources |
| HAProxy | High-throughput load balancing on layer 4 and layer 7 |
| Envoy | The data plane of many service meshes and Kubernetes gateways |
In Kubernetes, the cluster provides the reverse proxy through Ingress or the Gateway API, and applications only declare the routes they need.
Reverse Proxy vs. Load Balancer vs. Reverse Tunnel
A load balancer that works on layer 7 reads HTTP requests, which makes it a reverse proxy whose main job is spreading load. A layer 4 load balancer only forwards TCP or UDP connections, so it cannot route by path, pick a certificate per hostname or set headers.
A reverse tunnel solves a different problem. A reverse proxy has to be reachable, since it accepts inbound connections and forwards them to backends it can reach. With a reverse tunnel, an agent next to the service dials out to a relay, and the service becomes reachable without any inbound connection into its network. The two often work together: Cloudflare’s edge, for example, acts as a reverse proxy for the requests it sends through a Cloudflare Tunnel.
Reverse Proxies in Self-Hosted Software
Vendors of self-hosted software have to decide whether to ship a reverse proxy or leave it to the customer.
For Docker Compose, shipping one is often the friendlier choice. A Caddy service in the Compose file gives the customer HTTPS on their own domain without extra setup. Many customers already run a proxy or a load balancer, though, so make the bundled one optional and document how to run the application behind theirs.
For Kubernetes, leave the proxy to the cluster. Most clusters already offer Ingress or the Gateway API, and a proxy installed by your Helm chart would need cluster-wide permissions and a load balancer of its own, which a shared cluster rarely allows. Ship the routing in the chart as an option, and let the customer set the hostname, the TLS certificate and whatever else their setup needs.
What to Get Right Behind a Proxy
Support cases about reverse proxies tend to come back to the same few settings.
Behind a proxy, every request comes from the proxy’s address.
The proxy passes the original client address in X-Forwarded-For and the original scheme and host in X-Forwarded-Proto and X-Forwarded-Host.
The application has to read these headers, but only when they come from a proxy it trusts, since any client can send them too.
The backend receives plain HTTP and cannot tell from the request whether users reach it over HTTPS. Let customers configure the public URL, and build redirects, links in emails and OAuth callbacks from it.
WebSockets need the Upgrade and Connection headers passed through, and some proxies only do that when configured to.
Proxies also close connections that stay idle for too long, which cuts off long polling and log streams.
Many proxies limit the size of a request body and answer larger requests with 413 Request Entity Too Large.
File uploads and container image pushes need that limit raised.
Exports and other long-running requests need a proxy timeout longer than the request takes.
Customers who run their own proxy hit these settings one by one, so write down what your application needs for the common proxies.
Reverse Proxies with Distr
Distr itself runs behind a TLS-terminating reverse proxy: Caddy in the Docker Compose setup and an Ingress controller in Kubernetes, as described in the system requirements.
Vendors who distribute their software with Distr can ship a proxy as a deployment of its own. The blue-green deployments guide uses Caddy with weighted upstreams to switch traffic between two versions of an application without downtime. For Docker Swarm, Load Balancing and Routing in Docker Swarm compares the built-in routing mesh with Traefik and other proxies.







