A Step-by-Step Guide to Installing Strapi CMS on Rocky Linux 9

Strapi is an open-source, headless Content Management System (CMS), developed with JavaScript. Unlike traditional CMS’, Strapi doesn’t include a frontend by default, leveraging an API to allow integration with popular frameworks like React and Next.js. Its plugin-based architecture offers extensive customization of the admin panel and API, making it suitable for various uses. Strapi also features a built-in user management system for detailed access control.

In this comprehensive guide, you’ll learn how to install the community version of Strapi CMS on a Rocky Linux 9 server, using Nginx as a reverse proxy server.

Prerequisites

  • A server with Rocky Linux 9, at least 2GB RAM, and 1 CPU Core.
  • A non-root user with sudo privileges.
  • A fully qualified domain name (FQDN) such as strapi.example.com.
  • System packages should be updated using:
    $ sudo dnf update
  • Install essential packages:
    $ sudo dnf install wget curl nano unzip yum-utils -y

    Note that some packages might already be present on your system.

Step 1 – Configure Firewall

Start by configuring the firewall, as Rocky Linux uses Firewalld. Check the firewall status:

$ sudo firewall-cmd --state

If it is running, list services and ports:

$ sudo firewall-cmd --permanent --list-services

You should see services like cockpit, dhcpv6-client, and ssh. Open HTTP and HTTPS ports for Strapi:

$ sudo firewall-cmd --permanent --add-service=http
$ sudo firewall-cmd --permanent --add-service=https

Reload the firewall to apply these changes:

$ sudo firewall-cmd --reload

Check the updated list of services:

$ sudo firewall-cmd --permanent --list-services

The output should now include http and https services.

Step 2 – Install and Configure PostgreSQL

Strapi supports PostgreSQL 11 and above. We’ll use PostgreSQL 15. Add the PostgreSQL GPG key:

$ curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | sudo tee /usr/share/keyrings/postgresql-key.gpg >/dev/null

Install the PostgreSQL repository RPM:

$ sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm

Disable the built-in PostgreSQL module:

$ sudo dnf -qy module disable postgresql

Install PostgreSQL:

$ sudo dnf install -y postgresql15-server

Initialize the database:

$ sudo /usr/pgsql-15/bin/postgresql-15-setup initdb

Enable and start PostgreSQL service:

$ sudo systemctl enable postgresql-15
$ sudo systemctl start postgresql-15

Check PostgreSQL service status:

$ sudo systemctl status postgresql-15

Access the PostgreSQL shell and create the database and user:

$ sudo -i -u postgres psql
postgres=# CREATE DATABASE strapidb;
postgres-# CREATE USER strapiuser WITH PASSWORD 'Your_Password';
postgres-# ALTER DATABASE strapidb OWNER TO strapiuser;
postgres-# \q

Verify credentials:

$ psql --username strapiuser --password --host localhost strapidb

Step 3 – Install Node.js

Rocky Linux 9 includes Node v16, which is outdated. Install the latest Node LTS (v18):

$ curl -fsSL https://rpm.nodesource.com/setup_18.x | sudo bash -

Then, install Node.js:

$ sudo dnf install nodejs -y

Verify installation:

$ node -v

Step 4 – Install Strapi

Install Strapi:

$ npx create-strapi-app@latest howtoforge-project

When prompted, confirm the installation and choose custom/manual settings:

    ? Choose your installation type: Custom (manual settings)
    ? Choose your preferred language: JavaScript
    ? Choose your default database client: postgres
    ? Database name: strapidb
    ? Host: 127.0.0.1
    ? Port: 5432
    ? Username: strapiuser
    ? Password: Your_Password
    ? Enable SSL connection: No

Complete installation, then build your Strapi project:

$ cd howtoforge-project
$ NODE_ENV=production npm run build

Start the Strapi server:

$ node ~/howtoforge-project/node_modules/.bin/strapi start

Access Strapi at http://<yourserverIP>:1337. First, open port 1337:

$ sudo firewall-cmd --permanent --add-port=1337/tcp
$ sudo firewall-cmd --reload

To stop the server, press Ctrl + C. Remove firewall rule:

$ sudo firewall-cmd --permanent --remove-port=1337/tcp
$ sudo firewall-cmd --reload

Step 5 – Install and Configure PM2

Use PM2 to manage processes:

$ sudo npm install pm2@latest -g

Edit the PM2 configuration:

$ sudo nano ecosystem.config.js
module.exports = {
  apps: [
    {
      name: 'strapi',
      cwd: '/home/navjot/howtoforge-project',
      script: 'npm',
      args: 'start',
      env: {
        NODE_ENV: 'production',
        DATABASE_HOST: 'localhost',
        DATABASE_PORT: '5432',
        DATABASE_NAME: 'strapidb',
        DATABASE_USERNAME: 'strapiuser',
        DATABASE_PASSWORD: 'Your_Password',
      },
    },
  ],
};

Save and start Strapi with PM2:

$ pm2 start ecosystem.config.js

To ensure the setup starts on boot, generate and activate a startup script:

$ pm2 startup
$ sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u navjot --hp /home/navjot

Preserve the PM2 process list:

$ pm2 save

Step 6 – Install Nginx

Configure the Nginx repository for the latest version:

$ sudo nano /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

Install Nginx:

$ sudo dnf install -y nginx

Enable and start it:

$ sudo systemctl enable nginx --now

Step 7 – Install SSL

Install prerequisites and Certbot for SSL:

$ sudo dnf install -y epel-release
$ sudo dnf install -y snapd
$ sudo systemctl enable snapd --now
$ sudo snap install core && sudo snap refresh core
$ sudo ln -s /var/lib/snapd/snap /snap
$ echo 'export PATH=$PATH:/var/lib/snapd/snap/bin' | sudo tee -a /etc/profile.d/snapd.sh
$ sudo snap install --classic certbot
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

Generate an SSL certificate:

$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m name@example.com -d strapi.example.com

Generate a Diffie-Hellman group certificate:

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

Test SSL renewal:

$ sudo certbot renew --dry-run

Step 8 – Configure Nginx

Edit Nginx configuration:

$ sudo nano /etc/nginx/nginx.conf

Add:

server_names_hash_bucket_size  64;

Create Nginx site configuration for Strapi:

$ sudo nano /etc/nginx/conf.d/strapi.conf
server {
  listen         80;
  listen         [::]:80;
  server_name    strapi.example.com;
  return 301     https://$host$request_uri;
}

server {
  listen                    443 ssl http2;
  listen                    [::]:443 ssl http2;
  server_name               strapi.example.com;

  access_log                /var/log/nginx/strapi.access.log;
  error_log                 /var/log/nginx/strapi.error.log;

  ssl_certificate           /etc/letsencrypt/live/strapi.example.com/fullchain.pem;
  ssl_certificate_key       /etc/letsencrypt/live/strapi.example.com/privkey.pem;
  ssl_trusted_certificate   /etc/letsencrypt/live/strapi.example.com/chain.pem;
  ssl_protocols             TLSv1.2 TLSv1.3;

  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;
  ssl_session_timeout       1d;

  ssl_stapling on;
  ssl_stapling_verify on;
  ssl_dhparam /etc/ssl/certs/dhparam.pem;

  location / {
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-Proto $scheme;
    proxy_set_header	      X-Forwarded-Host $http_host;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass              http://127.0.0.1:1337;
  }
}

Verify and restart Nginx:

$ sudo nginx -t
$ sudo systemctl restart nginx

Access Strapi CMS at https://strapi.example.com. Proceed to set up your admin user.

Step 9 – Upgrade Strapi

Stop the Strapi service for upgrade:

$ cd ~
$ pm2 stop ecosystem.config.js

Edit project and upgrade dependencies:

$ cd howtoforge-project
$ nano package.json
"devDependencies": {},
  "dependencies": {
    "@strapi/strapi": "4.5.5",
    "@strapi/plugin-users-permissions": "4.5.5",
    "@strapi/plugin-i18n": "4.5.5",
    "pg": "8.6.0"
  },

Change dependencies to the latest stable versions, save, and install:

$ npm install

Rebuild and restart:

$ NODE_ENV=production npm run build
$ pm2 start ecosystem.config.js

Your Strapi installation is now upgraded and operational.

Conclusion

This concludes our guide on installing Strapi CMS on Rocky Linux 9 using Nginx. If you have any questions, feel free to comment below.

FAQ

  • What is Strapi? Strapi is an open-source, headless CMS that uses JavaScript and an API for integrating with frontend frameworks.
  • Why choose a headless CMS like Strapi? It allows flexibility in designing the frontend with your preferred frameworks like React or Next.js.
  • Can I customize Strapi? Yes, Strapi is highly customizable, from the admin panel to its API endpoints.
  • How do updates work in Strapi? Updates involve stopping the server, updating the package.json for dependencies, and rebuilding the project.
  • Why use PM2 with Strapi? PM2 manages Node.js processes efficiently, ensuring that applications run smoothly and restart on failures.