Setup Nginx Reverse Proxy with Let's Encrypt SSL
Secure your applications with free HTTPS certificates using Certbot and configure Nginx to act as a reverse proxy for apps running on internal ports (like 8000 or 8501).
Install Nginx & Certbot
First, ensure your server has the web server and the certificate management tool installed.
For Amazon Linux / CentOS / RHEL:
sudo yum update -y
sudo yum install nginx certbot python3-certbot-nginx -y
sudo systemctl start nginx
sudo systemctl enable nginxFor Ubuntu / Debian:
sudo apt update
sudo apt install nginx certbot python3-certbot-nginx
sudo systemctl start nginxA list of installed packages will appear upon completion.
The "Chicken & Egg" Configuration
You cannot configure Nginx for SSL/HTTPS immediately because the certificates don't exist yet. Nginx will crash if you reference missing files.
The Strategy: Create a simple HTTP (Port 80) config first -> Run Certbot -> Then add the full Proxy/SSL config.
Create a new configuration file for your domain:
sudo nano /etc/nginx/conf.d/myapp.confPaste this temporary configuration:
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
location / {
# Just a placeholder for validation
root /usr/share/nginx/html;
index index.html;
}
}Replace yourdomain.com with your actual domain.
Reload Nginx to apply changes:
sudo nginx -t && sudo systemctl reload nginxObtain the Certificate
Now that Port 80 is open and listening for your domain, Certbot can verify ownership.
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.comFollow the prompts. When asked to redirect HTTP traffic to HTTPS, select Yes (2). Certbot will automatically modify your config file to add the SSL paths.
Configure the Reverse Proxy
Now we modify the file one last time to forward traffic to your running application (e.g., Streamlit on port 8501 or FastAPI on 8000).
sudo nano /etc/nginx/conf.d/myapp.confOption A: For Streamlit Apps (Port 8501)
Streamlit requires special headers for WebSockets.
# INSIDE THE server { listen 443 ssl ... } BLOCK
location / {
proxy_pass http://localhost:8501;
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;
}Option B: For Standard Apps (Port 8000/3000)
For FastAPI, Node.js, or Flask.
# INSIDE THE server { listen 443 ssl ... } BLOCK
location / {
proxy_pass http://localhost:8000;
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;
}Final Test & Reload:
sudo nginx -t && sudo systemctl reload nginxAutomate Renewal
Let's Encrypt certificates expire every 90 days. Set up a cron job to renew them automatically.
sudo crontab -eAdd this line to the bottom of the file:
0 0 * * * certbot renew --nginx --quietThis checks for renewal eligibility every day at midnight.
Troubleshooting
If you see a "502 Bad Gateway" error, it means your application (Streamlit/FastAPI) isn't running.
Check if it's active with: sudo lsof -i :8501 or ensure you used nohup to keep it running in the background.