{"id":1025,"date":"2026-11-07T09:00:00","date_gmt":"2026-11-07T09:00:00","guid":{"rendered":"https:\/\/vpslake.com\/blog\/?p=1025"},"modified":"2026-11-07T09:00:00","modified_gmt":"2026-11-07T09:00:00","slug":"install-bludit-cms-nginx-almalinux-8","status":"publish","type":"post","link":"https:\/\/vpslake.com\/blog\/2026\/11\/07\/install-bludit-cms-nginx-almalinux-8\/","title":{"rendered":"How to Install Bludit CMS with Nginx on AlmaLinux 8"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">To install Bludit CMS with Nginx on AlmaLinux 8, you will configure PHP-FPM, download the current Bludit release, and publish it over HTTPS. A fresh VPS with DNS already configured should reach the browser installer in about 15 minutes, with no database server required.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>A fresh AlmaLinux 8.x VPS with at least 1 GB RAM, 10 GB of free disk space, and a public IPv4 address.<\/li>\n\n\n<li>Root access or a sudo-enabled user connected over SSH. The commands below use <code>sudo<\/code>.<\/li>\n\n\n<li>A domain such as <code>YOUR_DOMAIN<\/code> with an A record pointing to the VPS. Keep ports 80 and 443 available for the website and certificate validation.<\/li>\n\n\n<li>A strong, unique Bludit administrator password. Bludit stores content in files, so MariaDB or MySQL is not needed.<\/li>\n\n\n<li>A <a href=\"https:\/\/vpslake.com\/buy-vps\">VPSLake Linux VPS<\/a> running AlmaLinux 8 is a suitable starting point for a small Bludit site.<\/li>\n\n\n<li>The latest <a href=\"https:\/\/docs.bludit.com\/en\/getting-started\/requirements\" target=\"_blank\" rel=\"noopener\">Bludit requirements<\/a> call for PHP 8.0 or newer plus the <code>mbstring<\/code>, <code>gd<\/code>, <code>dom<\/code>, and <code>json<\/code> modules.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Install Nginx and PHP-FPM<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">AlmaLinux 8 uses <code>dnf<\/code>, while the Remi PHP stream provides a current PHP branch that meets Bludit 3.22.0\u2019s PHP requirement.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo dnf update -y\nsudo dnf install -y epel-release firewalld nginx curl unzip bind-utils policycoreutils-python-utils\nsudo dnf install -y https:\/\/rpms.remirepo.net\/enterprise\/remi-release-8.rpm\nsudo dnf module reset php -y\nsudo dnf module enable php:remi-8.3 -y\nsudo dnf install -y php php-fpm php-cli php-gd php-mbstring php-xml php-curl php-zip php-opcache\nsudo sed -ri 's\/^[;[:space:]]*user[[:space:]]*=.*\/user = nginx\/; s\/^[;[:space:]]*group[[:space:]]*=.*\/group = nginx\/; s\/^[;[:space:]]*listen\\.owner[[:space:]]*=.*\/listen.owner = nginx\/; s\/^[;[:space:]]*listen\\.group[[:space:]]*=.*\/listen.group = nginx\/' \/etc\/php-fpm.d\/www.conf\nsudo systemctl enable --now firewalld nginx php-fpm\nsudo systemctl restart php-fpm\nphp -v\nphp -m | grep -E 'dom|gd|json|mbstring'<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The version check should show PHP 8.3.x, followed by <code>dom<\/code>, <code>gd<\/code>, <code>json<\/code>, and <code>mbstring<\/code>. Patch numbers can change as the repositories publish updates. PHP-FPM will listen on <code>\/run\/php-fpm\/www.sock<\/code>, which the Nginx server block uses later.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Download Bludit and set secure permissions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Bludit is a flat-file CMS, so the application archive and the writable <code>bl-content<\/code> directory replace the database setup used by many other PHP applications.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd \/tmp\ncurl -fL -o bludit.zip https:\/\/www.bludit.com\/releases\/bludit-3-22-0.zip\nsudo unzip -q bludit.zip -d \/tmp\nsudo install -d \/var\/www\/bludit\nsudo cp -a \/tmp\/bludit-3-22-0\/. \/var\/www\/bludit\/\nsudo chown -R root:nginx \/var\/www\/bludit\nsudo find \/var\/www\/bludit -type d -exec chmod 0750 {} \\;\nsudo find \/var\/www\/bludit -type f -exec chmod 0640 {} \\;\nsudo chown -R nginx:nginx \/var\/www\/bludit\/bl-content\nsudo find \/var\/www\/bludit\/bl-content -type d -exec chmod 0770 {} \\;\nsudo find \/var\/www\/bludit\/bl-content -type f -exec chmod 0660 {} \\;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The archive is pinned to Bludit 3.22.0 so a future release cannot silently change this installation. Root owns the code, while PHP-FPM can write only the content area that stores pages, settings, users, uploads, and workspace data.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Keep SELinux enforcing and label those two areas according to how they are used:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo semanage fcontext -a -t httpd_sys_content_t '\/var\/www\/bludit(\/.*)?'\nsudo semanage fcontext -a -t httpd_sys_rw_content_t '\/var\/www\/bludit\/bl-content(\/.*)?'\nsudo restorecon -Rv \/var\/www\/bludit<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Create the Nginx server block<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Bludit routes friendly URLs through <code>index.php<\/code>; the protected locations prevent direct access to its JSON data and executable core files.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Create <code>\/etc\/nginx\/conf.d\/bludit.conf<\/code>, replacing <code>YOUR_DOMAIN<\/code> with the hostname in your DNS record:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>server {\n    listen 80;\n    listen [::]:80;\n    server_name YOUR_DOMAIN;\n\n    root \/var\/www\/bludit;\n    index index.php;\n    client_max_body_size 16m;\n\n    location ^~ \/bl-content\/databases\/ { deny all; }\n    location ^~ \/bl-content\/pages\/ { deny all; }\n    location ^~ \/bl-content\/workspaces\/ { deny all; }\n    location ~* ^\/bl-kernel\/.*\\.php$ { deny all; }\n\n    location \/ {\n        try_files $uri $uri\/ \/index.php?$args;\n    }\n\n    location ~ \\.php$ {\n        try_files $uri =404;\n        include fastcgi_params;\n        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n        fastcgi_param HTTPS $https if_not_empty;\n        fastcgi_pass unix:\/run\/php-fpm\/www.sock;\n    }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Write the file with your editor, then test before reloading Nginx:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo vi \/etc\/nginx\/conf.d\/bludit.conf\nsudo nginx -t\nsudo systemctl reload nginx<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Expected output is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>nginx: the configuration file \/etc\/nginx\/nginx.conf syntax is ok\nnginx: configuration file \/etc\/nginx\/nginx.conf test is successful<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>~* ^\/bl-kernel\/.*\\.php$<\/code> expression is a real regular-expression match. A <code>^~<\/code> location containing <code>*.php<\/code> would treat the asterisk literally and would not protect nested PHP files.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Open the firewall and enable HTTPS<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Allow SSH for administration, HTTP for the Let\u2019s Encrypt challenge, and HTTPS for the finished site. If your VPS has a separate provider firewall, allow the same TCP ports there.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo firewall-cmd --permanent --zone=public --add-service=ssh\nsudo firewall-cmd --permanent --zone=public --add-service=http\nsudo firewall-cmd --permanent --zone=public --add-service=https\nsudo firewall-cmd --reload\nsudo firewall-cmd --list-services<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Confirm that <code>YOUR_DOMAIN<\/code> resolves to this server before requesting a certificate:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>dig +short YOUR_DOMAIN<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Install the Nginx Certbot plugin and let it add the TLS listener and HTTP-to-HTTPS redirect:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo dnf install -y certbot python3-certbot-nginx\nsudo certbot --nginx --redirect --agree-tos --no-eff-email -m YOUR_EMAIL -d YOUR_DOMAIN<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Replace <code>YOUR_EMAIL<\/code> with an address that receives renewal notices. Certbot needs the domain to resolve publicly and port 80 to reach this VPS. Its final output should say that the certificate was successfully deployed.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5: Finish the Bludit setup in your browser<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The web installer creates the site configuration and administrator account in <code>bl-content<\/code>, so no database credentials are involved.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Open <code>https:\/\/YOUR_DOMAIN<\/code> in a browser. Select the installer language, enter a site name, choose an administrator username, and create a long unique password. Save the password in a password manager, then submit the form and sign in at the administrator address shown by Bludit.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you see a permission warning, stop the installer and run the following commands before trying again:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo chown -R nginx:nginx \/var\/www\/bludit\/bl-content\nsudo restorecon -Rv \/var\/www\/bludit\/bl-content\nsudo systemctl restart php-fpm<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Bludit\u2019s <a href=\"https:\/\/docs.bludit.com\/en\/webservers\/nginx\" target=\"_blank\" rel=\"noopener\">official Nginx notes<\/a> explain the front-controller rule and the sensitive directories that should not be served directly. The site should now load at its HTTPS address, and the administrator panel should allow you to create a test page and upload an image.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Verify the Bludit installation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Run these checks from SSH, then open the site in a private browser window to confirm the certificate and login session work together.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl is-active nginx php-fpm firewalld\nsudo nginx -t\nphp -m | grep -E 'dom|gd|json|mbstring'\ncurl -fsSI https:\/\/YOUR_DOMAIN<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">After the installer completes, expect four <code>active<\/code> lines, a successful Nginx test, the four PHP modules, and an HTTPS response such as <code>HTTP\/2 200<\/code>. A <code>302<\/code> redirect to the installer is normal before the browser setup is complete.<\/p>\n\n\n\n<aside class=\"vl-element vl-cta-banner\" aria-label=\"Host Bludit on Linux\">\n\t<div class=\"vl-cta-banner__content\">\n\t\t<p class=\"vl-cta-banner__eyebrow\">AlmaLinux VPS<\/p>\n\t\t<h3 class=\"vl-cta-banner__title\">Host Bludit on Linux<\/h3>\n\t\t<p class=\"vl-cta-banner__text\">Launch a secure Bludit site with Nginx and HTTPS on AlmaLinux 8.<\/p>\n\t<\/div>\n\t<a class=\"vl-cta-banner__button\" href=\"\/buy-vps\" aria-label=\"View Linux VPS plans\">View Linux VPS plans<\/a>\n<\/aside>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">502 Bad Gateway<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Nginx cannot reach PHP-FPM, usually because the service is stopped or the socket path differs from the server block. Check <code>sudo systemctl status php-fpm<\/code>, confirm that <code>\/run\/php-fpm\/www.sock<\/code> exists, and restart PHP-FPM after rechecking the pool settings in <code>\/etc\/php-fpm.d\/www.conf<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The installer says <code>bl-content<\/code> is not writable<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>nginx<\/code> account needs write access and an SELinux writable label on that directory. Run the ownership and <code>restorecon<\/code> commands from Step 5, then check <code>sudo ls -Zd \/var\/www\/bludit\/bl-content<\/code>; the label should include <code>httpd_sys_rw_content_t<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Friendly URLs return 404, but the home page loads<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The request may be reaching another Nginx server block, or the front-controller fallback was changed. Run <code>sudo nginx -T | grep -A8 -B2 'server_name YOUR_DOMAIN'<\/code>, verify <code>try_files $uri $uri\/ \/index.php?$args;<\/code>, and reload Nginx after correcting the file.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Certbot reports a timeout or failed validation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The DNS A record may still point to another address, or port 80 may be blocked by firewalld, the VPS control panel, or an upstream network firewall. Compare <code>dig +short YOUR_DOMAIN<\/code> with the VPS public IP, allow HTTP, and rerun Certbot after DNS has updated.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Hardening and maintenance<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Back up the complete <code>\/var\/www\/bludit<\/code> tree, especially <code>bl-content<\/code>, before upgrades; it contains the pages, users, site settings, and uploaded files.<\/li>\n\n\n<li>Keep AlmaLinux, PHP, Nginx, and Bludit updated. Read the release notes and take a backup before replacing files within the same Bludit major version.<\/li>\n\n\n<li>Test certificate renewal with <code>sudo certbot renew --dry-run<\/code> after HTTPS is working.<\/li>\n\n\n<li>Keep SELinux enforcing and do not make the whole document root writable. Add write access only to a directory that a specific Bludit plugin genuinely needs.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">FAQ<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Does Bludit require MariaDB or MySQL?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No. Bludit is a flat-file CMS and stores its content and configuration as files and JSON beneath <code>bl-content<\/code>. That makes the installation smaller, but file backups are essential because there is no database dump to restore.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Can I install Bludit without a domain name?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You can test it over the VPS IP address, but a domain is the practical choice for a public site. This guide uses Let\u2019s Encrypt, whose HTTP validation requires a publicly resolvable domain.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Why use PHP 8.3 on AlmaLinux 8?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The default AlmaLinux 8 PHP stream may be older than Bludit\u2019s current minimum. The Remi 8.3 module supplies a maintained PHP branch while preserving the AlmaLinux PHP-FPM service and socket layout used here.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Where should I look when a page or image disappears?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Start with <code>\/var\/www\/bludit\/bl-content<\/code>, then inspect the Nginx error log at <code>\/var\/log\/nginx\/error.log<\/code> and the PHP-FPM journal with <code>sudo journalctl -u php-fpm<\/code>. Restore the latest complete file backup rather than creating broad permissions if content is missing or unreadable.<\/p>\n\n\n\n<script type=\"application\/ld+json\">{\"@context\": \"https:\/\/schema.org\", \"@type\": \"FAQPage\", \"mainEntity\": [{\"@type\": \"Question\", \"name\": \"Does Bludit require MariaDB or MySQL?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"No. Bludit is a flat-file CMS and stores its content and configuration as files and JSON beneath `bl-content`. That makes the installation smaller, but file backups are essential because there is no database dump to restore.\"}}, {\"@type\": \"Question\", \"name\": \"Can I install Bludit without a domain name?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"You can test it over the VPS IP address, but a domain is the practical choice for a public site. This guide uses Let\u2019s Encrypt, whose HTTP validation requires a publicly resolvable domain.\"}}, {\"@type\": \"Question\", \"name\": \"Why use PHP 8.3 on AlmaLinux 8?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"The default AlmaLinux 8 PHP stream may be older than Bludit\u2019s current minimum. The Remi 8.3 module supplies a maintained PHP branch while preserving the AlmaLinux PHP-FPM service and socket layout used here.\"}}, {\"@type\": \"Question\", \"name\": \"Where should I look when a page or image disappears?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Start with `\/var\/www\/bludit\/bl-content`, then inspect the Nginx error log at `\/var\/log\/nginx\/error.log` and the PHP-FPM journal with `sudo journalctl -u php-fpm`. Restore the latest complete file backup rather than creating broad permissions if content is missing or unreadable.\"}}]}<\/script>\n\n","protected":false},"excerpt":{"rendered":"Install Bludit CMS with Nginx on AlmaLinux 8 using PHP-FPM, SELinux, firewalld, HTTPS, and secure flat-file permissions on a fresh VPS in minutes.","protected":false},"author":1,"featured_media":1026,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_singular_sidebar":"","csco_page_header_type":"","csco_page_load_nextpost":"","footnotes":""},"categories":[5,9],"tags":[94,127,129,125,128],"class_list":["post-1025","post","type-post","status-publish","format-standard","has-post-thumbnail","category-guides","category-vps-hosting","tag-almalinux-8","tag-bludit","tag-cms","tag-nginx","tag-php-fpm","cs-entry"],"_links":{"self":[{"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/posts\/1025","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/comments?post=1025"}],"version-history":[{"count":1,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/posts\/1025\/revisions"}],"predecessor-version":[{"id":3926,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/posts\/1025\/revisions\/3926"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/media\/1026"}],"wp:attachment":[{"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/media?parent=1025"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/categories?post=1025"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/tags?post=1025"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}