A reverse proxy gateway accepts public HTTPS traffic and forwards it to an application that listens only on a private address. This page explains the pattern, then gives the production deployment runbooks for the two gateways in the sources, Nginx and OpenResty.

How the gateway works

A reverse proxy gateway sits in front of an application: it accepts public traffic, terminates HTTPS, and forwards requests to the application over a private address, so the application port is never exposed directly. In this wiki’s sources the gateway is Nginx or OpenResty and the upstream is an application on 127.0.0.1:3000.12

flowchart LR
    accTitle: Request path through a reverse proxy gateway
    accDescr: A client connects over HTTPS to the Nginx or OpenResty gateway, which terminates TLS and forwards the request over a private address to the application, whose port is not exposed publicly.
    C[Client] -->|HTTPS| G[Gateway: Nginx or OpenResty, terminates TLS]
    G -->|proxy_pass to 127.0.0.1:3000| A[Application]

How the pieces are named

Nginx’s master process reads and validates configuration and worker processes serve requests. A server block is a virtual host, a location matches a request path, and proxy_pass forwards a request to the upstream application.1

Nginx or OpenResty

NginxOpenResty
What it isThe web serverAn Nginx-based platform with LuaJIT and Lua modules
Choose it forStatic serving and reverse proxyingGateway behaviour that needs reviewed Lua
On one hostNot together with OpenResty: both bind ports 80 and 443Replaces Nginx; not an add-on

As described in the two deployment guides.12

Rules that carry across

  • Preserve Host, X-Forwarded-For, and X-Forwarded-Proto, and trust them only when traffic is constrained to an approved gateway.
  • Never expose an unauthenticated development listener directly to the Internet.3
  • At the edge, Nginx and OpenResty remain useful for TLS, routing, rate limiting, and carefully bounded Lua extensions.4

Nginx production deployment

A baseline for running Nginx alone on one Ubuntu 24.04 LTS VM: static files, a reverse proxy to an application on 127.0.0.1:3000, and HTTPS through Certbot webroot.1

Steps

  1. Prepare the host. Confirm the domain resolves to the VM, the firewall allows TCP 80/443, time is correct, and no server owns either port (ss -lntp). Install nginx, curl, ca-certificates, and certbot.
  2. Configure. Back up /etc/nginx, remove the default site, create a site with an ACME challenge location, a /healthz location returning 200, and a location / that proxies to the application with proxy_connect_timeout 5s and proxy_read_timeout 60s. For a static-only site use try_files instead of the proxy.
  3. Enable. Link the site, run nginx -t, enable the service, and reload. Always run nginx -t before a reload.
  4. Add HTTPS. Prove HTTP health publicly (ACME needs public DNS and port 80), issue the certificate with certbot certonly --webroot, then add an HTTP-to-HTTPS redirect server that keeps the challenge location, and an HTTPS server with ssl_protocols TLSv1.2 TLSv1.3. Confirm certbot renew --dry-run.
  5. Verify each layer. Service state, effective config (nginx -T), loopback health, the upstream’s own health path, HTTPS via curl --resolve, and the journal. An open port is not an acceptance test.

Never copy privkey.pem into an application directory or repository.1

Troubleshooting by symptom

SymptomFirst checksDo not
nginx -t failsReported file and line, nginx -TReload anyway
Port 80/443 bind failuress port checkRun Nginx and OpenResty together
502 / 504Loopback upstream, app logs, error log, timeoutsRaise timeouts before finding the failing layer
403namei -l on the web root, ownershipchmod -R 777
404Effective config, root, location, URIChange many locations at once
413Whether large uploads are really required; a reviewed client_max_body_sizeRemove limits blindly
ACME failureDNS, port 80, challenge path, Certbot logsShare keys or disable TLS checks

As described in the guide.1

Monitoring

If nginx -V shows http_stub_status_module, expose stub_status on a loopback-only listener; it is not an authenticated admin API. Watch availability, status codes, latency, connections, restarts, disk and inodes, certificate expiry, and upstream errors.1

OpenResty production deployment

A baseline for running OpenResty alone on one Ubuntu 24.04 LTS VM. It differs from the Nginx deployment mainly in two ways: it installs from OpenResty’s package repository, and /healthz is served by a Lua script.2

When to choose it

Only when the gateway needs reviewed Lua behaviour; ordinary Nginx covers static serving and reverse proxying. OpenResty replaces the Nginx web-server process on the host, so disable Ubuntu’s nginx (after confirming it serves nothing required) rather than running both.

content_by_lua_file runs in OpenResty’s event-driven request path: no blocking shell commands, blocking file I/O, unbounded loops, secrets, or ad-hoc network calls without a reviewed design.2

Steps

  1. Prepare. Check DNS, ports 80/443, time, CPU architecture (dpkg --print-architecture; official x86_64 packages require SSE 4.2), and port ownership.
  2. Install. Add OpenResty’s signed apt repository (arm64 uses a different repository URL), install openresty, and create /etc/openresty/conf.d and /etc/openresty/lua. Use the openresty command, not a bare nginx that may be another binary.
  3. Configure. Write health.lua (owned by root:root, mode 0644), a site file whose /healthz uses content_by_lua_file, and include conf.d inside http {} of the vendor nginx.conf only if no equivalent include exists. Run openresty -t, enable, and reload.
  4. HTTPS. As for Nginx: prove HTTP health, issue with Certbot webroot, add the redirect and TLS servers, and dry-run renewal.
  5. Verify. Service, Lua health, upstream health, and TLS separately; then the journal.2

Troubleshooting additions

SymptomFirst checks
500 on /healthzError log, Lua path and ownership, config test; never make a broken script return success
502 / 504The loopback upstream before blaming Lua

As described in the guide.2

Footnotes

  1. Nginx Production Deployment and Operations for Beginners, original ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7

  2. OpenResty Production Deployment and Operations for Beginners, original ↩ ↩2 ↩3 ↩4 ↩5 ↩6

  3. Express BFF Production Deployment for Beginners, original ↩

  4. Modern BFF Architecture Assessment for Beginners, original ↩