I'm running a development server on Ubuntu 14.04 LTS with multiple services hosted on different ports. To simplify access, I've configured Nginx as a reverse proxy to route traffic based on hostnames rather than port numbers. For example:
upstream sub {
server 127.0.0.1:7547;
}
server {
listen 80;
server_name sub.domain.com www.sub.domain.com;
access_log /var/log/nginx/sub.log combined;
location / {
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_pass http://127.0.0.1:7547;
proxy_set_header Authorization "";
}
}
Now I want to secure these services with Let's Encrypt SSL certificates while maintaining this proxy structure.
First, install Certbot and the Nginx plugin:
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot python-certbot-nginx
For a single subdomain:
sudo certbot --nginx -d sub.domain.com -d www.sub.domain.com
For multiple subdomains (more efficient):
sudo certbot --nginx -d sub1.domain.com -d sub2.domain.com -d sub3.domain.com
Here's how to modify your existing configuration for SSL:
server {
listen 443 ssl;
server_name sub.domain.com www.sub.domain.com;
ssl_certificate /etc/letsencrypt/live/sub.domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sub.domain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:7547;
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;
}
}
server {
listen 80;
server_name sub.domain.com www.sub.domain.com;
return 301 https://$host$request_uri;
}
Add this to your crontab (sudo crontab -e):
0 12 * * * /usr/bin/certbot renew --quiet
If you need to use webroot authentication (for services not directly served by Nginx):
sudo certbot certonly --webroot -w /var/www/html -d sub.domain.com
Then manually configure Nginx to use the certificate as shown above.
Check your configuration:
sudo nginx -t
Test SSL configuration:
openssl s_client -connect sub.domain.com:443 -servername sub.domain.com
Check certificate expiration:
sudo certbot certificates
I'm running a development environment on Ubuntu 14.04 with multiple services exposed through an Nginx reverse proxy configuration. Here's a typical setup for one of my subdomains:
upstream service_x {
server 127.0.0.1:7547;
}
server {
listen 80;
server_name x.domain.com www.x.domain.com;
access_log /var/log/nginx/x.log combined;
location / {
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_pass http://service_x;
proxy_set_header Authorization "";
}
}
To secure these subdomains with HTTPS, we'll use Certbot, the official Let's Encrypt client. First, install Certbot and the Nginx plugin:
sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-nginx
For a single subdomain (x.domain.com), run:
sudo certbot --nginx -d x.domain.com -d www.x.domain.com
For multiple subdomains in one command:
sudo certbot --nginx \
-d x.domain.com -d www.x.domain.com \
-d y.domain.com -d www.y.domain.com \
-d z.domain.com -d www.z.domain.com
After running Certbot, your configuration will automatically be updated. Here's what the HTTPS version looks like:
server {
listen 443 ssl;
server_name x.domain.com www.x.domain.com;
ssl_certificate /etc/letsencrypt/live/x.domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/x.domain.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/x.domain.com/chain.pem;
access_log /var/log/nginx/x.log combined;
location / {
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_pass http://service_x;
proxy_set_header Authorization "";
}
}
server {
listen 80;
server_name x.domain.com www.x.domain.com;
return 301 https://$host$request_uri;
}
Let's Encrypt certificates expire every 90 days. Add this cron job for automatic renewal:
0 12 * * * /usr/bin/certbot renew --quiet
If you need to use webroot authentication instead of the Nginx plugin:
sudo certbot certonly --webroot -w /var/www/html \
-d x.domain.com -d www.x.domain.com \
--email admin@domain.com --agree-tos
For improved security, add these SSL parameters to your Nginx config:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384...';
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_stapling on;
ssl_stapling_verify on;