How to Install Backdrop CMS with LEMP on AlmaLinux 8

Install Backdrop CMS with LEMP Stack on AlmaLinux 8 using Nginx, MariaDB, PHP-FPM, SELinux, firewalld, and HTTPS in minutes on a fresh VPS today.
A glowing blue server rack and database cylinder represent Backdrop CMS on AlmaLinux 8.

Install Backdrop CMS with LEMP Stack on AlmaLinux 8 by connecting Nginx, MariaDB, and PHP-FPM, then finish the web installer over HTTPS. The complete setup takes about 10–15 minutes on a fresh VPS with a domain already pointed at its IP address.

Prerequisites

  • AlmaLinux 8.x with at least 1 GB RAM, 10 GB free disk space, and a public IPv4 address.
  • Root access or a sudo-enabled user over SSH. The commands below use sudo.
  • A domain such as YOUR_DOMAIN with an A record pointing to the VPS. A second DNS record is not required for this single-site setup.
  • A strong database password and a separate strong Backdrop administrator password. Use different passwords for both accounts.
  • A VPSLake Linux VPS with AlmaLinux 8 is a suitable starting point for this workload.
  • The LEMP components will be installed in this guide; do not install Apache on the same ports.

Step 1: Update AlmaLinux and install the LEMP packages

Updating first applies the latest AlmaLinux 8 fixes, while the Remi PHP stream supplies a modern PHP version for a long-lived Backdrop installation.

sudo dnf update -y
sudo dnf install -y epel-release firewalld mariadb-server unzip curl bind-utils policycoreutils-python-utils
sudo dnf module enable nginx:1.20 -y
sudo dnf install -y nginx
sudo dnf install -y https://rpms.remirepo.net/enterprise/remi-release-8.rpm
sudo dnf module reset php -y
sudo dnf module enable php:remi-8.3 -y
sudo dnf install -y php php-fpm php-cli php-mysqlnd php-gd php-mbstring php-opcache php-xml php-curl php-zip php-intl
sudo systemctl enable --now firewalld mariadb nginx php-fpm
php -v
nginx -v
mariadb --version

You should see PHP 8.3.x, an Nginx version, and a MariaDB client version. The exact patch numbers can change as the repositories publish updates.

PHP-FPM normally starts workers as apache on AlmaLinux. Nginx needs access to its Unix socket, so change the default pool to the Nginx account and restart PHP-FPM.

sudo sed -ri 's/^[; ]*user = .*/user = nginx/; s/^[; ]*group = .*/group = nginx/; s/^[; ]*listen.owner = .*/listen.owner = nginx/; s/^[; ]*listen.group = .*/listen.group = nginx/' /etc/php-fpm.d/www.conf
sudo systemctl restart php-fpm
sudo systemctl is-active php-fpm

Expected output is active.

Step 2: Create the MariaDB database

Backdrop stores pages, users, configuration, and content in MariaDB, so give it a dedicated database and account with access limited to that database.

sudo mariadb <<'SQL'
CREATE DATABASE backdrop CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'backdrop_user'@'localhost' IDENTIFIED BY 'YOUR_DATABASE_PASSWORD';
GRANT ALL PRIVILEGES ON backdrop.* TO 'backdrop_user'@'localhost';
FLUSH PRIVILEGES;
SQL
sudo mariadb -e "SHOW DATABASES LIKE 'backdrop';"

Replace YOUR_DATABASE_PASSWORD with a unique password before running the block. The final command should return a row named backdrop; you will enter the same database name, username, and password in the Backdrop installer.

Step 3: Download Backdrop CMS and set the webroot

The release archive is downloaded from Backdrop’s GitHub releases rather than from a mutable development branch, which keeps this installation reproducible.

The commands below use Backdrop 1.35.1, the current stable release at the time of writing. The archive can contain a top-level directory, so find locates the real release root before copying its files.

BACKDROP_VERSION=1.35.1
sudo curl -fL -o /tmp/backdrop.zip "https://github.com/backdrop/backdrop/releases/download/${BACKDROP_VERSION}/backdrop.zip"
sudo mkdir -p /tmp/backdrop-release /var/www/backdrop
sudo unzip -q /tmp/backdrop.zip -d /tmp/backdrop-release
BACKDROP_ROOT="$(find /tmp/backdrop-release -type f -name index.php -printf '%h\n' | head -n 1)"
sudo cp -a "$BACKDROP_ROOT"/. /var/www/backdrop/

Set read access for Nginx, but leave only the upload directory writable by the web process. Backdrop needs that directory for images, modules, and other managed files.

sudo mkdir -p /var/www/backdrop/files
sudo chown -R root:nginx /var/www/backdrop
sudo find /var/www/backdrop -type d -exec chmod 750 {} \;
sudo find /var/www/backdrop -type f -exec chmod 640 {} \;
sudo chown -R nginx:nginx /var/www/backdrop/files
sudo chmod -R 770 /var/www/backdrop/files
sudo chmod 660 /var/www/backdrop/settings.php

On an SELinux-enabled server, label the code as read-only web content and the files directory as writable web content. This keeps SELinux enforcing while allowing Backdrop to manage uploads.

sudo semanage fcontext -a -t httpd_sys_content_t '/var/www/backdrop(/.*)?'
sudo semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/backdrop/files(/.*)?'
sudo restorecon -Rv /var/www/backdrop

Step 4: Configure Nginx for Backdrop

Backdrop uses front-controller routing for clean URLs, so Nginx must send unknown paths to index.php instead of returning a plain 404.

Create /etc/nginx/conf.d/backdrop.conf with this server block:

server {
    listen 80;
    listen [::]:80;
    server_name YOUR_DOMAIN;

    root /var/www/backdrop;
    index index.php;
    client_max_body_size 32m;

    location / {
        try_files $uri $uri/ @backdrop;
    }

    location @backdrop {
        rewrite ^/(.*)$ /index.php?q=$1 last;
    }

    location ^~ /files/styles/ {
        try_files $uri @backdrop;
    }

    location ~ \.php$ {
        try_files $uri =404;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTP_PROXY "";
        fastcgi_pass unix:/run/php-fpm/www.sock;
    }

    location = /settings.php {
        deny all;
    }

    location ~ ^/files/.*\.php$ {
        deny all;
    }
}

Replace YOUR_DOMAIN with the hostname in your DNS record. The explicit settings.php rule blocks direct access to database credentials, and the upload rule prevents an uploaded PHP file from being executed.

sudo nginx -t
sudo systemctl reload nginx

Expected output includes syntax is ok and test is successful.

Step 5: Open the firewall and enable HTTPS

HTTP is needed for the initial certificate challenge, while HTTPS protects the Backdrop login and administration pages.

sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https
sudo firewall-cmd --reload
sudo dnf install -y certbot python3-certbot-nginx
sudo certbot --nginx --redirect --agree-tos --no-eff-email -m YOUR_EMAIL -d YOUR_DOMAIN

Replace YOUR_EMAIL with an address for certificate renewal notices. Certbot must be able to resolve YOUR_DOMAIN to this server and reach port 80 from the internet. On success, it updates the Nginx server block and redirects HTTP requests to HTTPS.

Step 6: Finish the Backdrop installation in your browser

The browser installer creates the site configuration and administrator account, so no CMS password needs to appear in your shell history.

Open https://YOUR_DOMAIN in a browser. If the installer does not appear, open https://YOUR_DOMAIN/core/install.php directly. Choose the standard installation profile, enter backdrop as the database name, backdrop_user as the database user, localhost as the host, and the database password from Step 2.

On the site information screen, enter the site name and create a new administrator account with a long, unique password. When setup completes, sign in through the HTTPS address and confirm that the dashboard loads.

After the installer finishes, make the settings file read-only to the web process while retaining group read access for Nginx:

sudo chown root:nginx /var/www/backdrop/settings.php
sudo chmod 640 /var/www/backdrop/settings.php

For Nginx routing details, compare this server block with Backdrop’s official system requirements. The official installation instructions also explain the browser steps and the writable files directory.

Verify the Backdrop installation

Run these checks from SSH, then open the site in a private browser window to confirm that the certificate and login session work together.

sudo systemctl is-active nginx php-fpm mariadb firewalld
sudo nginx -t
curl -fsSI https://YOUR_DOMAIN
sudo php -m | grep -E 'curl|gd|mbstring|mysqli|mysqlnd|PDO|xml|zip'

Expected results are active for each service, a successful Nginx test, an HTTP response such as HTTP/2 200, and the PHP extensions listed on separate lines. A successful page request proves Nginx can reach PHP-FPM and Backdrop can serve its front controller.

Troubleshooting

502 Bad Gateway

Nginx cannot reach the PHP-FPM socket, usually because PHP-FPM is stopped or the pool still uses the wrong socket owner. Check sudo systemctl status php-fpm, confirm that /run/php-fpm/www.sock exists, and restart both services after reapplying the pool changes from Step 1.

The installer shows missing PDO MySQL or PHP extensions

The PHP modules were not installed in the active stream, or PHP-FPM has not been restarted. Run sudo dnf install -y php-mysqlnd php-gd php-mbstring php-xml php-curl php-zip php-intl, then run sudo systemctl restart php-fpm and refresh the installer.

Clean URLs return 404, but the home page loads

The Backdrop rewrite location is missing, the domain is using a different server block, or Nginx was not reloaded. Run sudo nginx -T | grep -A5 -B3 'server_name YOUR_DOMAIN', verify the @backdrop block, and reload Nginx after correcting it.

Certbot cannot validate the domain

The DNS A record may still point elsewhere, or an upstream firewall may block port 80. Confirm dig +short YOUR_DOMAIN returns the VPS IP, allow HTTP in the VPS control panel and firewalld, then run Certbot again after DNS propagation.

Hardening and maintenance

  • Keep AlmaLinux, Nginx, PHP, and MariaDB updated with sudo dnf update -y; take a database and /var/www/backdrop/files backup before major CMS updates.
  • Leave SELinux enforcing and do not make the whole document root writable. Only the files directory needs web-server write access.
  • Test renewal before you rely on the certificate: sudo certbot renew --dry-run.
  • Backdrop’s update manager may need outbound HTTPS access. If SELinux logs deny that specific operation, review the denial and then enable only the documented httpd_can_network_connect boolean if required.

FAQ

Can I install Backdrop CMS without a domain?

You can test the site over the VPS IP address, but a real domain is strongly preferred for HTTPS and reliable administrator access. Let’s Encrypt certificates are issued for domain names, not bare IP addresses in this workflow.

Why use PHP 8.3 on AlmaLinux 8?

AlmaLinux 8’s default application streams can be older than the PHP release recommended for current Backdrop deployments. The Remi 8.3 stream provides a maintained PHP version while preserving the AlmaLinux 8 package layout and PHP-FPM service name.

Does Backdrop require MariaDB instead of MySQL?

No. Backdrop supports MySQL-compatible databases, including MariaDB, and the php-mysqlnd extension provides the PHP database driver used here. A separate database and user per site keeps permissions easier to audit.

Where are uploaded images stored?

Backdrop stores managed uploads below /var/www/backdrop/files. That directory is intentionally writable by Nginx and should be included in backups, while the rest of the code remains read-only to the web process.

Samrat Ghosh
Written by

Samrat Ghosh

Founder & Infrastructure Engineer

Samrat Ghosh is the founder of VPSLake, where he builds and runs the remote desktop and VPS hosting infrastructure the company is built on. He writes hands-on guides about RDP, Windows Server, VPS management and secure remote access - the practical documentation he wishes had…

Previous Article

5 Best Hostinger VPS Alternatives in 2026

Write a Comment

Leave a Comment

Your email address will not be published. Required fields are marked *

Subscribe to our Newsletter

Subscribe to our email newsletter to get the latest posts delivered right to your email.
Pure inspiration, zero spam ✨