Try โ€‚โ€‰HackMD
tags: web certbot docker nginx

Deploy node SSL DNS server on VPS using Docker & Nginx

In this article, we are going to deploy a production server that we created on docker section

The flow will like below:

  1. Runing the docker application on port 3000 (this one is already done on previous section)
  2. Start very first Nginx server on VPS
  3. Apply for a Doman and direct it to our VPS public IP
  4. Use certbot to create a SSL certification
  5. Config Nginx

Below is the overall idea of this application

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More โ†’

Nginx startup

Nginx is going to listen on 80 port as an reverse proxy. When it gets certain request, it will transfer it to the responsible port service.
In this case, when a user accesses https://www.colorfullife.ml, Nginx will transfer it to localhost:3000 port in which our node server is located.

Installation

apt install nginx

Basic config

cd into /etc/nginx/sites-available and then touch one more file called colorfullife.ml

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    root /var/www/html;
    server_name colorfullife.ml www.colorfullife.ml;
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Then reload the nginx server by

sudo systemctl reload nginx

When try to access the public IP address of our VPS, we can see the nginx welcome page.

The DNS (Domain Name Service) setting

Firstly, we need to have a Domain name. We register one from freenom called "colorfullife.ml".

We then direct the Aname in the DNS config page to our VPS public IP

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More โ†’

Then when we enter the url with our domain, we can see the same nginx welcome page. It means the DNS successfully resolve the url to our public ip address.

Register SSL (HTTPS) with certbot

Now we need to make the access secured by adding SSL certification to allow https protocol access.

We are making use of "certbot" package.

Certbot installation

sudo apt-get install certbot
sudo apt-get install python3-certbot-nginx

And we can obtaining an SSL Certificate for our domain url
Reference doc: How To Secure Nginx with Let's Encrypt on Ubuntu 18.04
sudo certbot --nginx -d www.colorfullife.ml

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More โ†’

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More โ†’

Now we can see the same nginx welcome page using "https"

Final proxy reverse setting

Now we need to route the request when nginx gets the request from "https://www.colorfullife.ml"

server {
	listen 80 default_server;
	listen [::]:80 default_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 _;

	location / {
		# First attempt to serve request as file, then
		# as directory, then fall back to displaying a 404.
		#try_files $uri $uri/ =404;
		proxy_pass http://localhost:3000;
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection 'upgrade';
		proxy_set_header Host $host;
		proxy_cache_bypass $http_upgrade;	
	}

	# pass PHP scripts to FastCGI server
	#
	#location ~ \.php$ {
	#	include snippets/fastcgi-php.conf;
	#
	#	# With php-fpm (or other unix sockets):
	#	fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
	#	# With php-cgi (or other tcp sockets):
	#	fastcgi_pass 127.0.0.1:9000;
	#}

	# deny access to .htaccess files, if Apache's document root
	# concurs with nginx's one
	#
	#location ~ /\.ht {
	#	deny all;
	#}
}


# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
#	listen 80;
#	listen [::]:80;
#
#	server_name example.com;
#
#	root /var/www/example.com;
#	index index.html;
#
#	location / {
#		try_files $uri $uri/ =404;
#	}
#}

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 www.colorfullife.ml; # 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;
		proxy_pass http://localhost:3000;
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection 'upgrade';
		proxy_set_header Host $host;
		proxy_cache_bypass $http_upgrade;
	}

	# pass PHP scripts to FastCGI server
	#
	#location ~ \.php$ {
	#	include snippets/fastcgi-php.conf;
	#
	#	# With php-fpm (or other unix sockets):
	#	fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
	#	# With php-cgi (or other tcp sockets):
	#	fastcgi_pass 127.0.0.1:9000;
	#}

	# 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/www.colorfullife.ml/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/www.colorfullife.ml/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 = www.colorfullife.ml) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


	listen 80 ;
	listen [::]:80 ;
    server_name www.colorfullife.ml;
    return 404; # managed by Certbot


}

Everything is done, we can access our docker container application by accessing "https://www.colorfullife.ml"

Update 2022/4/17

After reading through the official doc, I realized that directly modifying sites-availale/default is not a recommanded apporach

In most cases, administrators will remove this file from sites-enabled/ and leave it as reference inside of sites-available where it will continue to be updated by the nginx packaging team.

So, we need to classify our structure a bit.

Firstly comment out all the content in sites-available/default.
Secondly, I realized that actually the colorfullife.ml file in sites-aviable/ has not been used at all.
Lets change the name more explicitly (www.colorfullife.ml) and also change the content

server {
        root /var/www/html;

        index index.html index.htm index.nginx-debian.html;
        server_name services.dev-eric.ml; # managed by Certbot


        location / {
                proxy_pass http://localhost:3000;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection 'upgrade';
                proxy_set_header Host $host;
                proxy_cache_bypass $http_upgrade;
        }
    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/services.dev-eric.ml/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/services.dev-eric.ml/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
}

Only changing the content will not enable this setting.
We will need to link this file to sites-enabled to enable this config.
So, cd into the sites-enabled/ and run following command

sudo ln -s ../sites-available/www.colorfullife.ml

And then we can see there is symbolic link with the same name (www.colrfullife.ml) is created into sites-enabled/.
It mean the config in sites-available/www.colorfullife.ml has been enabled.
After reloading the nginx service, and access www.colorfullife.ml, it will be working as before.

NOTE

According to the document, The reason to make this classification is making the site control more systematic. We can disable or enable certain proxy or site by just create a symboic link. Else disable by remove the symboic link.