Playbook

Configure Reverse Proxy

An nginx site with a Let's Encrypt certificate that forwards requests to your app, API or container.

Category

Web servers

Time limit per server

15 minutes

Temporary failures

Not retried: run it again

Version

1.0

Supported systems

Ubuntu 22.04+, Debian 12+, RHEL-compatible 8+ (AlmaLinux, Rocky Linux, RHEL, CentOS Stream, Oracle Linux), Amazon Linux 2023+

Options

As they appear on the run form, with their defaults.

Domains

List: one per line or comma-separated

Each must already point at this server. The first one names the site and certificate.

Default: Required

Forward requests to

Text

Such as http://127.0.0.1:8000 for an app on this server, or unix:/run/app.sock.

Default: Required

Email for Let's Encrypt

Text

Optional. Let's Encrypt uses it for account recovery and service notices.

Default: Empty

I accept the Let's Encrypt Subscriber Agreement

On or off

Required to get a certificate. Read it at https://letsencrypt.org/repository/.

Default: Off

Redirect HTTP to HTTPS

On or off

Default: On

Support WebSocket connections

On or off

Default: On

Largest request body

One choice

Larger uploads are refused before they reach the application.

  • 1 MB
  • 10 MB
  • 100 MB
  • 1 GB

Default: 10 MB

Use a staging certificate

On or off

For testing. Browsers do not trust staging certificates, but the limits are much higher.

Default: Off

Send HSTS

On or off

Browsers then use HTTPS only, for a year. Turn it on once HTTPS works for every domain.

Default: Off

When to use it

To serve an application over HTTPS on your own domain. Your application listens on a local port, a container's published port, another machine on the private network or a Unix socket; nginx terminates HTTPS in front of it with a free Let's Encrypt certificate. Run Install Nginx and Install Certbot first.

Before you run it

  • Every domain must already resolve to this server's public address. Check with dig +short shop.example.com or any DNS lookup tool; the answer must be the server's IP.
  • Ports 80 and 443 must be open in the server's firewall and in your provider's firewall or security group. Let's Encrypt connects on port 80.

Choosing the options

Domains — one per line or separated by commas, for example shop.example.com and www.shop.example.com. The first one names the site file and the certificate. Wildcard domains (*.example.com) are not supported: they need DNS validation.

Forward requests to — where your application answers:

  • http://127.0.0.1:8000 — an application on this server, such as one set up by Configure Python App.
  • http://127.0.0.1:8080 — a container published with -p 127.0.0.1:8080:80.
  • http://10.0.0.5:3000 or https://10.0.0.5:8443 — another machine on the private network.
  • unix:/run/app.sock — a Unix socket.

Email for Let's Encrypt — optional. Let's Encrypt uses it for account recovery and service notices.

I accept the Let's Encrypt Subscriber Agreement — required to get a certificate. Read it at https://letsencrypt.org/repository/.

Redirect HTTP to HTTPS — keep it on, so visitors who type http:// land on the secure site.

Support WebSocket connections — keep it on for applications that use WebSockets (live dashboards, chat, Laravel Reverb, Socket.IO). It does no harm otherwise.

Largest request body — uploads larger than this are refused by nginx before they reach your application. Choose 100 MB or 1 GB for sites that accept file uploads.

Use a staging certificate — for testing only. Browsers do not trust staging certificates, but Let's Encrypt's rate limits for them are much higher. Turn it off for a real certificate.

Send HSTS — tells browsers to use HTTPS only, for a year. Turn it on only once HTTPS works for every domain on the site, because browsers remember it.

What it does on the server

  1. Writes the site to a file named after the first domain, such as /etc/nginx/conf.d/iap-proxy-shop.example.com.conf, with a folder /var/www/iap-acme for Let's Encrypt's check file, and checks it with nginx -t.
  2. On SELinux systems, allows nginx to connect to the upstream (httpd_can_network_connect).
  3. Checks every domain with a dry run against Let's Encrypt's staging environment, so a domain that does not point here yet does not use up the real service's limits.
  4. Obtains the certificate with the webroot method, reloads nginx, and checks that port 443 serves the new certificate and that HTTP redirects.
  5. If anything fails, the previous nginx configuration is put back.

After the run

Open the first domain over HTTPS in a browser, such as https://shop.example.com/. Until your application answers at the upstream address, visitors see 502 Bad Gateway: the proxy works, the application behind it is not running yet. Keep the certificate renewing with Configure Certificate Renewal.

Common problems

"Let's Encrypt could not validate the domain." — The domain does not point at this server yet, or port 80 is blocked. Check the DNS record and both firewalls, wait for DNS to update, and run again.

"The dry run against Let's Encrypt's staging environment failed (above), so no real certificate was requested." — Same causes as above; the output shows Let's Encrypt's own reason.

"A Let's Encrypt certificate needs its Subscriber Agreement accepted" — Turn on I accept the Let's Encrypt Subscriber Agreement.

"Another nginx site already answers for …" — Another site file uses the same domain. Remove or rename that site, then run again.

"… is not an upstream this playbook accepts." — Use a full address with scheme and port, such as http://127.0.0.1:8000, or a socket such as unix:/run/app.sock.

Visitors see 502 Bad Gateway — nginx cannot reach your application. Check it is running and listening on the upstream address: curl -I http://127.0.0.1:8000 on the server.