Skip to content

Instantly share code, notes, and snippets.

@pedrouid
Last active March 12, 2021 14:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save pedrouid/9ad43a9631b216adb684c8edf700063d to your computer and use it in GitHub Desktop.
Save pedrouid/9ad43a9631b216adb684c8edf700063d to your computer and use it in GitHub Desktop.
Digital Ocean DevOps Cheatsheet (Ubuntu 16.04)

Digital Ocean DevOps Cheatsheet (Ubuntu 16.04)

How to Deploy a Node.js App with SSL

Create an SSH key

We will need this for our server configuration

  1. Open console

  2. Change directory to root

    cd ~
    
  3. Run the following command to generate a SSH key on default directory

    ssh-keygen -t rsa
    

Server setup and config

  1. Go to "Create Droplet" on Digital Ocean

  2. Select on image Ubuntu

  3. Choose your preferred size

  4. Copy your SSH key using the following command

    pbcopy < ~/.ssh/id_rsa.pub
    
  5. Add your ssh key to your droplet

  6. Press "Create" button

  7. Get your ip address on the next view

  8. Connect to your server using ssh

    ssh root@192.168.1.1
    

Create a Super User

  1. Create a new user

    adduser pedro
    
  2. Check if your user is created

    $ id pedro
    > uid=1000(pedro) gid=1000(pedro) groups=1000(pedro)
    
  3. Give your user sudo permissions

    usermod -aG sudo pedro
    
  4. Check if your user has new permissions

    $ id pedro
    > uid=1000(pedro) gid=1000(pedro) groups=1000(pedro),27(sudo)
    
  5. 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
    
  6. Change user to root again

    exit
    
  7. Log out of the server as root

    exit
    

Disable Password Login

  1. Log into your server as the new user

    ssh pedro@192.168.1.1
    
  2. Update SSH config to disable password logins

    sudo vim /etc/ssh/sshd_config
    
    1. Change PermitRootLogin yes to PermitRootLogin no
    2. Change PasswordAuthentication yes to PassowrdAuthentication no
  3. Restart the SSH service

    sudo systemctl reload sshd
    
  4. Open a new Terminal and check if both root and password login are disabled

    $ ssh root@138.68.11.65
    > Permission denied (publickey).
    

Setup Basic Firewall

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

Install Docker CE for Ubuntu

  1. Remove older versions of docker or docker-engine
$ sudo apt-get remove docker docker-engine docker.io
  1. Update the apt package index
$ sudo apt-get update
  1. Install packages to allow apt to use a repository over HTTPS
$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common
  1. 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
  1. 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"
  1. Install the latest version of Docker CE
$ sudo apt-get install docker-ce

Get a Free SSL Certificate With Let’s Encrypt

Let’s Encrypt is a free, automated, and open Certificate Authority.

  1. 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
  1. Configure your domain DNS to point to your droplet's IP

  2. Check if your domain is pointing correctly

    $ dig +short example.com
    > 138.68.174.154
    
  3. Run Certbot to create the SSL certificate

    sudo certbot --nginx certonly
    

Setup Nginx with SSL

  1. Install Nginx

    sudo apt-get install nginx
    
  2. 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;
    }
    
  3. Create a secure Diffie-Hellman group (takes a few minutes)

    sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
    
  4. 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;
    
  5. 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;
        }
    }
    
  6. 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
    
  7. Start Nginx

    sudo systemctl start nginx
    
  8. Finally, test your app by visiting your domain on your browser!

[OPTIONAL] Add Swap to your Linux Server

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

  1. 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
    
  2. 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
    
  3. 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
    
  4. 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
    
  5. 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
    
  6. 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
    
  7. 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.

[OPTIONAL] Setup a NodeJS App

  1. Install GIT

    sudo apt-get install git
    
  2. Check if installed properly

    $ git --version
    > git version 2.7.4
    
  3. Run NodeSource script to setup apt-get for Node.js

    curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
    
  4. Install Node.js

    sudo apt-get install -y nodejs
    
  5. Check if installed properly

    $ node --version
    > v14.16.0
    
  6. 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
    
  7. Test the app

    node hello-world
    
  8. Open a new Terminal and make a curl request

    $ curl localhost:5000
    > Hello World!
    

[BUG] node-gyp fails to build on npm-install

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

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