How to setup NGINX reverse proxy for application server dev and prod setup with Let’s Encrypt SSL certificate on Ubuntu 18.04
Reading Time:
Reading Time:
Assume we have two app servers running on port 8181 and 8080 Prod on 8080 and dev on 8181
We want to redirect
http --> https --> localhost
http://prod.example.com --> https://prod.example.com --> localhost:8080
http://dev.example.com --> https://dev.example.com --> localhost:8181
Connect to your Ubuntu box via SSH and run the following command on terminal
sudo apt update
sudo apt install nginx
Ubuntu Firewall setup for Nginx HTTPS and HTTP
sudo ufw status
To Action From
-- ------ ----
22 ALLOW Anywhere
22 (v6) ALLOW Anywhere (v6)
sudo ufw allow 'Nginx HTTPS'
sudo ufw allow 'Nginx HTTP'
sudo ufw status
To Action From
-- ------ ----
22 ALLOW Anywhere
Nginx HTTPS ALLOW Anywhere
Nginx HTTP ALLOW Anywhere
22 (v6) ALLOW Anywhere (v6)
Nginx HTTPS (v6) ALLOW Anywhere (v6)
Nginx HTTP (v6) ALLOW Anywhere (v6)
Check if nginx is running and make sure nginx auto starts on reboot by enabling nginx service
sudo systemctl start nginx
sudo systemctl enable nginx
Check status
sudo systemctl status nginx
In console we would see
nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: e
Active: active (running) since Mon 2019-05-13 13:02:22 UTC; 25min ago
Main PID: 613 (nginx)
CGroup: /system.slice/nginx.service
├─613 nginx: master process /usr/sbin/nginx -g daemon on; master_pro
├─614 nginx: worker process
└─615 nginx: worker process
May 13 13:02:22 ubuntu-sb-blr1-01 systemd[1]: Starting A high performance web s
May 13 13:02:22 ubuntu-sb-blr1-01 systemd[1]: Started A high performance web se
May 13 13:24:28 ubuntu-sb-blr1-01 systemd[1]: Started A high performance web se
lines 1-12/12 (END)
In case you get an error then try the below command to make sure there is no service running on port 80 or 443 . Refer Stackoverflow
Try to run the following two commands:
sudo fuser -k 80/tcp
sudo fuser -k 443/tcp
Enter the http url in your browser's address bar
and you should see the welcome to nginx page , if you dont see the page then check firewall settings on you cloud service provider system
Automatically enable HTTPS on your website with EFF's Certbot, deploying Let's Encrypt certificates. Visit https://certbot.eff.org/ for more information
Certbot has an Nginx plugin, which is supported on many platforms, and automates certificate installation.
Certbot helps us fetch the SSL certificate from Let's Encrypt server from cmd prompt , so lets go ahead and install it
sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot python-certbot-nginx
We use the Certbot nginx plugin to obtain SSL certificate
Now run the certbot command to get the SSL certificate for our domain and auto install it on nginx under the ‘server_name dev.example.com and prod.example.com server block for port 443 and 80
sudo certbot --nginx -d dev.example.com -d prod.example.com
Follow the instructions in the terminal to get the SSL certificate from 'Let's Encrypt'
Chose Option 2 : Auto redirect HTTP to HTTPS
Certbot would have updated the file
/etc/nginx/sites-enabled/default
The lines added by certbot shown below
server {
# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name prod.example.com dev.example.com; # managed by Certbot
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# include snippets/fastcgi-php.conf;
#
# # With php7.0-cgi alone:
# fastcgi_pass 127.0.0.1:9000;
# # With php7.0-fpm:
# fastcgi_pass unix:/run/php/php7.0-fpm.sock;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/dev.example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/dev.example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = prod.example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = dev.example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 ;
listen [::]:80 ;
server_name prod.example.com dev.example.com;
return 404; # managed by Certbot
}
Enter the http url in your browser's address bar
It will get redirected to https (443 port)
We want to forward
dev.example.com → localhost:8181
prod.example.com → localhost:8080
We need to modify file /etc/nginx/sites-enabled/default
server {
server_name prod.example.com ;
location / {
include /etc/nginx/proxy_params;
proxy_pass http://localhost:8080;
proxy_read_timeout 90s;
}
listen [::]:443 ssl; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/dev.example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/dev.example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
server_name dev.example.com ;
location / {
include /etc/nginx/proxy_params;
proxy_pass http://localhost:8181;
proxy_read_timeout 90s;
}
listen [::]:443 ssl; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/dev.example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/dev.example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = prod.example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = dev.example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 ;
listen [::]:80 ;
server_name prod.example.com dev.example.com;
return 404; # managed by Certbot
}
Verify the nginx conf file for any syntax issue
nginx -t
Note : If we get an error during ‘nginx -t’ command then remove 'ipv6only=on' section , it is a bug in nginx . Cerbot adds that to nginx ipv6 ssl line by default
listen [::]:443 ssl ipv6only=on; # managed by Certbot
modify it as
listen [::]:443 ssl; # managed by Certbot
On 'nginx -t' we will see this in the console
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Run the command to restart nginx
sudo systemctl reload nginx
sudo systemctl restart nginx
When we point our browser to http://dev.example.com it redirects to https then to dev server running on port 8181 and when we point to http://prod.example.com it redirects to https then to prod server running on port 8080