Skip to content

Instantly share code, notes, and snippets.

@ZainUrRehmanKhan
Forked from bradtraversy/node_nginx_ssl.md
Last active April 25, 2024 07:27
Show Gist options
  • Select an option

  • Save ZainUrRehmanKhan/c61f5694917f95a41c1222af5238d1b7 to your computer and use it in GitHub Desktop.

Select an option

Save ZainUrRehmanKhan/c61f5694917f95a41c1222af5238d1b7 to your computer and use it in GitHub Desktop.
Node app deployment - nginx - SSL - Docker - mongo - swap memory - muti tenant nginx config - firewall

Node.js Deployment

Steps to deploy a Node.js app to DigitalOcean using PM2, NGINX as a reverse proxy and an SSL from LetsEncrypt

1. Sign up for Digital Ocean

2. Create a droplet (Select Ubuntu 20.04) and log in via ssh

I will be using the root user, but would suggest creating a new user https://www.digitalocean.com/community/tutorials/how-to-configure-ssh-key-based-authentication-on-a-linux-server

Run this command on the remote server:

ssh-keygen -t rsa

Run this command on your local machine:

ssh-copy-id username@host

- Install docker

https://docs.docker.com/engine/install/ubuntu/

- Install mongodb

https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-ubuntu/

If mongodb stops working on changing the configuration: https://askubuntu.com/questions/823288/mongodb-loads-but-breaks-returning-status-14

- Apply Auth on mongodb

use admin
db.createUser(
  {
    user: "useradmin",
    pwd: "password",
    roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
  }
)
db.grantRolesToUser('useradmin', [{ role: 'root', db: 'admin' }])
sudo nano /etc/mongod.conf
security:
  authorization: enabled
sudo systemctl restart mongod

For Issue after applying auth

sudo chown -R mongodb:mongodb /var/lib/mongodb
sudo chown mongodb:mongodb /tmp/mongodb-27017.sock
sudo systemctl restart mongod

3. Install Node/NPM

curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -

sudo apt install nodejs

node --version

4. Clone your project from Github

There are a few ways to get your files on to the server, I would suggest using Git

git clone yourproject.git

5. Install dependencies and test app

cd yourproject
npm install
npm start (or whatever your start command)
# stop app
ctrl+C

6. Setup PM2 process manager to keep your app running

sudo npm i pm2 -g
pm2 start app (or whatever your file name)

# Other pm2 commands
pm2 show app
pm2 status
pm2 restart app
pm2 stop app
pm2 logs (Show log stream)
pm2 flush (Clear logs)

# To make sure app starts when reboot
pm2 startup ubuntu

You should now be able to access your app using your IP and port. Now we want to setup a firewall blocking that port and setup NGINX as a reverse proxy so we can access it directly using port 80 (http)

7. Setup ufw firewall

sudo ufw enable
sudo ufw status
sudo ufw allow ssh (Port 22)
sudo ufw allow http (Port 80)
sudo ufw allow https (Port 443)

8. Install NGINX and configure

sudo apt install nginx

sudo nano /etc/nginx/sites-available/default

Add the following to the location part of the server block

    server_name yourdomain.com www.yourdomain.com;

    location / {
        proxy_pass http://localhost:5000; #whatever port your app runs on
        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;
    }

Increase Max File upload size

# go to niginx.conf
nano /etc/nginx/nginx.conf

#put this line in the http section
client_max_body_size 100M;

Restart nginx

# Check NGINX config
sudo nginx -t

# Restart NGINX
sudo service nginx restart

You should now be able to visit your IP with no port (port 80) and see your app. Now let's add a domain

9. Add domain in Digital Ocean

In Digital Ocean, go to networking and add a domain

Add an A record for @ and for www to your droplet

Register and/or setup domain from registrar

I prefer Namecheap for domains. Please use this affiliate link if you are going to use them https://namecheap.pxf.io/c/1299552/386170/5618

Choose "Custom nameservers" and add these 3

  • ns1.digitalocean.com
  • ns2.digitalocean.com
  • ns3.digitalocean.com

It may take a bit to propogate

Add SSL with LetsEncrypt

Install snapd: sudo apt install snapd

Ensure you have the latest snapd version installed: sudo snap install core; sudo snap refresh core

Install Certbot with snapd: sudo snap install --classic certbot

Create a symlink to ensure Certbot runs:

sudo certbot --nginx --redirect -d yourdomain.com -d www.yourdomain.com

Only valid for 90 days, test the renewal process with

certbot renew --dry-run

or

sudo certbot --nginx --redirect -d api.domain.com -v

https://samholst.com/blog/2017/10/14/nginx-ssl-lets-encrypt-auto-renew-setup

Add SSL with LetsEncrypt for Multi tenant app

Update certbot

   sudo apt-get update; sudo apt-get install certbot

Try insalling, ingore if error

sudo apt install certbot python3-certbot-dns-manual

Use this command to apply SSL on wildcard domain, this setup will ask you to add a TXT record in the DNS

sudo certbot certonly --manual --preferred-challenges=dns --server https://acme-v02.api.letsencrypt.org/directory --agree-tos --redirect -d *.domain.com

To apply SSL on a specific subdomain use

sudo certbot certonly --manual -d api.domain.com

You will get a token which you need to server on the web server, add this location in the server config of the subdomain

location ^~ /.well-known/acme-challenge/ {
        allow all;
        root /var/www/html;
        try_files $uri =404;
    }

create a file with the given name on path /var/www/html/.well-known/acme-challenge/filename and paste the file the given token.

Now apply the SSL and redirection config manually in nginx

listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/cloudwaiver.com-0001/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/cloudwaiver.com-0001/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

Enable Swap on ubuntu

https://www.digitalocean.com/community/tutorials/how-to-add-swap-space-on-ubuntu-20-04

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment