<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Julien Le Coupanec</title>
    <description>The latest articles on DEV Community by Julien Le Coupanec (@lecoupa).</description>
    <link>https://dev.to/lecoupa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F501525%2Fa5059f67-7af0-489d-b9cc-843a9c892d87.jpeg</url>
      <title>DEV Community: Julien Le Coupanec</title>
      <link>https://dev.to/lecoupa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lecoupa"/>
    <language>en</language>
    <item>
      <title>Deploy Adonis 5 in Production (with CI/CD + Github Actions)</title>
      <dc:creator>Julien Le Coupanec</dc:creator>
      <pubDate>Thu, 12 Nov 2020 11:20:00 +0000</pubDate>
      <link>https://dev.to/lecoupa/deploy-adonis-5-in-production-with-ci-cd-44ch</link>
      <guid>https://dev.to/lecoupa/deploy-adonis-5-in-production-with-ci-cd-44ch</guid>
      <description>&lt;h1&gt;
  
  
  Deploy Adonis in Production
&lt;/h1&gt;

&lt;p&gt;Let's see how we can deploy and run Adonis in production on a remote server. I will assume that you are using Ubuntu all along with this article to adapt the command for another distribution.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Initial Server Setup
&lt;/h2&gt;

&lt;p&gt;Skip this step if your server is already set up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;adduser adonis              &lt;span class="c"&gt;# Create a new user&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;adonis     &lt;span class="c"&gt;# Grant administrative privileges&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow OpenSSH           &lt;span class="c"&gt;# Make sure that the firewall allows SSH connections&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw &lt;span class="nb"&gt;enable&lt;/span&gt;                  &lt;span class="c"&gt;# Enable the firewall&lt;/span&gt;

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update              &lt;span class="c"&gt;# Update packages&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;nodejs npm  &lt;span class="c"&gt;# Install node and NPM&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; pm2                &lt;span class="c"&gt;# Install pm2 to manage node &lt;/span&gt;

&lt;span class="c"&gt;# Install nvm to manage the node versions&lt;/span&gt;
curl &lt;span class="nt"&gt;-o-&lt;/span&gt; https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash

bash                             &lt;span class="c"&gt;# Reload bash environment&lt;/span&gt;
nvm &lt;span class="nb"&gt;install &lt;/span&gt;14.15.4              &lt;span class="c"&gt;# Install your Node version&lt;/span&gt;
node &lt;span class="nt"&gt;-v&lt;/span&gt;                          &lt;span class="c"&gt;# Check node version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To access your server with SSH, go back to your local machine and execute the following instructions to display your public key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/id_rsa.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the SSH key printed to the terminal and go back to your remote server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# If you are still logged in as root, run the command below:&lt;/span&gt;
su - adonis

&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/.ssh
&lt;span class="nb"&gt;chmod &lt;/span&gt;700 ~/.ssh
nano ~/.ssh/authorized_keys       &lt;span class="c"&gt;# Copy the public key here&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;600 ~/.ssh/authorized_keys  &lt;span class="c"&gt;# Restrict the permissions of the authorized_keys file&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Clone Your Adonis Repository
&lt;/h2&gt;

&lt;p&gt;To allow the server to access your Adonis project on Github/Gitlab, we need to generate a new SSH key and it to your account.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Generate a new ssh key&lt;/span&gt;
&lt;span class="c"&gt;# Follow the instructions and make sure to remember the name for the newly created key&lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-b&lt;/span&gt; 2048 &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"email@example.com"&lt;/span&gt;

&lt;span class="c"&gt;# Copy the SSH key&lt;/span&gt;
pbcopy &amp;lt; ~/.ssh/id_rsa.pub           &lt;span class="c"&gt;# MacOs&lt;/span&gt;
xclip &lt;span class="nt"&gt;-sel&lt;/span&gt; clip &amp;lt; ~/.ssh/id_rsa.pub  &lt;span class="c"&gt;# Linux (requires the xclip package)&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/id_rsa.pub | clip         &lt;span class="c"&gt;# Git Bash on Windows&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, add this new SSH Key to Github or Gitlab. Read the article below to learn more about the exact steps.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/adding-a-new-ssh-key-to-your-github-account"&gt;Adding a new SSH key to your GitHub account&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.gitlab.com/ee/ssh/README.html#adding-an-ssh-key-to-your-gitlab-account"&gt;Adding an SSH key to your GitLab account&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should now be able to clone your repository and install its dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone git@github.com:username/repository-name.git

git checkout production  &lt;span class="c"&gt;# If you need to switch to a specific production branch&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt;              &lt;span class="c"&gt;# Install dependencies&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Set up Mysql
&lt;/h2&gt;

&lt;p&gt;Here is how you can install MySQL on your server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;mysql-server
systemctl status mysql         &lt;span class="c"&gt;# Check the MySQL is installed&lt;/span&gt;
mysql_secure_installation      &lt;span class="c"&gt;# Secure MySQL (Follow the instructions)&lt;/span&gt;
mysql &lt;span class="nt"&gt;-u&lt;/span&gt; root &lt;span class="nt"&gt;-p&lt;/span&gt;               &lt;span class="c"&gt;# Connect to MySQL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are the commands to run to create a new user and database for your project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create a new MySQL user
CREATE USER 'root'@'%' IDENTIFIED BY 'YOUR_PASSWORD';

# Replace YOUR_PASSWORD
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'YOUR_PASSWORD';
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YOUR_PASSWORD';

# Create a new database
CREATE DATABASE database_name;

# Grant the new user privileges to the tables on the new database
GRANT ALL ON *.* TO 'root'@'%';

# For the changes to take effect
FLUSH PRIVILEGES;

# Exit the MySQL server
exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To allow remote access:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ufw allow 3306

&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/mysql/mysql.conf.d/mysqld.cnf

&lt;span class="c"&gt;# Then replace 127.0.0.1 by 0.0.0.0 for bind-address&lt;/span&gt;
bind-address            &lt;span class="o"&gt;=&lt;/span&gt; 0.0.0.0

&lt;span class="c"&gt;# Restart mysql&lt;/span&gt;
service mysql restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Set up Redis (For &lt;a href="https://github.com/Rocketseat/adonis-bull"&gt;Adonis Bull&lt;/a&gt;).
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;redis-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure redis.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/redis/redis.conf

&lt;span class="c"&gt;# Inside the file, find the supervised directive.&lt;/span&gt;
&lt;span class="c"&gt;# This directive allows you to declare an init system to manage Redis as a service, providing you with more control over its operation.&lt;/span&gt;
&lt;span class="c"&gt;# The supervised directive is set to no by default. Since you are running Ubuntu, which uses the systemd init system, change this to systemd.&lt;/span&gt;
supervised systemd

&lt;span class="c"&gt;# By default, Redis is only accessible from localhost.&lt;/span&gt;
&lt;span class="c"&gt;# However, if you installed and configured Redis by following a different tutorial than this one, you might have updated the configuration file to allow connections from anywhere.&lt;/span&gt;
&lt;span class="c"&gt;# This is not as secure as binding to localhost.&lt;/span&gt;
&lt;span class="nb"&gt;bind &lt;/span&gt;127.0.0.1 ::1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check that redis is working.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Upgrade Redis to a specific version.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Next, download the redis tar file from https://redis.io/download, then install it from the directory it downloaded to:&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/
wget http://download.redis.io/releases/redis-6.0.10.tar.gz redis-6.0.10.tar.gz
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xf&lt;/span&gt; redis-6.0.10.tar.gz
&lt;span class="nb"&gt;rm &lt;/span&gt;redis-6.0.10.tar.gz
&lt;span class="nb"&gt;cd &lt;/span&gt;redis-6.0.10
make

&lt;span class="c"&gt;# Next, we’ll move the new installed redis to the location where the current instance is running.&lt;/span&gt;
&lt;span class="nb"&gt;sudo mv &lt;/span&gt;src/redis-server /usr/bin
&lt;span class="nb"&gt;sudo mv &lt;/span&gt;src/redis-cli /usr/bin

&lt;span class="c"&gt;# After copy content you need restart redis-server:&lt;/span&gt;
&lt;span class="nb"&gt;sudo&lt;/span&gt; /etc/init.d/redis-server restart

&lt;span class="c"&gt;# To validate the version of redis-server and redis-cli run:&lt;/span&gt;
redis-cli &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="c"&gt;#redis-cli version&lt;/span&gt;
redis-cli INFO &lt;span class="c"&gt;#redis-server version&lt;/span&gt;

&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; ~/redis-6.0.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Build for Production
&lt;/h2&gt;

&lt;p&gt;Go back to your project repository and create a new &lt;code&gt;.env&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build         &lt;span class="c"&gt;# Generate the production bundle&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; .env build/.env    &lt;span class="c"&gt;# Copy the .env file to the production bundle&lt;/span&gt;

pm2 start build/server.js &lt;span class="nt"&gt;--name&lt;/span&gt; API  &lt;span class="c"&gt;# Start the Adonis server&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You may be wondering why we need to copy the &lt;code&gt;.env&lt;/code&gt; file to the build folder. In a nutshell, there is no standard way of defining environment variables. One could do it via a &lt;code&gt;.env&lt;/code&gt; file, via Heroku or AWS management console's or an app specification file for Digital Ocean. Earlier (before the recent release), we used to copy the &lt;code&gt;.env&lt;/code&gt; file. But this can lead to false-positive behavior too. This means that from now on, you must run &lt;code&gt;cp .env build/.env&lt;/code&gt; after each build.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then ping your server with curl to see if everything is behaving correctly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl 127.0.0.1:3333  &lt;span class="c"&gt;# Do you get a response?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One final step is to run the migrations and seed the database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node ace migration:run &lt;span class="nt"&gt;--force&lt;/span&gt;
node ace db:seed &lt;span class="nt"&gt;--force&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Regarding &lt;code&gt;pm2&lt;/code&gt;, here are a few commands you should know to manage your processes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pm2 kill&lt;/code&gt;: stop and remove all processes.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pm2 start command --name PROCESS_NAME&lt;/code&gt;: stop the process name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pm2 stop PROCESS_NAME&lt;/code&gt;: stop a given process&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pm2 restart PROCESS_NAME&lt;/code&gt;: restart a given process&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Set up Nginx with SSL.
&lt;/h2&gt;

&lt;p&gt;To allow people to access Adonis from your domain name, we will install Nginx. We will also configure SSL to make sure the connection is secured.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;nginx        &lt;span class="c"&gt;# Install Nginx&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow &lt;span class="s1"&gt;'Nginx HTTPS'&lt;/span&gt;  &lt;span class="c"&gt;# Open the port 443 only (TLS/SSL encrypted traffic)&lt;/span&gt;
systemctl status nginx        &lt;span class="c"&gt;# Check that Nginx is running&lt;/span&gt;

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;certbot python3-certbot-nginx     &lt;span class="c"&gt;# Install certbot&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw disable                                   &lt;span class="c"&gt;# Disable the firewall while generating the certificate&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;certbot certonly &lt;span class="nt"&gt;-d&lt;/span&gt; api.example.com           &lt;span class="c"&gt;# Generate the certificate&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw &lt;span class="nb"&gt;enable&lt;/span&gt;                                    &lt;span class="c"&gt;# Enable the firewall&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Useful certbot commands&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;certbot certificates &lt;span class="c"&gt;# List certificates&lt;/span&gt;
certbot delete       &lt;span class="c"&gt;# Delete a specific certificate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure Nginx.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /etc/nginx/sites-available
nano default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a possible configuration file to deliver your website with SSL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;api.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-NginX-Proxy&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:3333&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$http_host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_cache_bypass&lt;/span&gt; &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_redirect&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt; &lt;span class="s"&gt;ipv6only=on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/api.example.com/fullchain.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/api.example.com/privkey.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/options-ssl-nginx.conf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_dhparam&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/ssl-dhparams.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;if&lt;/span&gt; &lt;span class="s"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;api.example.com)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://&lt;/span&gt;&lt;span class="nv"&gt;$host$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="s"&gt;default_server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:80&lt;/span&gt; &lt;span class="s"&gt;default_server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;api.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, restart Nginx:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Set up Your Continuous Deployment Process with Github Actions
&lt;/h2&gt;

&lt;p&gt;If you are looking to deploy a new version of Adonis while merging on your production branch, here is a GitHub action file that connects to your remove server, run some instructions and notify you on Slack if something fails or succeeds.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make sure to configure the &lt;a href="https://docs.github.com/en/free-pro-team@latest/actions/reference/encrypted-secrets"&gt;related secret variables&lt;/a&gt;: &lt;code&gt;secrets.HOST&lt;/code&gt;, &lt;code&gt;secrets.USERNAME&lt;/code&gt;, &lt;code&gt;secrets.KEY&lt;/code&gt;, &lt;code&gt;secrets.SLACK_WEBHOOK&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;timeout-minutes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploying&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;appleboy/ssh-action@master&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.HOST }}&lt;/span&gt;
          &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.USERNAME }}&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.KEY }}&lt;/span&gt;
          &lt;span class="na"&gt;script_stop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;# Copy and build new version&lt;/span&gt;

            &lt;span class="s"&gt;rm -rf my-project-repo-new&lt;/span&gt;
            &lt;span class="s"&gt;cp -r my-project-repo my-project-repo-new&lt;/span&gt;
            &lt;span class="s"&gt;cd my-project-repo-new&lt;/span&gt;
            &lt;span class="s"&gt;git checkout production&lt;/span&gt;
            &lt;span class="s"&gt;git reset --hard origin/production&lt;/span&gt;
            &lt;span class="s"&gt;git pull&lt;/span&gt;
            &lt;span class="s"&gt;npm rebuild&lt;/span&gt;
            &lt;span class="s"&gt;npm install&lt;/span&gt;

            &lt;span class="s"&gt;# Build the api&lt;/span&gt;

            &lt;span class="s"&gt;npm run build&lt;/span&gt;
            &lt;span class="s"&gt;cp .env build/.env&lt;/span&gt;

            &lt;span class="s"&gt;# Run migrations&lt;/span&gt;

            &lt;span class="s"&gt;node ace migration:run --force&lt;/span&gt;
            &lt;span class="s"&gt;node ace db:seed --force&lt;/span&gt;

            &lt;span class="s"&gt;# Replace current version with the new one&lt;/span&gt;

            &lt;span class="s"&gt;cd ..&lt;/span&gt;
            &lt;span class="s"&gt;mv my-project-repo my-project-repo-old&lt;/span&gt;
            &lt;span class="s"&gt;mv my-project-repo-new my-project-repo&lt;/span&gt;

            &lt;span class="s"&gt;# Restart server&lt;/span&gt;

            &lt;span class="s"&gt;cd my-project-repo&lt;/span&gt;
            &lt;span class="s"&gt;pm2 delete my-project-repo&lt;/span&gt;
            &lt;span class="s"&gt;pm2 start build/server.js --name my-project-repo&lt;/span&gt;
            &lt;span class="s"&gt;rm -rf ../my-project-repo-old&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Slack success notification&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;success()&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rtCamp/action-slack-notify@master&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;SLACK_CHANNEL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-channel&lt;/span&gt;
          &lt;span class="na"&gt;SLACK_COLOR&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;good&lt;/span&gt;
          &lt;span class="na"&gt;SLACK_ICON&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png&lt;/span&gt;
          &lt;span class="na"&gt;SLACK_MESSAGE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Deployment&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;achieved&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;with&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;success'&lt;/span&gt;
          &lt;span class="na"&gt;SLACK_TITLE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CI&lt;/span&gt;
          &lt;span class="na"&gt;SLACK_USERNAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GitHub&lt;/span&gt;
          &lt;span class="na"&gt;SLACK_WEBHOOK&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SLACK_WEBHOOK }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Slack error notification&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;failure()&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rtCamp/action-slack-notify@master&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;SLACK_CHANNEL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-channel&lt;/span&gt;
          &lt;span class="na"&gt;SLACK_COLOR&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;danger&lt;/span&gt;
          &lt;span class="na"&gt;SLACK_ICON&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png&lt;/span&gt;
          &lt;span class="na"&gt;SLACK_MESSAGE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;The&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;deployment&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;has&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;failed&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;@channel'&lt;/span&gt;
          &lt;span class="na"&gt;SLACK_TITLE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CI&lt;/span&gt;
          &lt;span class="na"&gt;SLACK_USERNAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GitHub&lt;/span&gt;
          &lt;span class="na"&gt;SLACK_WEBHOOK&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SLACK_WEBHOOK }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>node</category>
    </item>
  </channel>
</rss>
