Nginx reverse proxy Expose a backend application (Node, Docker, etc.) behind Nginx on your HolyCloud VPS with proxy headers and WebSocket. ~12 min read Intermediate #nginx #reverse-proxy #docker #websocket 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 / Connection headers Support: nginx -t, vhost excerpt (no private key), container/service status Continue reading Previous article Nginx and Certbot (Let's Encrypt) Read Next article Nginx static cache Read