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.
- Download PuTTY & PuTTYgen
- Download WinSCP
- Have your application on a GitHub repo.
- Create New Project/Create New Droplet
- Choose Ubuntu, Choose your desired plan & country
- Click on New SSH Key
- Open PuTTyGen and generate a new RSA Key
- Copy the key in the input field and add it to your droplet, Add SSH Key
- IMPORTANT Be sure to save the public key as .txt and your private key as .ppk on your computer, you will need these later
- Create Droplet
- Open PuTTY
- Add your droplets IP Adress to 'Host Name (or IP Adress)'
- In Connection -> Data, set username to "root"
- In SSH -> Auth, load your privatekey.ppk that you created from last step
- Set a session name and SAVE
-
Login to your server, click yes if first time connecting to server
-
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]
- Login as that user:
sudo su - [username]
- Make new directory:
mkdir ~/.ssh
- Change permission:
chmod 700 ~/.ssh
- Create and go into new file:
nano ~/.ssh/authorized_keys
-
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
-
Set permission for that file:
chmod 600 ~/.ssh/authorized_keys
- Restart service:
sudo service ssh restart
- Exit terminal and login as new user. Load config, click Data and change root to your [username].
Update packages
sudo apt update
- Go into ssh config file:
sudo nano /etc/ssh/sshd_config
- Search for PermitRootLogin: Ctrl+W and type "PermitRootLogin"
- Set PermitRootLogin to "no"
- Search for PasswordAuthentication: Ctrl+W and type "PasswordAuthentication"
- Set PasswordAuthentication to "no"
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.)
- 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
- Close terminal and open PuTTY
- 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".
- Save and open terminal
Note: to enable firewall you need to be on the root user. Type
sudo -i
orsudo -s
to switch to the root user
Typesu - [username]
to switch back to your user after enabling firewall
- 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 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 -
- Install nodejs & npm:
sudo apt-get install nodejs
You can make sure they are installed: "npm -v" and "node -v"
- Install nginx:
sudo apt install nginx
- Go into default folder:
sudo nano /etc/nginx/sites-available/default
- 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.
- 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
- Exit and save: Ctrl+X & Y
- Check so nginx is configured properly
sudo nginx -t
. It should say something like the test is successful - Now restart the service
sudo service nginx restart
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
- Create ssh key for github:
ssh-keygen -t ed25519 -C "[email protected]"
- When you're prompted to "Enter a file in which to save the key," press Enter. This accepts the default file location.
- Ensure the ssh-agent is running.
eval "$(ssh-agent -s)"
- Add your SSH private key to the ssh-agent.
ssh-add ~/.ssh/id_ed25519
- copy SSH key that you just created:
cd .ssh
cat id_ed25519.pub
copy the output including email
- Go to GitHub > Settings > SSH and GPG Keys
- Click "New SSH Key"
- 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
If your project is not on github, upload it to github so we can clone it to your droplet
- Make sure you are standing on root:
cd
- Go into /var/www
cd /var/www
You can remove default html folder if you want "sudo rm -fr html"
- Clone app from GitHub
sudo git clone [email protected]:user/your-repository.git
- if this gives permission error clone from HTTPS instead
- type
ls
and boom your project is there cd
into your projext and typenpm install
to install all packages that your project contains
- Install pm2 globally:
sudo npm install -g pm2
- Start server:
pm2 start index.js
orpm2 start npm -- start
- App should now be running on the droplets ip adress:
ex.165.227.216.5:8080
- First buy your domain through preferred service: ex, namecheap, godaddy.
- Then in DigitalOcean go to the networking tab and add your domain
- Where it says HOSTNAME you will add a "@" and at WILL DIRECT TO you want to put your droplet
- Click on Create Record.
The record you are creating is "A"
- Create a Record for the www version, so do the same but replace "@" with "www"
- Go to your domain name provider. Click on your domain or click manage domain and go to nameservers and click Custom DNS
- Add 3 nameservers. It should look like this:
- ns1.digitalocean.com
- ns2.digitalocean.com
- ns3.digitalocean.com
- 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
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
- Make sure everything is up to date
sudo apt-get update
- You should already have snapd installed, so make sure its up to date with this command:
sudo snap install core; sudo snap refresh core
- Before installing certbot, remove it so we can install certbot snap, we dont want them to collide:
sudo apt-get remove certbot
- Now install certbot:
sudo snap install --classic certbot
- 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
- Install figlet
sudo apt-get install -y figlet
- Type
figlet
and type in your custom welcome message - Copy the text and go into motd
sudo nano /etc/motd
- Paste text and save
- Restart terminal to see your new welcome message
Thanks @carlssonk for this great guide!