# 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 * Download [PuTTY & PuTTYgen](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html) * Download [WinSCP](https://winscp.net/eng/download.php) ## 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** 7. **IMPORTANT** Be sure to save the public key as **.txt** and your private key as **.ppk** on your computer, you will need these later 8. **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]`` 3. Login as that user:
``` sudo su - [username] ``` ## Authorize Key For New User 1. Make new directory: ``` mkdir ~/.ssh ``` 2. Change permission: ``` chmod 700 ~/.ssh ``` 3. Create and go into new file: ``` nano ~/.ssh/authorized_keys ``` 4. 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 5. Set permission for that file: ``` chmod 600 ~/.ssh/authorized_keys ``` 6. Restart service: ``` sudo service ssh restart ``` 7. Exit terminal and login as new user. Load config, click **Data** and change root to your [username]. ## Disable Root & Password Login AND Change SSH-port #### Disable Root & Password Login 1. Go into ssh config file: ``` sudo nano /etc/ssh/sshd_config ``` 2. Search for PermitRootLogin: **Ctrl+W** and type "PermitRootLogin" 3. Set PermitRootLogin to "no" 4. Search for PasswordAuthentication: **Ctrl+W** and type "PasswordAuthentication" 5. 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.) 6. 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 ``` Exit with Ctrl+X and Save 7. Reboot session: ``` reboot ``` 8. Close terminal and open PuTTY 9. 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". 10. 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 ``` To check your firewall status: ```ufw status``` ## Install packages 1. Update packages: ``` sudo apt update ``` 2. 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 - ``` 3. Install nodejs & npm: ``` sudo apt-get install nodejs ``` You can make sure they are installed: ```"npm -v" and "node -v"``` ## Install PM2 1. Install pm2 globally: ``` sudo npm install -g pm2 ``` 2. Start server: ```pm2 start index.js``` or ```pm2 start npm -- start``` 3. App should now be running on the droplets ip adress:
> ex.165.227.216.5:8080 ## NGINX 1. Install nginx: ``` sudo apt install nginx ``` 2. Go into default folder: ``` sudo nano /etc/nginx/sites-available/default ``` 3. 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. 4. 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``` 5. Exit and save: Ctrl+X & Y 6. Check so nginx is configured properly ```sudo nginx -t```. It should say something like the test is successful 7. Now restart the service ```sudo service nginx restart``` ## Clone App from github > If your project is not on github, upload it to github so we can clone it to your droplet 1. Create ssh key for github: ``` ssh-keygen -t rsa -C 'your@githubemail.com' ``` 2. Open **WinSCP** and choose import droplet & login 3. In /home/[username]/ add .ssh because its hidden by default, so go into the /home/[username]/.ssh directory 4. Drag over the **id_rsa.pub** file to the **document** folder and open the file 5. Copy the key and add it to ssh in GitHub 6. Now in your droplets terminal clone the project from github: ``` git clone git@github.com:user/your/repository ``` 8. type ```ls``` and boom your project is there 9. ```cd``` into your projext and type ```npm install``` to install all packages that your project contains ## 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"** 5. Create a Record for the **www** version, so do the same but replace "@" with "www" 6. Go to your domain name provider. Click on your domain or click manage domain and go to nameservers and click **Custom DNS** 7. Add 3 nameservers. It should look like this: * ns1.digitalocean.com * ns2.digitalocean.com * ns3.digitalocean.com 8. 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](https://certbot.eff.org/lets-encrypt/ubuntubionic-nginx) > 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 ``` 3. Before installing certbot, remove it so we can install certbot snap, we dont want them to collide: ``` sudo apt-get remove certbot ``` 4. Now install certbot: ``` sudo snap install --classic certbot ``` 5. 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 ``` # Congratulations you are done! Happy Hacking :D