Skip to main content

Configure a Reverse Proxy

This guide explains how to set up a reverse proxy with Nginx or Traefik on your VPS.

What is a Reverse Proxy?​

A reverse proxy is a server that sits in front of your applications and redirects traffic to them. Benefits:

  • Single entry point for multiple applications
  • Centralized SSL/HTTPS
  • Different domain names for each service
  • Load balancing if needed

Option 1: Nginx​

Installation​

sudo apt update
sudo apt install nginx

Basic Configuration​

Create a configuration file for your site:

sudo nano /etc/nginx/sites-available/my-app

Proxy to a Local Application​

server {
listen 80;
server_name my-app.example.com;

location / {
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_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;
proxy_cache_bypass $http_upgrade;
}
}

Enable the Site​

sudo ln -s /etc/nginx/sites-available/my-app /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Add SSL with Let's Encrypt​

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d my-app.example.com

Multi-Application Example​

# Application 1 - api.example.com
server {
listen 80;
server_name api.example.com;

location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

# Application 2 - dashboard.example.com
server {
listen 80;
server_name dashboard.example.com;

location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

Option 2: Traefik (with Docker)​

Traefik is ideal if you use Docker because it automatically detects containers.

docker-compose.yml for Traefik​

version: '3.8'

services:
traefik:
image: traefik:v3.0
command:
- "--api.dashboard=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.letsencrypt.acme.email=your@email.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
labels:
- "traefik.enable=true"
- "traefik.http.routers.dashboard.rule=Host(`traefik.example.com`)"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$xyz..."
restart: unless-stopped

# Example application
whoami:
image: traefik/whoami
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`whoami.example.com`)"
- "traefik.http.routers.whoami.entrypoints=websecure"
- "traefik.http.routers.whoami.tls.certresolver=letsencrypt"
restart: unless-stopped

Add an Application with Traefik​

  my-app:
image: my-image
labels:
- "traefik.enable=true"
- "traefik.http.routers.my-app.rule=Host(`app.example.com`)"
- "traefik.http.routers.my-app.entrypoints=websecure"
- "traefik.http.routers.my-app.tls.certresolver=letsencrypt"
- "traefik.http.services.my-app.loadbalancer.server.port=3000"

Nginx vs Traefik Comparison​

CriteriaNginxTraefik
ConfigurationManual filesDocker auto-discovery
SSLSeparate CertbotBuilt-in
Reloadnginx reloadAutomatic
Web interfaceNo (except plugins)Dashboard included
Ideal forTraditional serversDocker environments

HTTP to HTTPS Redirect​

With Nginx​

server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}

With Traefik​

- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
Tip

For Docker environments, prefer Traefik. For traditional servers, Nginx remains the reference.