Nginx reverse proxy
Rather than exposing port 3000 or 8080 on the Internet, have Nginx listen on 80/443 and forward traffic to your local application. Standard pattern on a HolyCloud Linux VPS hosting APIs, panels, or Docker containers.
Prerequisites
- Nginx installed (
apt install nginx) - Application listening locally (e.g.
127.0.0.1:3000) - Domain name and TLS certificate (see « Nginx and Certbot ») recommended
- UFW: only 80/443 public
Step 1: example backend application
# Exemple : conteneur sur le port 3000
docker run -d --name app -p 127.0.0.1:3000:3000 votre-image:tag
curl -sI http://127.0.0.1:3000
The application should be reachable on localhost only when possible.
Step 2: reverse proxy configuration
sudo nano /etc/nginx/sites-available/app.example.com
upstream app_backend {
server 127.0.0.1:3000;
keepalive 32;
}
server {
listen 80;
listen [::]:80;
server_name app.example.com;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name app.example.com;
# Chemins Certbot — adaptez si nécessaire
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
location / {
proxy_pass http://app_backend;
proxy_http_version 1.1;
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_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 90s;
}
}
Enable the site:
sudo ln -sf /etc/nginx/sites-available/app.example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
Step 3: multiple services (paths)
location /api/ {
proxy_pass http://127.0.0.1:4000/;
}
location / {
proxy_pass http://127.0.0.1:3000/;
}
Watch the trailing slash on proxy_pass to keep or strip the /api prefix.
Step 4: limits and logs
sudo nano /etc/nginx/nginx.conf
In the http block, adjust if needed:
client_max_body_size 50M;
Per-site logs: access_log /var/log/nginx/app.example.com.access.log;
Verification
curl -sI https://app.example.com
curl -s https://app.example.com/health
sudo tail -f /var/log/nginx/error.log
From outside, port 3000 must not be reachable:
sudo ufw status | grep 3000
Need help?
- 502 Bad Gateway: backend stopped or wrong port —
curl http://127.0.0.1:3000,docker ps - WebSocket drops: check
Upgrade/Connectionheaders - Support:
nginx -t, vhost excerpt (no private key), container/service status