Learning objectives
After reading this article you will be able to:
- Understand what a reverse proxy does and how it differs from a forward proxy
- Know what it is for: HTTPS, caching, load balancing and protection
- Set up a simple nginx reverse proxy, including WebSocket
When you open a website, you almost never talk directly to the program that builds the page. Somewhere in between, a server receives your request and hands it to the app. That intermediary is the reverse proxy, and it sits in front of most sites and APIs you use.
Understanding it answers common questions: where HTTPS is configured, why your app sees the wrong IP, how to run two apps on the same public ports, and why a WebSocket drops after a minute.
What is a reverse proxy?#
A reverse proxy is a server that receives requests on behalf of other servers and forwards them. The client talks only to it. The server behind it, called the upstream or backend, never receives direct connections from the internet.
The name comes from the contrast with the ordinary proxy. A forward proxy acts on behalf of the client: a company uses one to filter what employees can visit, and the destination site sees the proxy's IP. A reverse proxy acts on behalf of the server: the client sees the proxy's address and has no idea how many apps are behind it.
Well-known examples: nginx, Caddy, HAProxy, Traefik and Envoy. CDN services also work as a global reverse proxy.
How does a reverse proxy work?#
A request goes through five steps:
- The browser resolves the domain through DNS and connects to the proxy's IP.
- The proxy accepts the connection and, for HTTPS, performs the TLS handshake.
- It reads the request (method, path,
Hostheader) and decides which upstream gets it. - It opens a connection to the upstream, usually on the same machine or private network, and forwards the request.
- It receives the response and returns it to the client.
Because the proxy reads the request, it can change it on the way: add headers, rewrite paths, cache the response or refuse the connection.
What is a reverse proxy used for?#
- HTTPS in one place. The proxy terminates TLS and speaks plain HTTP to the app on the internal network. Your code never handles certificates. See what SSL/TLS is.
- Many apps on one IP. Using the
Hostheader, the proxy sendsapi.example.comto one app andexample.comto another, both on ports 80 and 443. - Load balancing. The proxy spreads requests across several copies of the app. That is the topic of what a load balancer is.
- Caching. Responses that do not change are served from the proxy's memory or disk without waking the app. At global scale, this is a CDN.
- Protection. The app is not exposed. The proxy can rate limit by IP, block attack patterns and hide infrastructure details.
- Compression and HTTP/2. The proxy compresses responses and speaks modern protocols to the client even if the app only understands HTTP/1.1.
How do you set up a reverse proxy with nginx?#
Assume a Node.js app listening on 127.0.0.1:3000. The file below sends everything that reaches the domain to it:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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;
}
}What each line does:
proxy_passsets the upstream. It can behttp://,https://or a Unix socket.- By default, nginx sends the upstream
Host: $proxy_host, which is the upstream's own address.proxy_set_header Host $hostforwards the domain the client asked for, which many frameworks expect. X-Forwarded-Forcarries the list of IPs the request passed through.$proxy_add_x_forwarded_forappends the IP of whoever connected to the proxy to the value the client already sent.X-Forwarded-Prototells the app whether the client usedhttporhttps, which it needs to build correct links and redirects.
Check the syntax with nginx -t and reload with nginx -s reload.
What if the app uses WebSocket?#
Upgrade and Connection are hop-by-hop headers: nginx does not pass them on by itself. Without them the WebSocket handshake fails. Add a dedicated location:
location /ws/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
}By default, nginx closes the connection if the upstream sends no data for 60 seconds. For idle connections, raise proxy_read_timeout as above or have the app send ping frames periodically.
How does the app learn the user's real IP?#
Behind a proxy, the connection reaching the app comes from the proxy, so the source IP is the proxy's. The client IP travels in X-Forwarded-For, formatted as client, proxy1, proxy2. MDN describes it as a de facto standard; the standardized version is Forwarded, which is much less used.
There is a risk: any client can send a fake X-Forwarded-For. For rate limiting or access control, use only the IPs added by proxies you trust, counting from the right of the list. If the app can be reached directly from the internet, no part of the header can be trusted. Frameworks have an option for this, such as trust proxy in Express.
When don't you need a reverse proxy?#
- Bots that only make outbound connections (Discord, Telegram via long polling) receive no requests.
- A single simple app on a platform that already serves HTTPS in front of it does not need you to install nginx yourself.
- Non-HTTP protocols, such as a direct database connection, need a TCP (layer 4) proxy or no proxy at all.
Each extra layer is one more piece to configure and monitor, and one more thing that can fail. Add one when you have a concrete reason.
How to do this on Square Cloud#
On Square Cloud you do not install or configure a reverse proxy for the common case. Every web application gets a *.squareweb.app subdomain with HTTPS on any plan, and TLS is automatic. The edge takes the HTTPS connection, redirects HTTP to HTTPS and forwards the request to your app, which only has to listen on 0.0.0.0 on the port in the PORT variable.
The network includes an Anycast CDN with more than 200 points of presence, HTTP/3, WebSockets, WAF and L3/L4/L7 DDoS mitigation. The proxy does not cut long connections: WebSocket and SSE pass through without buffering.
Starting with the Standard plan, you point your own domain by creating the DNS records shown in the dashboard at your registrar. The domain stays registered in your name, and the dashboard shows validation status in real time.
To spread traffic across copies of your app, load balancing serves one custom domain from several applications, with round-robin, passive failover and no sticky sessions: up to 2 applications per domain on Standard, up to 5 on Pro and up to 10 on Enterprise.
See the network layer details in Network and CDN.
Network
Custom domains, automatic TLS and a global CDN for your app
FAQs
What is the difference between a proxy and a reverse proxy?
A forward proxy sits on the client side and hides who is asking. A reverse proxy sits on the server side and hides who is answering. In both cases the proxy is an intermediary.
Is a reverse proxy the same as a load balancer?
No, but they overlap. Every HTTP load balancer acts as a reverse proxy, but a reverse proxy can sit in front of a single server, and then nothing is being balanced.
Do I need a reverse proxy for a bot?
Almost never. A bot that only opens outbound connections to the platform API does not receive HTTP requests. A reverse proxy makes sense for sites and APIs that receive traffic.
Why does my app show the proxy IP instead of the user IP?
Because the connection reaching your app comes from the proxy. The original IP travels in a header such as X-Forwarded-For, and your app must be configured to read it, trusting only your own proxy.
More in Networking and domains
See all 27 articles- What is a load balancer and how does it work?A load balancer spreads incoming requests across several servers. Learn how it works, the main algorithms, layer 4 vs 7, and a working nginx example.
- DNS records explained: A, CNAME, MX, TXTDNS records are the instructions in a zone that tell the internet where a name points. Learn A, AAAA, CNAME, MX, TXT, NS and CAA with examples and dig commands.
- How to point a domain to your server or appTo point a domain to your server or app, create a CNAME (or A) record in your registrar's DNS panel. Steps, how to test it, and common mistakes.
- Cache-Control headers explainedCache-Control is the HTTP header that sets how long browsers and CDNs keep a response. Learn max-age, no-cache, immutable and ready-made recipes for each file type.