We're live-coding on Twitch! Join us! FREE Webinar: Should I use React or Vue?
Deploying AdonisJs 5 to DigitalOcean

Deploying AdonisJs 5 to DigitalOcean

Code

In this tutorial, I’ll be showing you how to deploy an AdonisJs 5 application to DigitalOcean. For the purpose of this tutorial, I have created a demo AdonisJs 5 application, which we’ll be deploying to DigitalOcean. The demo application can be found on GitHub.

Prerequisites

This tutorial assumes the following:

Create a Droplet

We’ll start by spinning up a new server, which is referred to as droplet by DigitalOcean. Login to your DigitalOcean account and create a new droplet.

Create droplet

We’ll be making use of DigitalOcean's 1-Click Apps to quickly spin up our server. So under Choose an image, click on the Marketplace tab and type Node.js Quickstart then select it from the result as shown below:

Select Node.js Quickstart

Next, we’ll choose the $5/month plan, which is suitable for our demo application.

Choose plan

For the datacenter region, we’ll go with the default. Next, we’ll add our SSH key. If you have already added SSH keys to DigitalOcean before, you can choose from those:

React LogoReact Logo
Upgrade Your JS
Go from vanilla JavaScript 👉 React

Select SSH key

If not, you’ll need to click on the New SSH Key button to add a new SSH key. You can get your SSH key by running the command below on your local computer:

cat ~/.ssh/id_rsa.pub

The command above will print your SSH key on the terminal, which you can then copy and paste in the SSH Key Content field and give your SSH key a name.

Add SSH key

Finally, choose a hostname (if you don’t want the randomly generated name) for the droplet and click the Create Droplet button.

We should now have a server up and running on Ubuntu 18.04 with the following software installed and configured:

Node.js Quickstart softwares

Take note of the IP address of the server as we’ll be using it to access the server in subsequent sections.

Configuring The Server

As a security measure, it is recommended to carry out tasks on a server as a non-root user with administrative privileges. So before we start configuring our server, let’s create a non-root user which we’ll use to administer our server for the rest of the tutorial.

First, we need to login to the server as root. We can do that using the server’s IP address. Enter the command below on your local computer:

ssh root@IP_ADDRESS

Once we are logged in to the server, we can move on to create a new user:

adduser mezie

This will create a new user called mezie, you can name the user whatever you like. You will be asked a few questions, starting with the account password.

Having created the new user, we need to give it administrative privileges. That is, the user will be able to perform administrative tasks by using sudo command:

usermod -aG sudo mezie

The command above adds the user mezie to sudo group. Now, the user can run commands with superuser privileges.

Next, let’s set up SSH key for the newly created user. You need to copy your public key to your new server. Enter the command below on your local computer:

cat ~/.ssh/id_rsa.pub

Copy the SSH key printed to the terminal.

For the new user to login to the server with an SSH key, we must add the public key to a special file in the user's home directory.

Still logged in as root on the server, run the command below:

su - mezie

This will temporarily switch to the new user. Now, you’ll be in your new user's home directory.

Next, we need to create a new directory called .ssh and restrict its permission:

mkdir ~/.ssh
chmod 700 ~/.ssh

Within the .ssh directory, create a new file called authorized_keys:

touch ~/.ssh/authorized_keys

Open the file:

vim ~/.ssh/authorized_keys

and paste your public key (copied above) into the file. To save the file, hit esc to stop editing, then :wq and press ENTER.

Next, restrict the permissions of the authorized_keys file with this command:

chmod 600 ~/.ssh/authorized_keys

Type the command below to return to the root user:

exit

Now, your public key is installed, and you can use SSH keys to log in as the new user.

To make sure you can log in as the new user with SSH. Enter the command below in a new terminal on your local computer:

ssh mezie@IP_ADDRESS

If all went well, you’ll be logged in to the server as the new user with SSH.

The rest of the tutorial assumes you are logged in to the server with the newly created user (mezie in my case).

Because we chose 1-Click App while creating our droplet, ufw firewall is enabled, which keeps our server secured. Now, we need to open the firewall for only HTTP since we are not concerned with SSL in this tutorial:

sudo ufw allow 'Nginx HTTP'

Installing and Configuring MySQL

The demo application we’re deploying in this tutorial makes use of MySQL, so we need to install and configure MySQL on our server:

sudo apt install mysql-server

Next, let’s configure MySQL:

sudo mysql_secure_installation

Enter a root password when prompted, then answer the necessary options when prompted.

With the MySQL configured, we need to create a database and a user. First, log in to the MySQL server:

mysql -u root -p

Provide the root password you enter above while installing MySQL. Once you are logged in, create a new user:

CREATE USER 'YOUR_USERNAME'@'localhost' IDENTIFIED BY 'YOUR_PASSWORD';

Replace YOUR_USERNAME and YOUR_PASSWORD with your user and password respectively. Then execute the following command:

ALTER USER 'YOUR_USERNAME'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YOUR_PASSWORD';

This will allow us to use a password when connecting to MySQL as the created user. Remember to change YOUR_USERNAME and YOUR_PASSWORD to your database user and password respectively.

Next, create a new database:

CREATE DATABASE adonis_tasks;

Then we need to grant the new user privileges to the tables on the new database:

GRANT ALL ON adonis_tasks.* TO 'YOUR_USERNAME'@'localhost';

For the changes to take effect, run:

FLUSH PRIVILEGES;

Finally, exit the MySQL server:

exit;

Pulling in Our Application

With everything configured on our server, we can focus on our application. We’ll be pulling in our application to our server using git.

We are going to clone the app unto the server directly in the user's home directory (that is, /home/mezie in my case):

git clone https://github.com/ammezie/adonis5-tasks.git

Once cloned, run the following command:

cd adonis5-tasks
npm install

Just like any other TypeScript application, we need to compile the TypeScript file to JavaScript. In AdonisJs, this process is called build, which can be done using the command below:

node ace build

This will create a build directory containing the compiled TypeScript files.

By default, AdonisJs reads most of its configuration settings from environment variables, which are store inside a .env file located in the root of every AdonisJs application. This makes it easier to make use of different configuration settings depending on the environment (development, staging, production, etc.) the application is running.

Let’s create the .env file:

touch .env

Once the file is created, we need to generate an APP_KEY for our application:

node ace generate:key

This will output a random string, which we’ll copy and add inside the .env file. Open .env:

vim .env

and paste the following into it:

// .env

PORT=3333
HOST=127.0.0.1
NODE_ENV=production
APP_KEY=YOUR_GENERATED_KEY_COPIED_FROM_ABOVE
DB_CONNECTION=mysql
DB_HOST=localhost
DB_NAME=adonis_tasks
DB_USER=YOUR_DATABASE_USERNAME
DB_PASSWORD=YOUR_DATABASE_PASSWORD

Remember to update YOUR_DATABASE_USERNAME and YOUR_DATABASE_PASSWORD with your database details from the previous section.

Since we have updated the .env file, we need to rebuild our application:

node ace build

Now, we can run the migration:

node ace migration:run --force

Because we are on production, we have to use the --force flag, otherwise, the migration will not run.

Now, we can start our application. For this, we’ll be making use of PM2, which will start our application and restart it whenever it crashes:

pm2 start build/server.js

Setting Up Nginx As A Reverse Proxy Server

We already have Nginx installed and configured, let’s set it up as a reverse proxy, which will allow us to access our app directly with an IP address or domain instead of tacking port to the IP address. Eg. 102.123.83.29:5000.

Open the default Nginx server configuration file:

sudo vim /etc/nginx/sites-available/default

and update the server block as below:

// /etc/nginx/sites-available/default

server_name DOMAIN_NAME_OR_IP_ADDRESS;

location / {
    proxy_pass http://localhost:3333;
    proxy_http_version 1.1;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

We set the server_name to that of our server IP address or domain name (if it’s set up). It is important to set proxy_pass to that of our application URL (in our case, http://localhost:3333).

To make sure there are no errors in the configuration, run the command below:

sudo nginx -t

Then we can restart Nginx for our changes to take effect:

sudo service nginx restart

Now, we should be able to access our application with our server’s IP_ADDRESS. If a domain name has been set up for our server, then we should be able to access our application using the domain name as well.

You should get something similar to the image below:

Application demo

Conclusion

In this tutorial, we have seen how to deploy an AdonisJs 5 application to DigitalOcean. Also, we saw how easy it is to spin up a new server with DigitalOcean’s 1-Click App.

Like this article? Follow @ammezie on Twitter