Skip to content

Instantly share code, notes, and snippets.

@carlssonk
Last active February 18, 2024 16:38
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save carlssonk/97d474045e69f8e394ed23f91695f56e to your computer and use it in GitHub Desktop.
Save carlssonk/97d474045e69f8e394ed23f91695f56e to your computer and use it in GitHub Desktop.
Deploy node.js app to DigitalOcean

Deploy Node.js Application to DigitalOcean

This step by step tutorial will show you how to set up a Node.js server with MongoDB to DigitalOcean using PM2, NGINX as reverse proxy and a SSL from LetsEncrypt. We will also add a custom domain name.

Prerequisites

Create Droplet & Generate SSH Key

  1. Create New Project/Create New Droplet
  2. Choose Ubuntu, Choose your desired plan & country
  3. Click on New SSH Key
  4. Open PuTTyGen and generate a new RSA Key
  5. Copy the key in the input field and add it to your droplet, Add SSH Key
  6. IMPORTANT Be sure to save the public key as .txt and your private key as .ppk on your computer, you will need these later
  7. Create Droplet

Configure PuTTY

  1. Open PuTTY
  2. Add your droplets IP Adress to 'Host Name (or IP Adress)'
  3. In Connection -> Data, set username to "root"
  4. In SSH -> Auth, load your privatekey.ppk that you created from last step
  5. Set a session name and SAVE

Create New User

  1. Login to your server, click yes if first time connecting to server

  2. Add user and assign him to the sudo group:

adduser [username]
usermod -aG sudo [username]

You can check to make sure that user was added in sudo group id [username]

  1. Login as that user:
sudo su - [username]

Authorize Key For New User

  1. Make new directory:
mkdir ~/.ssh
  1. Change permission:
chmod 700 ~/.ssh
  1. Create and go into new file:
nano ~/.ssh/authorized_keys
  1. Copy ssh key from publickey.txt (exclude "Comment: rsa-key-date") Inside authorized_keys on the first line type: "ssh-rsa" space and add your key, also make everything in one line.

    It should look something like this now: “ssh-rsa AAAABaxASDVAV17547DFDVGDVG...”

    Save file: Ctrl+X & Y

  2. Set permission for that file:

chmod 600 ~/.ssh/authorized_keys
  1. Restart service:
sudo service ssh restart
  1. Exit terminal and login as new user. Load config, click Data and change root to your [username].

Ensure everything is up to date

Update packages

sudo apt update

Disable Root & Password Login AND Change SSH-port

Disable Root & Password Login

  1. Go into ssh config file:
sudo nano /etc/ssh/sshd_config
  1. Search for PermitRootLogin: Ctrl+W and type "PermitRootLogin"
  2. Set PermitRootLogin to "no"
  3. Search for PasswordAuthentication: Ctrl+W and type "PasswordAuthentication"
  4. Set PasswordAuthentication to "no"

Change SSH-port

A lot of attacks on web servers occur by scripts trying to get into the default port for SSH, port 22. Therefore, we change this, feel free to take a five-digit port (difficulty guessing), but not higher than 65535. (Also: Note the number should not start with 0.)

  1. Find the row Port 22 and change it to another port, eg. XXXXX
    Important: Make sure to remember the Port you changed to
# If the row start with a '#' you should remove it
# Ex.
Port 25565

Save file: Ctrl+X & Y
7. Reboot session:

reboot
  1. Close terminal and open PuTTY
  2. Now in the port input, type in your new port

Note that if you try to open the terminal with another port like 22 you will get a "connection refused error".

  1. Save and open terminal

Enable Firewall

Note: to enable firewall you need to be on the root user. Type sudo -i or sudo -s to switch to the root user
Type su - [username] to switch back to your user after enabling firewall

  1. Enable firewall, ssh, http & https:
ufw enable
ufw allow ssh
ufw allow http
ufw allow https
ufw allow XXXXX # the port you choosed earlier

To check your firewall status: ufw status 2. Reboot session and connect again to make sure everything is working:

reboot

Install Node.js & Npm

  1. Install latest version of nodejs:

Note: this is version 14 we are installing, check nodejs homepage and see if there is a newer version, pick the one that says recommended for most users, and change "14" in this command to the new version

curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
  1. Install nodejs & npm:
sudo apt-get install nodejs

You can make sure they are installed: "npm -v" and "node -v"

NGINX

  1. Install nginx:
sudo apt install nginx
  1. Go into default folder:
sudo nano /etc/nginx/sites-available/default
  1. Remove everything inside the location brackets and add proxies:
location / {
	
	proxy_pass http://localhost:8080; #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;
	
}

Note: if localhost does not work use ip address from your droplet.

  1. Above the location we have server_name_;. Set the server name to your domain name if you want to use a domain name for this app. It should look like this server_name mywebsite.com www.mywebsite.com
  2. Exit and save: Ctrl+X & Y
  3. Check so nginx is configured properly sudo nginx -t. It should say something like the test is successful
  4. Now restart the service sudo service nginx restart

Install MongoDB

sudo apt install -y mongodb

After install mongodb should be running To check status of db: systemctl status mongodb
Commands to start, stop and restart the database

systemctl stop mongodb
systemctl start mongodb
systemctl restart mongodb

Generate SSH key & add it to GitHub

Generating SSH key for github

  1. Create ssh key for github:
ssh-keygen -t ed25519 -C "your@githubemail.com"
  1. When you're prompted to "Enter a file in which to save the key," press Enter. This accepts the default file location.

Adding your SSH key to the ssh-agent

  1. Ensure the ssh-agent is running.
eval "$(ssh-agent -s)"
  1. Add your SSH private key to the ssh-agent.
ssh-add ~/.ssh/id_ed25519

Adding your SSH key to GitHub

  1. copy SSH key that you just created:
cd .ssh
cat id_ed25519.pub

copy the output including email

  1. Go to GitHub > Settings > SSH and GPG Keys
  2. Click "New SSH Key"
  3. Paste the SSH key in the input box

IF YOU ARE STUCK generating SSH key and adding it to GitHub. Follow these steps: https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent

https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account

Clone App from github

If your project is not on github, upload it to github so we can clone it to your droplet

  1. Make sure you are standing on root:
cd
  1. Go into /var/www
cd /var/www

You can remove default html folder if you want "sudo rm -fr html"

  1. Clone app from GitHub
sudo git clone git@github.com:user/your-repository.git
  1. if this gives permission error clone from HTTPS instead
  2. type ls and boom your project is there
  3. cd into your projext and type npm install to install all packages that your project contains

Install PM2

  1. Install pm2 globally:
sudo npm install -g pm2
  1. Start server: pm2 start index.js or pm2 start npm -- start
  2. App should now be running on the droplets ip adress:

ex.165.227.216.5:8080

Add domain

  1. First buy your domain through preferred service: ex, namecheap, godaddy.
  2. Then in DigitalOcean go to the networking tab and add your domain
  3. Where it says HOSTNAME you will add a "@" and at WILL DIRECT TO you want to put your droplet
  4. Click on Create Record.

The record you are creating is "A"

  1. Create a Record for the www version, so do the same but replace "@" with "www"
  2. Go to your domain name provider. Click on your domain or click manage domain and go to nameservers and click Custom DNS
  3. Add 3 nameservers. It should look like this:
    • ns1.digitalocean.com
    • ns2.digitalocean.com
    • ns3.digitalocean.com
  4. Click save

Note: it can take up to a couple of hours for the domain name to take effect, but usually it takes 5-15 minutes

Add SSL with LetsEncrypt (enables HTTPS)

Note: certbot is deprecated. So its best to install snapshot of certbot so it stays up to date. We will install certbot by following these instructions This installation is for web server on Nginx with Ubuntu 20.04

  1. Make sure everything is up to date sudo apt-get update
  2. You should already have snapd installed, so make sure its up to date with this command:
sudo snap install core; sudo snap refresh core
  1. Before installing certbot, remove it so we can install certbot snap, we dont want them to collide:
sudo apt-get remove certbot
  1. Now install certbot:
sudo snap install --classic certbot
  1. Prepare cerbot with your domains, it should look like this:
sudo certbot --nginx -d mywebsite.com -d www.mywebsite.com

This command gives you a certificate & Certbot edits your Nginx configuration automatically to serve it, turning on HTTPS access in a single step 6. Almost done, but this certificate will expire in 90 days, to renew it after every 90 days type this command:

sudo certbot renew --dry-run

BONUS: Change Welcome Message

  1. Install figlet
sudo apt-get install -y figlet
  1. Type figlet and type in your custom welcome message
  2. Copy the text and go into motd sudo nano /etc/motd
  3. Paste text and save
  4. Restart terminal to see your new welcome message

Congratulations you are done! Happy Hacking :D

@Shahzad6077
Copy link

Thanks @carlssonk for this great guide!

@hamidsaid
Copy link

Thanks a lot man

@njoromyke
Copy link

You deserve a hug.

@horizonvert1027
Copy link

Thank you for your effort.
I have a question.
How to host node.js application without ssh key?

@njoromyke
Copy link

a

In digital ocean? When creating an droplet they ask you whether you want to connect via ssh or password. Check that step.

@horizonvert1027
Copy link

a

In digital ocean? When creating an droplet they ask you whether you want to connect via ssh or password. Check that step.

I have selected password method.

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