Sails.js is a full-stack MVC JavaScript framework for Node.js. It is used for developing real-time web applications. It is inspired by Ruby on Rails, but with support for data-driven APIs and scalable, service-oriented architecture. It uses a powerful Object-Relational Mapping (ORM) called Waterline that allows it to be used with databases such as MySQL, PostgreSQL, MongoDB, Redis, etc.

In this tutorial, you will learn how to install the Sails.js framework to create a test app and deploy it using the Nginx server along with Let’s Encrypt SSL on a Ubuntu 22.04 server.

Prerequisites

  • A server running Ubuntu 22.04.

  • A non-root user with sudo privileges.

  • The Uncomplicated Firewall(UFW) is enabled and running.

  • A Fully Qualified domain name pointed to the server. For our tutorial, we will be using the domain sails.example.com.

  • Everything is updated.

    $ sudo apt update && sudo apt upgrade
    

Step 1 – Configure Firewall

The first step before installing any packages is to configure the firewall to allow HTTP and HTTPS connections.

Check the status of the firewall.

$ sudo ufw status

You should see something like the following.

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)

Allow HTTP and HTTPs ports.

$ sudo ufw allow http
$ sudo ufw allow https

Check the status again to confirm.

$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443                        ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443 (v6)                   ALLOW       Anywhere (v6)

Step 2 – Install Node Version Manager (NVM)

We will install Node using Node Version Manager (nvm) application. You can use NVM to install multiple versions of Node and switch between them with ease. Run the following command to download and install NVM.

Check the latest version of NVM from the Github releases page. At the time of writing this tutorial, v0.39.1 is the latest available version.

$ NVMVERSION=0.39.1
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/$NVMVERSION/install.sh | bash

Refresh the terminal.

$ source ~/.bashrc

Verify that NVM is installed.

$ command -v nvm

You should see the following output on successful installation.

nvm

Step 3 – Install Node.js

We will install the latest version of the LTS (Long term support) release of Node.js. Run the following command to do that.

$ nvm install --lts

Verify that Node.js is installed.

$ node --version
v16.17.0

Step 4 – Install Sails.js

Now that Node.js is installed, it is time to install the Sails.js framework. Run the following command to install it globally.

$ npm -g install sails

Verify that the Sails.js framework is installed.

$ sails --version
1.5.3

You can check other commands available with the sails command line application by using the --help flag.

$ sails --help

You will receive the following output.

Usage: sails [command]

  Options:

    -v, --version  output the version number
    -h, --help     output usage information

  Commands:

    version
    lift|l [options]
    new [options] [path_to_new_app]
    generate
    upgrade
    migrate
    console|c [options]
    www
    debug                            (for Node v5 and below)
    inspect                          (for Node v6 and above)
    run
    test
    lint
    deploy
    debug-console|dc
    help [command]

Step 5 – Create a Demo application

Run the following command to generate a demo application.

$ sails new howtoforge-app

You will get the following two options.

Choose a template for your new Sails app:
 1. Web App  ·  Extensible project with auth, login, & password recovery
 2. Empty    ·  An empty Sails app, yours to configure
 (type "?" for help, or  to cancel)

You can type 1 to go with a pre-defined template for a full-fledged application with authentication, a login page, and a password recovery feature. If you want to start with a blank slate, go with option 2.

We will go with option 1. You will need to wait for a few minutes for the process to complete.

? 1
 info: Installing dependencies...
Press CTRL C to cancel.
(to skip this step in the future, use --fast)
 info: Created a new Sails app `howtoforge-app`!

Switch to the working directory of the newly created application. The directory name is the same as your application.

$ cd howtoforge-app

Check the folder listing. The folder will have all essential files and packages installed to get you started with the application.

$ ls
total 944
drwxrwxr-x   9 navjot navjot   4096 Aug 23 07:14 .
drwxr-x---   8 navjot navjot   4096 Aug 23 07:13 ..
drwxrwxr-x   8 navjot navjot   4096 Aug 23 07:13 api
-rw-rw-r--   1 navjot navjot   1841 Aug 23 07:13 app.js
drwxrwxr-x   8 navjot navjot   4096 Aug 23 07:13 assets
drwxrwxr-x   4 navjot navjot   4096 Aug 23 07:13 config
-rw-rw-r--   1 navjot navjot   1046 Aug 23 07:13 .editorconfig
-rw-rw-r--   1 navjot navjot     44 Aug 23 07:13 .eslintignore
-rw-rw-r--   1 navjot navjot   4228 Aug 23 07:13 .eslintrc
-rw-rw-r--   1 navjot navjot   3531 Aug 23 07:13 .gitignore
-rw-rw-r--   1 navjot navjot    669 Aug 23 07:13 Gruntfile.js
-rw-rw-r--   1 navjot navjot    709 Aug 23 07:13 .htmlhintrc
-rw-rw-r--   1 navjot navjot   2162 Aug 23 07:13 .lesshintrc
drwxrwxr-x 510 navjot navjot  20480 Aug 23 07:14 node_modules
-rw-rw-r--   1 navjot navjot    369 Aug 23 07:13 .npmrc
-rw-rw-r--   1 navjot navjot   6151 Aug 23 07:13 package.json
-rw-rw-r--   1 navjot navjot 854958 Aug 23 07:14 package-lock.json
-rw-rw-r--   1 navjot navjot   1732 Aug 23 07:13 README.md
-rw-rw-r--   1 navjot navjot    123 Aug 23 07:13 .sailsrc
drwxrwxr-x   2 navjot navjot   4096 Aug 23 07:13 scripts
drwxrwxr-x   4 navjot navjot   4096 Aug 23 07:13 tasks
drwxrwxr-x   5 navjot navjot   4096 Aug 23 07:13 views

Run the Sails application. The following command will start the application in development mode. Sails.js uses the Grunt tool to monitor the /assets folder. If you change anything in that folder, it will be reflected automatically in the browser. You can also change your view files without restarting Sails because the templates are not cached in memory.

$ sails lift

You will get the following output on the successful starting of the application.

 info: Starting app...

 info: Initializing project hook... (`api/hooks/custom/`)
 info: Initializing `apianalytics` hook...  (requests to monitored routes will be logged!)
 info: ·• Auto-migrating...  (alter)
 info:    Hold tight, this could take a moment.
 info:  ? Auto-migration complete.

debug: Running v0 bootstrap script...  (looks like this is the first time the bootstrap has run on this computer)
 info:
 info:                .-..-.
 info:
 info:    Sails              <|    .-..-.
 info:    v1.5.3              |
 info:                       /|.
 info:                      / || 
 info:                    ,'  |'  
 info:                 .-'.-==|/_--'
 info:                 `--'-------'
 info:    __---___--___---___--___---___--___
 info:  ____---___--___---___--___---___--___-__
 info:
 info: Server lifted in `/home/navjot/howtoforge-app`
 info: To shut down Sails, press    C at any time.
 info: Read more at https://sailsjs.com/support.

debug: -------------------------------------------------------
debug: :: Tue Aug 23 2022 09:01:32 GMT 0000 (Coordinated Universal Time)

debug: Environment : development
debug: Port        : 1337
debug: -------------------------------------------------------

Sails.js exposes your app to port 1337. You will need to open the port to access the application. Launch another terminal to your server and run the following command to open the port.

$ sudo ufw allow 1337

Launch the URL http://:1337 in your browser. You will get the following page.

<img alt="Sails.js Demo App Page" data-ezsrc="https://kirelos.com/wp-content/uploads/2022/09/echo/sailsjs-demo-app.png631064c31f72a.jpg" ezimgfmt="rs rscb5 src ng ngcb5" height="750" loading="lazy" referrerpolicy="no-referrer" src="data:image/svg xml,” width=”719″>

Press Ctrl C on the terminal to shut down the Sails application.

Step 6 – Create a systemd service file

Right now, the Sails app is working only if the terminal is active. To keep it persistent across reboots, we need to create a systemd service file for Sails.

Create and open the howtoforge-app.service file for editing.

$ sudo nano /etc/systemd/system/howtoforge-app.service

Paste the following code in it.

[Unit]
After=network.target

[Service]
Type=simple
User=navjot
WorkingDirectory=/home/navjot/howtoforge-app
ExecStart=/home/navjot/.nvm/versions/node/v16.17.0/bin/node app.js
Restart=on-failure

[Install]
WantedBy=multi-user.target

Replace the values for the User, WorkingDirectory and ExecStart variables with your system’s username, application path, and the path to your node application. To locate the path to Node.js, you can use the following command.

$ which node
/home/navjot/.nvm/versions/node/v16.17.0/bin/node

We are using Node.js instead of the Sails CLI application because it is easier to configure and run it via a system script. Save the file by pressing Ctrl X and entering Y when prompted.

Reload the system daemon to apply the changes.

$ sudo systemctl daemon-reload

Start the Sails.js service and enable it to start at system boot.

$ sudo systemctl enable howtoforge-app --now

Check the status of the service.

$ sudo systemctl status howtoforge-app
? howtoforge-app.service - Sails.js Howtoforge App
     Loaded: loaded (/etc/systemd/system/howtoforge-app.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2022-08-23 11:52:58 UTC; 5s ago
   Main PID: 15385 (node)
      Tasks: 22 (limit: 2237)
     Memory: 123.8M
        CPU: 3.894s
     CGroup: /system.slice/howtoforge-app.service
             ??15385 /home/navjot/.nvm/versions/node/v16.17.0/bin/node app.js
             ??15392 grunt "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ">

Aug 23 11:53:01 sails node[15385]:  info:  ____---___--___---___--___---___--___-__
Aug 23 11:53:01 sails node[15385]:  info:
Aug 23 11:53:01 sails node[15385]:  info: Server lifted in `/home/navjot/howtoforge-app`
Aug 23 11:53:01 sails node[15385]:  info: To shut down Sails, press    C at any time.
Aug 23 11:53:01 sails node[15385]:  info: Read more at https://sailsjs.com/support.
Aug 23 11:53:01 sails node[15385]: debug: -------------------------------------------------------
Aug 23 11:53:01 sails node[15385]: debug: :: Tue Aug 23 2022 11:53:01 GMT 0000 (Coordinated Universal Time)
Aug 23 11:53:01 sails node[15385]: debug: Environment : development
Aug 23 11:53:01 sails node[15385]: debug: Port        : 1337
Aug 23 11:53:01 sails node[15385]: debug: -------------------------------------------------------

You can verify the service by opening the URL http://:1337 in your browser.

Step 7 – Install Nginx

Ubuntu 22.04 ships with an older version of Nginx. To install the latest version, you need to download the official Nginx repository.

Import Nginx’s signing key.

$ curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor 
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

Add the repository for Nginx’s stable version.

$ echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg arch=amd64] 
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" 
| sudo tee /etc/apt/sources.list.d/nginx.list

Update the system repositories.

$ sudo apt update

Install Nginx.

$ sudo apt install nginx

Verify the installation.

$ nginx -v
nginx version: nginx/1.22.0

Step 8 – Install SSL

We need to install Certbot to generate the SSL certificate. You can either install Certbot using Ubuntu’s repository or grab the latest version using the Snapd tool. We will be using the Snapd version.

Ubuntu 22.04 comes with Snapd installed by default. Run the following commands to ensure that your version of Snapd is up to date.

$ sudo snap install core
$ sudo snap refresh core

Install Certbot.

$ sudo snap install --classic certbot

Use the following command to ensure that the Certbot command can be run by creating a symbolic link to the /usr/bin directory.

$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

Run the following command to generate an SSL Certificate.

$ sudo certbot certonly --standalone --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -d sails.example.com

The above command will download a certificate to the /etc/letsencrypt/live/sails.example.com directory on your server.

Generate a Diffie-Hellman group certificate.

$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096

Open the file /etc/letsencrypt/renewal/sails.example.com.conf for editing.

$ sudo nano /etc/letsencrypt/renewal/sails.example.com.conf

Paste the following code at the bottom.

pre_hook = systemctl stop nginx
post_hook = systemctl start nginx

Save the file by pressing Ctrl X and entering Y when prompted.

We have generated the SSL certificate using the standalone option of Certbot. It runs its web server to create the certificate which means Nginx should be shut off during the renewal. The pre_hook and post_hook commands run before and after the renewal to automatically shut and restart the Nginx server thereby requiring no manual intervention.

To check whether the SSL renewal is working fine, do a dry run of the process.

$ sudo certbot renew --dry-run

If you see no errors, you are all set. Your certificate will renew automatically.

Step 9 – Configure Nginx

Open the file /etc/nginx/nginx.conf for editing.

$ sudo nano /etc/nginx/nginx.conf

Add the following line before the line include /etc/nginx/conf.d/*.conf;.

server_names_hash_bucket_size  64;

Save the file by pressing Ctrl X and entering Y when prompted.

Create and open the file /etc/nginx/conf.d/sails.conf for editing.

$ sudo nano /etc/nginx/conf.d/sails.conf

Paste the following code in it. Replace sails.example.com with your domain name. Make sure the value of the client_max_body_size is set to 10MB. Change it according to your requirements.

upstream backend {
   server 127.0.0.1:1337;
   keepalive 32;
}

server {
  listen 80 default_server;
  server_name sails.example.com;
  return 301 https://$server_name$request_uri;
}

server {
   listen 443 ssl http2;
   server_name sails.example.com;

   http2_push_preload on; # Enable HTTP/2 Server Push

   ssl_certificate /etc/letsencrypt/live/sails.example.com/fullchain.pem;
   ssl_certificate_key /etc/letsencrypt/live/sails.example.com/privkey.pem;
   ssl_trusted_certificate /etc/letsencrypt/live/sails.example.com/chain.pem;
   ssl_session_timeout 1d;

   # Enable TLS versions (TLSv1.3 is required upcoming HTTP/3 QUIC).
   ssl_protocols TLSv1.2 TLSv1.3;

   # Enable TLSv1.3's 0-RTT. Use $ssl_early_data when reverse proxying to
   # prevent replay attacks.
   #
   # @see: https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_early_data
   ssl_early_data on;

   ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384';
   ssl_prefer_server_ciphers on;
   ssl_session_cache shared:SSL:50m;
   # OCSP Stapling ---
   # fetch OCSP records from URL in ssl_certificate and cache them
   ssl_stapling on;
   ssl_stapling_verify on;
   ssl_dhparam /etc/ssl/certs/dhparam.pem;

   add_header X-Early-Data $tls1_3_early_data;
   
   access_log /var/log/nginx/sails.access.log main;
   error_log  /var/log/nginx/sails.error.log;

   location / {
       client_max_body_size 10M;
       proxy_set_header Host $http_host;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "upgrade";
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Proto $scheme;
       proxy_set_header X-Frame-Options SAMEORIGIN;
       proxy_buffering off;
       proxy_http_version 1.1;
       proxy_pass http://backend;
   }
}

# This block is useful for debugging TLS v1.3. Please feel free to remove this
# and use the `$ssl_early_data` variable exposed by NGINX directly should you
# wish to do so.
map $ssl_early_data $tls1_3_early_data {
  "~." $ssl_early_data;
  default "";
}

Save the file by pressing Ctrl X and entering Y when prompted.

Verify your Nginx configuration.

$ sudo nginx -t

Restart the Nginx server.

$ sudo systemctl restart nginx

Step 10 – Access Sails.js App

Launch the URL https://sails.example.com in your browser and you will be greeted with the Sails homepage.

Click the Sign up button at the top right to create a new account.

<img alt="Sails App Create account page" data-ezsrc="https://kirelos.com/wp-content/uploads/2022/09/echo/sails-create-account.png631064c382e39.jpg" ezimgfmt="rs rscb5 src ng ngcb5" height="648" loading="lazy" referrerpolicy="no-referrer" src="data:image/svg xml,” width=”750″>

Fill in your account details and click the Create account button to finish.

You will be immediately taken to the welcome screen.

<img alt="Sails Application Account Welcome Page" data-ezsrc="https://kirelos.com/wp-content/uploads/2022/09/echo/sails-welcome-page.png631064c3e6f70.jpg" ezimgfmt="rs rscb5 src ng ngcb5" height="302" loading="lazy" referrerpolicy="no-referrer" src="data:image/svg xml,” width=”750″>

You can now start using the application to build a dynamic application with user authentication, database support, and an in-built payment gateway powered by Stripe.

Conclusion

This completes the tutorial where you learned how to install the Sails.js framework and created a demo application. You also learned how to set up a systemd service for it and use the Nginx proxy server with Let’s Encrypt to launch a secure web application. If you have any questions, post them in the comments below.