Skip to main content
A reverse proxy sits between the internet and your Email Tracker Node.js server, handling TLS termination and forwarding requests.

Architecture

The reverse proxy:
  • Listens on ports 80 (HTTP) and 443 (HTTPS)
  • Obtains and manages SSL/TLS certificates
  • Terminates HTTPS connections
  • Forwards requests to the Node.js server on localhost

Configuration examples

Both configurations below are production-ready and come from the Email Tracker repository.
Caddy automatically obtains and renews Let’s Encrypt certificates. This is the simplest option.

Install Caddy

Caddyfile configuration

Create or edit /etc/caddy/Caddyfile:
Replace email-tracker.duckdns.org with your domain.

Start Caddy

Caddy will automatically:
  • Obtain a Let’s Encrypt certificate for your domain
  • Redirect HTTP to HTTPS
  • Renew certificates before expiration
  • Proxy requests to your Node.js server

Verify configuration

Check Caddy status:
Test the configuration:

Configuration details

Port forwarding

Both configurations:
  • Listen on port 443 for HTTPS traffic
  • Forward requests to 127.0.0.1:8090 (your Node.js server)
  • The Node.js server only needs to listen on localhost
Never expose the Node.js server directly to the internet. Always use a reverse proxy for TLS termination and security.

HTTP to HTTPS redirect

  • Caddy: Automatic redirect from HTTP to HTTPS
  • Nginx: Explicit return 301 in the port 80 server block
This ensures all traffic uses HTTPS, which is required for email tracking.

Compression

  • Caddy: encode gzip compresses responses
  • Nginx: Add gzip on; to enable compression (optional)
Compression reduces bandwidth usage for dashboard pages.

Headers forwarded to Node.js

The Nginx configuration forwards important headers:
  • Host: Original domain name
  • X-Real-IP: Client’s IP address
  • X-Forwarded-For: Full proxy chain
  • X-Forwarded-Proto: Original protocol (https)
These headers allow the Node.js server to see the client’s real IP address and know the request came via HTTPS.

Testing your setup

1. Check TLS certificate

Verify:
  • Certificate is valid
  • Issuer is Let’s Encrypt (or your CA)
  • Not expired

2. Test HTTP redirect

Should return 301 Moved Permanently with Location: https://...

3. Test HTTPS endpoint

Should return {"status":"ok"}

4. Test tracking pixel

Should return 200 OK with content-type: image/gif

Troubleshooting

Certificate errors

Problem: Browser shows “Your connection is not private” Solutions:
  • Verify DNS points to correct server
  • Check certificate was obtained for correct domain
  • Ensure certificate files exist at specified paths
  • Restart reverse proxy service

502 Bad Gateway

Problem: Nginx/Caddy returns 502 error Solutions:
  • Verify Node.js server is running: curl http://127.0.0.1:8090/health
  • Check port number matches in reverse proxy config and Node.js
  • Review reverse proxy error logs
  • Ensure no firewall blocking localhost connections

Certificate renewal fails

Problem: Let’s Encrypt certificate expires Solutions:
  • Ensure ports 80 and 443 are accessible from internet
  • Check DNS points to correct server
  • Review Certbot/Caddy logs for renewal errors
  • Manually renew: sudo certbot renew (Nginx) or sudo systemctl restart caddy (Caddy)

Advanced configuration

Rate limiting

Protect your server from abuse:

Custom SSL settings

For stricter security or compatibility:

Next steps