Deploy Multiple Adonis.js Applications with PM2 and Nginx on Ubuntu 20.04
AdonisJS is a web framework for Node.js that lets you write web apps or an API server easier. In version 5, AdonisJS uses TypeScript for the core framework and the application. This guide explains how to deploy multiple AdonisJS apps on one server using PM2 and Nginx.
Prerequisites
Before you begin, you should:
- Deploy a fresh Ubuntu 20.04 server on Vultr.
- Create a non-root user with sudo privileges.
Install Node.js
Install Node.js using Ubuntu APT repository:
$ sudo apt update $ sudo apt install nodejs npm
Ubuntu comes with an outdated Node.js. AdonisJS requires at least Node.js version 14, so you need to update it.
$ node -v v10.19.0
Install the
n
package. It helps you update Node.js.$ sudo npm install n -g
Update Node.js using the
n
package.$ sudo n stable
Check the Node.js version.
$ node -v v16.13.2
If the Node.js version is not yet changed, you need to disconnect and reconnect your ssh session.
Create Sample Applications
In this guide, you are creating two sample apps. The first one is a web app and the second one is an API server.
Create a directory to place the apps.
$ mkdir apps
Change to the directory.
$ cd apps
Initialize the first sample app and select the web project structure.
$ npm init adonis-ts-app@latest example1
Initialize the second app and select the API project structure.
$ npm init adonis-ts-app@latest example2
You have two folders, example1
and example2
, containing your two apps. To run them simultaneously, you need to change the second app port.
Go to the example2
directory and edit the .env
file:
$ cd example2
$ nano .env
Change the port number to anything you like, for example, 3334.
PORT=3334
Build for Production
Because the AdonisJS application uses TypeScript, you must compile it to JavaScript before running it in production.
Go to the first app folder and run the
build
Ace command. The compiled result is in thebuild
folder.$ cd ~/apps/example1 $ node ace build --production
After that, copy the
.env
file to thebuild
folder and edit it.$ cp .env build/.env $ nano build/.env
Set the
NODE_ENV
variable in the.env
file to production.NODE_ENV=production
Install production-only dependencies inside the
build
folder.$ cd build $ npm ci --production
Repeat the process above for the second app.
Using PM2 to Run the Apps
PM2 is a daemon process manager that helps you manage and keep your Node.js applications online.
Install the latest PM2 package.
$ sudo npm install pm2@latest -g
Create the PM2 ecosystem file to manage all your apps.
$ cd ~/apps $ nano ecosystem.config.js
Add these configurations to the
ecosystem.config.js
file.module.exports = { apps : [ { name : "example1", script : "./example1/build/server.js" }, { name : "example2", script : "./example2/build/server.js" } ] }
Run all of your apps.
$ pm2 start ecosystem.config.js
All your apps are running now, you can check it by using this command:
$ pm2 list
You see the two example apps in that list. You can access your apps from a web browser using your Vultr VPS IP address plus the app port numbers.
// Example 1
http://[VULTR_VPS_IP_ADDRESS]:3333
// Example 2
http://[VULTR_VPS_IP_ADDRESS]:3334
You may need to disable the firewall if you can't access it using the port number. You can enable it again later.
$ sudo ufw disable
At this point, all your apps are running. But, this process is not persistent yet, meaning that if you restart your server, your apps are not automatically run on the startup. You must run them manually again.
To have persistent apps running you need to generate a startup script for PM2.
Run the following command.
$ pm2 startup
Copy and paste the displayed command onto the terminal.
$ sudo env PATH=$PATH:/usr/local/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u <user> --hp <home-path>
Save your PM2 app list using this command.
$ pm2 save
Nginx Reverse Proxy
The next step is connecting your domains to your apps. You use Nginx reverse proxy to be able to do that. In general, you put your apps behind the Nginx web server. Nginx accepts all incoming requests and forwards them to your apps.
Install Nginx.
$ sudo apt update $ sudo apt install nginx
Disable the default Nginx configuration.
$ sudo unlink /etc/nginx/sites-enabled/default
Create an Nginx configuration file for the first sample app.
$ sudo nano /etc/nginx/sites-available/example1.com
Paste in the following configuration.
server { listen 80; server_name example1.com; location / { proxy_pass http://localhost:3333; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_cache_bypass $http_upgrade; } }
Create a configuration file for the second app.
$ sudo nano /etc/nginx/sites-available/example2.com
Paste in the following configuration.
server { listen 80; server_name example2.com; location / { proxy_pass http://localhost:3334; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_cache_bypass $http_upgrade; } }
Please note that you must change the domain names (example1.com and example2.com) to your own domains.
Enable the configuration files.
$ sudo ln -s /etc/nginx/sites-available/example1.com /etc/nginx/sites-enabled/ $ sudo ln -s /etc/nginx/sites-available/example2.com /etc/nginx/sites-enabled/
Test your configurations for syntax errors.
$ sudo nginx -t
If there are no errors then reload the Nginx process.
$ sudo systemctl reload nginx
Point your domains to your Vultr VPS IP address. And you can access your apps in the browser using the domain names.
Secure Apps with Let’s Encrypt SSL Certificate
Let’s Encrypt provides a free SSL certificate for your apps. It has a software client named Certbot to generate the certificate.
Install Certbot.
$ sudo snap install core; sudo snap refresh core $ sudo snap install --classic certbot $ sudo ln -s /snap/bin/certbot /usr/bin/certbot
Generate the SSL certificate.
$ sudo certbot --nginx
Visit your domains in the browser and confirm they have an HTTPS connection.
Autorenew the SSL Certificate
Let’s Encrypt SSL certificate expires after 90 days. You can set up a Cron job to renew the SSL certificate automatically.
Test certificate renewal command.
$ sudo certbot renew --dry-run
Set up the Cron job.
$ sudo crontab -e
Add the following line.
15 3 * * * /usr/bin/certbot renew --quiet; /bin/systemctl reload nginx
Set Up the Firewall
In the earlier step, you disable the firewall for testing purposes. You need to enable it again to make your server more secure.
Set the firewall to allow the SSH port.
$ sudo ufw allow 'OpenSSH'
Allow HTTP and HTTPS ports.
$ sudo ufw allow 'Nginx Full'
Enable the firewall.
$ sudo ufw enable
Check firewall status.
$ sudo ufw status
Conclusion
This completes the installation of multiple AdonisJS apps on one server using PM2 and Nginx, secured with a Let’s Encrypt SSL certificate. The firewall only allows SSH, HTTP, and HTTPS connections.
More Information on AdonisJS
[AdonisJS Official Website](https://adonisjs.com)
[AdonisJS Documentation](https://docs.adonisjs.com/guides/introduction)