Steps to deploy a Node.js app to DigitalOcean using PM2, NGINX as a reverse proxy and an SSL from LetsEncrypt
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
https://docs.docker.com/engine/install/ubuntu/
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
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
curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt install nodejs
node --version
There are a few ways to get your files on to the server, I would suggest using Git
git clone yourproject.git
cd yourproject
npm install
npm start (or whatever your start command)
# stop app
ctrl+C
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)
sudo ufw enable
sudo ufw status
sudo ufw allow ssh (Port 22)
sudo ufw allow http (Port 80)
sudo ufw allow https (Port 443)
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
In Digital Ocean, go to networking and add a domain
Add an A record for @ and for www to your droplet
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
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
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
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
https://www.digitalocean.com/community/tutorials/how-to-add-swap-space-on-ubuntu-20-04