Nginx in front of a backend

The application responds on 127.0.0.1:8080, but users need a domain name and HTTPS. Nginx acts as a reverse proxy here, accepting external requests and forwarding them to that internal backend. The guide follows installation and configuration through separate syntax, TLS and application-response checks; a running process alone does not establish service acceptance.

Backend, DNS and certificate

Commands target Ubuntu 24.04 LTS and its packaged Nginx. Record the version and review configuration borrowed from other releases.

Two vCPUs and 2 GiB RAM are example allocations. Determine workers and file descriptors through load tests. The backend must return its expected /health response before proxy configuration.

Replace app.example.com, prepare actual DNS/fullchain/private key, and restrict key access. Writing configuration requires sudo.

HTTP/2 syntax and packaged versions

listen 443 ssl suits this Ubuntu-package example. HTTP/2 syntax differs between Nginx branches. Check the installed version’s documentation before adding directives.

TLS at the proxy, HTTP on loopback

Follow the request: the client connects to Nginx on 443, TLS terminates at the proxy, and the request reaches the loopback backend. If the backend moves to another host, design the private-network and firewall protection for that path too. The application must accept origin headers only from a trusted proxy.

Example: a loopback application

Users reach only the proxy, with no direct external backend access. Configure one canary VM before changing the load-balancer path. Use matching domain/certificate identities in both tests.

Keys and proxy headers

Restrict key reads and keep the backend off public interfaces. Port 80 serves redirects/ACME and 443 serves HTTPS. This single-proxy example derives X-Forwarded-For from remote_addr so spoofed client headers do not become trusted origins. Multi-proxy chains need explicit trusted-proxy configuration.

Install packages and configure the virtual host

Before installing from the system repository, test the backend directly and preserve existing configuration. If the application itself does not respond, adding a proxy will not fix the cause and will add another layer to diagnose.

BASH
sudo apt-get update
sudo apt-get install -y nginx curl
nginx -v
curl --fail --max-time 5 http://127.0.0.1:8080/health
sudo cp -a /etc/nginx /root/nginx-before-change

The health endpoint must return HTTP 200 and its expected application payload. Before writing configuration, install the certificate chain and private key below. The key must have root ownership and mode 600.

BASH
sudo tee /etc/nginx/sites-available/enterprise-app >/dev/null <<'EOF'
server {
    listen 80;
    server_name app.example.com;
    return 301 https://app.example.com$request_uri;
}
server {
    listen 443 ssl;
    server_name app.example.com;
    ssl_certificate /etc/nginx/tls/fullchain.pem;
    ssl_certificate_key /etc/nginx/tls/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Request-ID $request_id;
        proxy_connect_timeout 5s;
        proxy_read_timeout 60s;
    }
}
EOF
sudo ln -s /etc/nginx/sites-available/enterprise-app /etc/nginx/sites-enabled/enterprise-app
sudo nginx -t
sudo systemctl reload nginx
curl --fail --max-time 10 https://app.example.com/health

Create the symlink only on first installation. Inspect its existing destination otherwise. Nginx -t must report syntax is ok and test is successful. Point canary DNS or --resolve at the canary VM. Resolve existing default-host or server_name conflicts before reloading.

Latency, 5xx and request IDs

Track 5xx rates, upstream latency and TLS errors alongside request count. X-Request-ID is sent to the backend, but searchable access-log IDs also require a configured log_format. Restrict exporter access to monitoring.

Place this log_format in the http context outside server blocks, then select it with access_log in the target server. The example omits query strings.

CODE
log_format upstream_trace '$remote_addr $request_id $request_method $uri $status $request_time $upstream_response_time';
# Inside the target server block:
access_log /var/log/nginx/app-access.log upstream_trace;

Diagnose 502 and 504

For 502 or 504, start at the backend: request /health directly and correlate its result and timing with the error log. A 502 often indicates a failed connection or invalid upstream response, while 504 indicates a timeout. That distinction guides whether to inspect a listener or processing latency.

BASH
curl --verbose --max-time 5 http://127.0.0.1:8080/health
sudo ss -lntp
sudo tail -n 80 /var/log/nginx/error.log
sudo journalctl -u nginx -n 50 --no-pager
sudo nginx -T

Connection refused involves listeners or rejects. Permission denied might involve sockets or AppArmor. Capture nginx -T only in protected locations. Extending timeouts without investigating latency increases request queues.

Roll back the virtual host and reload

Protect configuration, keys and chains. Roll back by restoring the prior file, validating with nginx -t and reloading. For an initial deployment, remove only the new symlink. Application data/databases need separate backups.

Acceptance after reload

After reload, test from the actual client path: valid syntax, a trusted certificate and the expected health response are three separate conditions. Successful reload or an active Nginx service establishes only part of that path. Evaluate worker and rate-limit settings under real traffic so users receive the tested backend behavior.

Best Practices

  • Version-control configuration and review changes.
  • Use least privilege and explicit allow-lists.
  • Automate repeatable checks and monitor the expected state.
  • Test upgrades and restores before production rollout.

Conclusion

A reliable implementation of Install Nginx on Ubuntu and Configure a TLS Reverse Proxy is more than a successful first run. Keep the configuration documented, observable, recoverable, and aligned with the team's change-management process.

Frequently Asked Questions

Does nginx -t verify application health?

No. It validates configuration. Application health needs a separate check.

Should a 504 be fixed by increasing the timeout?

Inspect upstream latency and dependencies first. A longer timeout can increase queueing.

Official Sources

Share

Meet AJInfrastructure & DevOps
Loading…