We will need this for our server configuration
-
Open console
-
Change directory to root
cd ~
-
Run the following command to generate a SSH key on default directory
ssh-keygen -t rsa
-
Go to "Create Droplet" on Digital Ocean
-
Select on image Ubuntu
-
Choose your preferred size
-
Copy your SSH key using the following command
pbcopy < ~/.ssh/id_rsa.pub
-
Add your ssh key to your droplet
-
Press "Create" button
-
Get your ip address on the next view
-
Connect to your server using ssh
ssh root@192.168.1.1
-
Create a new user
adduser pedro
-
Check if your user is created
$ id pedro > uid=1000(pedro) gid=1000(pedro) groups=1000(pedro)
-
Give your user
sudo
permissionsusermod -aG sudo pedro
-
Check if your user has new permissions
$ id pedro > uid=1000(pedro) gid=1000(pedro) groups=1000(pedro),27(sudo)
-
Add your SSH key for the new user
# Become the new user su - pedro # Create a new directory for SSH stuff mkdir ~/.ssh # Set the directory permissions to allow only this user read/write/execute chmod 700 ~/.ssh # Create a file for SSH keys vim ~/.ssh/authorized_keys # Copy & Paste your local machine's SSH key # Set the file permissions to allow only this user to read/write chmod 600 ~/.ssh/authorized_keys
-
Change user to root again
exit
-
Log out of the server as root
exit
-
Log into your server as the new user
ssh pedro@192.168.1.1
-
Update SSH config to disable password logins
sudo vim /etc/ssh/sshd_config
- Change
PermitRootLogin yes
toPermitRootLogin no
- Change
PasswordAuthentication yes
toPassowrdAuthentication no
- Change
-
Restart the SSH service
sudo systemctl reload sshd
-
Open a new Terminal and check if both root and password login are disabled
$ ssh root@138.68.11.65 > Permission denied (publickey).
Setup firewall to only allow ports 80 (HTTP), 443 (HTTPS) and SSH logins
# Enable OpenSSH connections
sudo ufw allow OpenSSH
# Enable HTTP traffic
sudo ufw allow http
# Enable HTTPS traffic
sudo ufw allow https
# Turn the firewall on
sudo ufw enable
Check the status of the firewall
sudo ufw status
- Remove older versions of
docker
ordocker-engine
$ sudo apt-get remove docker docker-engine docker.io
- Update the apt package index
$ sudo apt-get update
- Install packages to allow apt to use a repository over HTTPS
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
software-properties-common
- Add Docker’s official GPG key
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
Verify that you now have the key with the fingerprint 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
$ sudo apt-key fingerprint 0EBFCD88
pub 4096R/0EBFCD88 2017-02-22
Key fingerprint = 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
uid Docker Release (CE deb) <docker@docker.com>
sub 4096R/F273FCD8 2017-02-22
- Use the following command to set up the stable repository
$ sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
- Install the latest version of Docker CE
$ sudo apt-get install docker-ce
Let’s Encrypt is a free, automated, and open Certificate Authority.
- Install tools for using the Let's Encrypt certificates using Certbot
sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-nginx
-
Configure your domain DNS to point to your droplet's IP
-
Check if your domain is pointing correctly
$ dig +short example.com > 138.68.174.154
-
Run Certbot to create the SSL certificate
sudo certbot --nginx certonly
-
Install Nginx
sudo apt-get install nginx
-
Redirect all traffic traffic to SSL
# Open the following file sudo vim /etc/nginx/sites-enabled/default # Delete everything and add the following server { listen 80; listen [::]:80 default_server ipv6only=on; return 301 https://$host$request_uri; }
-
Create a secure Diffie-Hellman group (takes a few minutes)
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
-
Create a configuration file for SSL
# Open the following file sudo vim /etc/nginx/snippets/ssl-params.conf # Paste the following from https://cipherli.st/ (follow the link for more info) ssl_protocols TLSv1.3 TLSv1.2 TLSv1.1 TLSv1; ssl_prefer_server_ciphers on; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384; ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0 ssl_session_timeout 10m; ssl_session_cache shared:SSL:10m; ssl_session_tickets off; # Requires nginx >= 1.5.9 ssl_stapling on; # Requires nginx >= 1.3.7 ssl_stapling_verify on; # Requires nginx => 1.3.7 resolver 208.67.222.222 208.67.220.220 valid=300s; resolver_timeout 5s; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; # Paste this at the bottom of the file ssl_dhparam /etc/ssl/certs/dhparam.pem;
-
Configure the server to use SSL
ATTENTION: Replace all the
example.com
with your domain# Open the following file sudo vim /etc/nginx/sites-enabled/default # Paste the following bellow the existing config server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com; # REPLACE HERE ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # REPLACE HERE ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # REPLACE HERE include snippets/ssl-params.conf; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-NginX-Proxy true; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_pass http://localhost:5000/; proxy_ssl_session_reuse off; proxy_set_header Host $http_host; proxy_pass_header Server; proxy_cache_bypass $http_upgrade; proxy_redirect off; } }
-
Test the Nginx config
$ sudo nginx -t > nginx: the configuration file /etc/nginx/nginx.conf syntax is ok > nginx: configuration file /etc/nginx/nginx.conf test is successful
-
Start Nginx
sudo systemctl start nginx
-
Finally, test your app by visiting your domain on your browser!
Most likely you will run-out of RAM memory when building your app or installing dependencies if you have chosen the $5/month plan on Digital Ocean
Don't worry, because you setup a swap file to allocate some hard drive space to be used as memory
-
Check the system Swap information
# Run the following command $ sudo swapon -s > Filename Type Size Used Priority # You can clearly see that no swap as been allocated # Alternatively you could run this command to check for memory $ free -m > total used free shared buffers cached > Mem: 488 77 67 0 2 12 > Swap: 0 0 0
-
Check Available Space on the Hard Drive partition
# Run the following command $ df -h > Filesystem Size Used Avail Use% Mounted on > /dev/vda 20G 1.3G 18G 10% / > none 4.0K 0 4.0K 0% /sys/fs/cgroup > udev 2.0G 12K 2.0G 1% /dev > tmpfs 396M 312K 396M 1% /run > none 5.0M 0 5.0M 0% /run/lock > none 2.0G 0 2.0G 0% /run/shm > none 100M 0 100M 0% /run/user # We can see that we have available 18G of our hard drive partition # Since our system has 512M of memory, how about we add 1G of swap
-
Create a Swap file (the faster way)
# Run the following command $ sudo fallocate -l 1G /swapfile # Verify that correct amount of space was reserved $ ls -lh /swapfile > -rw-r--r-- 1 root root 1.0G Sep 09 17:19 /swapfile
-
Enable the Swap file
# First, change the Swap file access permissions $ sudo chmod 600 /swapfile # Verify that the file has the correct permissions $ ls -lh /swapfile > -rw------- 1 root root 1.0G Sep 09 17:19 /swapfile # Setup the Swap space $ sudo mkswap /swapfile > Setting up swapspace version 1, size = 976563 KiB > no label, UUID=e2f1e9cf-c0a9-4ed4-b8ab-714b8a7d6944 # Enable the Swap File $ sudo swapon /swapfile # Verify the swap file $ sudo swapon -s > Filename Type Size Used Priority > /swapfile file 976563 0 -1 # Alternatively we could also check $ free -m > total used free shared buffers cached > Mem: 488 77 67 0 2 12 > Swap: 9766 0 9766
-
Make the Swap file permanent
# Open the following file $ sudo vim /etc/fstab # Paste this at the bottom of the file $ /swapfile none swap sw 0 0
-
Tweak the Swap settings
# Swapiness defines the threshold at which to swith memory to swap space # This value varies from 0 (only when absolutely necessary) to 100 (favor swap memory) # Run the following command to verify this value $ cat /proc/sys/vm/swappiness > 60 # Since we are using a VPS system let's change this value to 10 $ sudo sysctl vm.swappiness=10 > vm.swappiness = 10 # Persist this value by copying it to the system's config # Open the following file sudo vim /etc/sysctl.conf # Paste this at the bottom of the file vm.swappiness=10
# Another related value is cache pressure, regarding caching system data # This value also varies from 0 (less chaching) to 100 (more caching) # Run the following command to verify this value $ cat /proc/sys/vm/vfs_cache_pressure > 100 # Since we are using a VPS system let's change this value to 10 $ sudo sysctl vm.vfs_cache_pressure=50 > vm.vfs_cache_pressure = 50 # Persist this value by copying it to the system's config # Open the following file sudo vim /etc/sysctl.conf # Paste this at the bottom of the file vm.vfs_cache_pressure = 50
-
That's it! You now have more space so that don't get stuck with
KILLED
processed when you run out of memory. Swap space is slower than RAM memory but it's a perfect substitute for infrequent processes like building your app or installing dependencies.
-
Install GIT
sudo apt-get install git
-
Check if installed properly
$ git --version > git version 2.7.4
-
Run NodeSource script to setup
apt-get
for Node.jscurl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
-
Install Node.js
sudo apt-get install -y nodejs
-
Check if installed properly
$ node --version > v14.16.0
-
Clone your app
# Make sure you’re in your home folder cd ~ # Create the new directory and move into it mkdir apps cd apps/ # Create a new ssh key to connect to github ssh-keygen -t rsa -b 4096 -C "your_email@example.com" # Clone your app into a new directory named for your domain git clone git@github.com:pedrouid/hello-world-node-http.git hello-world
-
Test the app
node hello-world
-
Open a new Terminal and make a
curl
request$ curl localhost:5000 > Hello World!
On newever versions of node (^6.x), npm install might fail when running the build script for node-gyp.
To fix simply run these two commands:
# install build tools for node-gyp
sudo apt-get install build-essential
# install node-gyp globally
sudo npm install -g node-gyp