###### 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](https://hackmd.io/@happyeric77/HJE2oRyV5) The flow will like below: 1. Runing the docker application on port 3000 (this one is already done on [previous section](https://hackmd.io/@happyeric77/HJE2oRyV5)) 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 ![](https://i.imgur.com/Zvwbzxk.png) ## 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 ![](https://i.imgur.com/vFqycV4.png) 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](https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-18-04) ``` sudo certbot --nginx -d www.colorfullife.ml ``` ![](https://i.imgur.com/nnazkUJ.png) ![](https://i.imgur.com/VI3SHCN.png) 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.