Deployment guide

Bludit Flat-File CMS 3.22.0

Overview

This guide covers launching and using the Bludit Flat-File CMS 3.22.0 on Ubuntu 24.04 AMI from SecureAnyCloud on Amazon EC2. It is one version of the SecureAnyCloud BookStack, CMS, Blogs and Wikis listing on AWS Marketplace. You pick it as the software version when you subscribe and launch.

Bludit is an open-source content management system for websites and blogs that needs no database. Pages, settings and users are stored as small JSON files, so the whole site is a folder you can back up and move with ordinary file tools. You write in a browser-based editor, publish pages and posts, organise them with categories and tags, and change the look with themes and plugins.

The SecureAnyCloud image ships Bludit 3.22.0 (the official source release, checksum verified) with PHP 8.3 FPM, nginx, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent. First boot installs Bludit's standard starter site: four example pages and the Alternative theme.

What you get:

  • No web installer, no default password. Bludit's own install.php takes over a site on the first visit, and it installs with the password demo123 when asked for a demo. On this image, the installer is never in the web root. Your instance's first boot runs Bludit's installer itself, before the web server starts, with an admin password generated on your instance and written to /root/bludit-credentials.txt. Nothing from the image build (no user, password hash or token) ships in the image.
  • HTTPS from the first boot. nginx serves Bludit on port 443 with a certificate generated on your instance's first boot. Port 80 redirects to HTTPS.
  • Fail closed. nginx and PHP refuse to start until first boot has finished.
  • PHP only through Bludit's front controller. nginx hands PHP nothing but /index.php. Bludit's flat-file databases (users, settings, pages) are never served, and a PHP file in the uploads folder is never run. Uploads are served as static files with a policy that stops an uploaded SVG or HTML file from running script.
  • Login lockout on. Ten failed sign-ins from one address block that address for five minutes. The address comes from the connection, never from a header a client sends.
  • Hardened defaults. The Bludit code is owned by root and read-only to PHP. PHP can write only the content folder, cannot run shell commands and is confined to Bludit's folders. nginx and PHP are blocked from the instance metadata service, and the AMI requires IMDSv2. Requests for a host name the instance does not serve are dropped, and Bludit's links always use the host name you configure, never the one a request claims.
  • A separate content volume. Everything Bludit stores lives on its own 20 GiB EBS volume at /var/lib/bludit-content, which you can resize or snapshot on its own.
  • Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
  • Default user: ubuntu, architecture: x86_64, recommended instance type: m5.large

Prerequisites

  • An AWS account subscribed to the listing, an EC2 key pair, and a VPC subnet with a route to the internet (or a private route you use for management)
  • A security group that allows TCP 22 (SSH), TCP 443 (the site and its admin panel) and TCP 80 (redirects to HTTPS) from the networks that should reach them. A public website needs 443 and 80 open to everyone. Keep 22 to your own networks.
1

Launch the instance

In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Pick Bludit Flat-File CMS 3.22.0 on Ubuntu 24.04 as the software version, choose your Region, then choose Launch through EC2.

Choose m5.large, your key pair and a security group as described above. Bludit is light, so a smaller instance is fine for a small site. Keep the second EBS volume in the launch settings, because it is where your site lives.

Alternatively, launch with the AWS CLI. Replace the values in angle brackets:

aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
  --instance-type m5.large --key-name <your-key-pair> \
  --security-group-ids <your-security-group> --subnet-id <your-subnet> \
  --metadata-options HttpTokens=required,HttpEndpoint=enabled \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=bludit}]'
2

Connect to your instance

Connect to Bludit Flat-File CMS 3.22.0 on Ubuntu 24.04 over SSH as the ubuntu user:

ssh -i <your-key.pem> ubuntu@<public-ip>
3

Check the services

First boot takes a few seconds. After it finishes, nginx, PHP and the first-boot unit are active:

systemctl is-active nginx php8.3-fpm bludit-firstboot
active active active

nginx serves ports 80 and 443. PHP listens on a local socket only, so the only open ports are 22, 80 and 443:

sudo ss -tlnp | awk 'NR==1 || /nginx|sshd|php/' | awk '{print $1, $4, $6}' | sed -E 's/,pid=[0-9]+,fd=[0-9]+//g'
State Local Peer LISTEN 0.0.0.0:443 users:(("nginx"),("nginx"),("nginx")) LISTEN 0.0.0.0:80 users:(("nginx"),("nginx"),("nginx")) LISTEN 0.0.0.0:22 users:(("sshd"),("systemd")) LISTEN [::]:443 users:(("nginx"),("nginx"),("nginx")) LISTEN [::]:80 users:(("nginx"),("nginx"),("nginx")) LISTEN [::]:22 users:(("sshd"),("systemd"))
grep -oE "BLUDIT_VERSION', +'[0-9.]+'" /var/www/bludit/bl-kernel/boot/init.php php -v | head -1
BLUDIT_VERSION', '3.22.0' PHP 8.3.6 (cli) (built: Oct 19 2026 15:16:58) (NTS)
4

Get your URL and password

The credentials file holds the address the site is served as (your instance's public DNS name by default), the admin panel address, the user, and the password generated on this instance. Show it:

sudo cat /root/bludit-credentials.txt
BLUDIT_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/ BLUDIT_ADMIN_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/admin/ BLUDIT_ADMIN_USER=admin BLUDIT_ADMIN_PASSWORD=<24 letters and digits>

To show the address lines without the password, run:

sudo grep -E '^BLUDIT_(URL|ADMIN_URL|ADMIN_USER)=' /root/bludit-credentials.txt
BLUDIT_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/ BLUDIT_ADMIN_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/admin/ BLUDIT_ADMIN_USER=admin
5

Visit your site and sign in

Open BLUDIT_URL in your browser. The certificate is self-signed and generated on your instance, so accept the browser warning once, or install your own certificate (Step 10). Bludit's starter site opens with its example pages.

The example pages tell you to sign in with the password you set during installation. On this image, that is the BLUDIT_ADMIN_PASSWORD from Step 4. Open BLUDIT_ADMIN_URL and sign in as admin.

The dashboard shows your published pages, drafts and scheduled posts, the visits counter and Bludit's notifications, with the admin menu on the left.

6

Write and publish a page

Choose New content. Give the page a title and write the body in the editor. The toolbar adds headings, lists, tables, links, images and embedded media.

Use Options for the page type, category, tags, cover image and URL. Choose Save to publish the page, or use the status switch to keep it as a draft or schedule it.

7

Site settings, users, themes and plugins

Settings > General sets the site title, slogan, description and footer. The other tabs cover the URL (Advanced), SEO, social links, image sizes, language and the logo.

Users adds editors and authors. Themes changes the look. Plugins switches on extras such as a contact form, a sitemap or the REST API.

Leave Settings > Advanced > URL as it is. If you change the host name with bludit-set-hostname (Step 10), that command sets the URL for you.

8

Your content volume

Everything Bludit stores (pages, uploads, settings, users and plugin data) is on its own EBS volume. Inspect it:

df -h /var/lib/bludit-content | awk 'NR==1 || /bludit/'
sudo ls /var/lib/bludit-content /var/lib/bludit-content/databases
Filesystem Size Used Avail Use% Mounted on /dev/nvme0n1 20G 176K 19G 1% /var/lib/bludit-content /var/lib/bludit-content: databases lost+found pages tmp uploads workspaces /var/lib/bludit-content/databases: categories.php pages.php plugins security.php site.php syslog.php tags.php users.php

Back it up with an EBS snapshot of that volume, or copy the folder (sudo tar -C /var/lib -czf bludit-content.tar.gz bludit-content).

To grow it, enlarge the volume in EC2 and run sudo resize2fs on its device.

9

Security checks

Port 80 sends browsers to HTTPS, and the health endpoint answers for load balancer checks. The installer, Bludit's databases and its internal PHP files are not reachable:

H=$(sudo grep '^BLUDIT_URL=' /root/bludit-credentials.txt | sed -E 's#^BLUDIT_URL=https://([^/]+)/.*#\1#')
curl -s -o /dev/null -w 'port 80: %{http_code} -> %{redirect_url}\n' --resolve "$H:80:127.0.0.1" "http://$H/admin/"
curl -sk --resolve "$H:443:127.0.0.1" "https://$H/healthz" for p in /install.php '/install.php?demo=true' /bl-content/databases/users.php /bl-kernel/boot/init.php; do
curl -sk -o /dev/null -w "$p: %{http_code}\n" --resolve "$H:443:127.0.0.1" "https://$H$p" done
curl -s -o /dev/null -w 'unknown host name: %{http_code}\n' -H 'Host: example.com' http://127.0.0.1/ || true
port 80: 301 -> https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/admin/ ok /install.php: 404 /install.php?demo=true: 404 /bl-content/databases/users.php: 404 /bl-kernel/boot/init.php: 404 unknown host name: 000

The code 000 means nginx closed the connection without an answer.

Bludit has exactly one user, its site URL is the configured host, and the login lockout is on (ten failures, five minutes):

sudo -u www-data php /usr/local/lib/sac/bludit/bludit-admin.php summary
users=admin:admin url=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com minutesBlocked=5 numberFailuresAllowed=10 blackList=0

Only root can read the credentials file, only the web server can read the user database, and root owns the code:

sudo stat -c '%a %U:%G %n' /root/bludit-credentials.txt /var/lib/bludit-content/databases/users.php /var/www/bludit/index.php
600 root:root /root/bludit-credentials.txt 640 www-data:www-data /var/lib/bludit-content/databases/users.php 644 root:root /var/www/bludit/index.php

The certificate was generated on this instance and names its own addresses:

H=$(sudo grep '^BLUDIT_URL=' /root/bludit-credentials.txt | sed -E 's#^BLUDIT_URL=https://([^/]+)/.*#\1#')
echo | openssl s_client -connect 127.0.0.1:443 -servername "$H" 2>/dev/null | openssl x509 -noout -subject -ext subjectAltName
subject=CN = ec2-<public-ip-dashed>.<region>.compute.amazonaws.com, O = sac X509v3 Subject Alternative Name: DNS:ec2-<public-ip-dashed>.<region>.compute.amazonaws.com, IP Address:<public-ip>, IP Address:<private-ip>, IP Address:127.0.0.1, DNS:localhost

nginx and PHP cannot reach the instance metadata service. PHP cannot run shell commands and is confined to Bludit's folders. nginx hands PHP the configured host name and the real client address from the connection, never values a client sends:

systemctl show nginx -p IPAddressDeny
systemctl show php8.3-fpm -p IPAddressDeny php-fpm8.3 -i 2>/dev/null | grep -E '^(open_basedir|disable_functions|expose_php) ' | cut -d' ' -f1-3 grep -E 'fastcgi_param (HTTP_HOST|HTTP_X_FORWARDED_FOR|HTTP_X_REAL_IP)' /etc/nginx/sites-available/sac-bludit
IPAddressDeny=169.254.169.254/32 fd00:ec2::254/128 168.63.129.16/32 IPAddressDeny=169.254.169.254/32 fd00:ec2::254/128 168.63.129.16/32 disable_functions => exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec expose_php => Off open_basedir => /var/www/bludit/:/var/lib/bludit-content/:/var/lib/php/sessions/:/tmp/ fastcgi_param HTTP_HOST $bludit_host; fastcgi_param HTTP_X_FORWARDED_FOR $remote_addr; fastcgi_param HTTP_X_REAL_IP $remote_addr;

If you lock yourself out with ten wrong passwords, wait five minutes or clear the block list:

sudo bludit-reset-lockout
10

Your own DNS name and certificate

Point a DNS record at the instance, then set the name Bludit is served as. The command below mints a new self-signed certificate for the name. It updates nginx, Bludit's site URL (links, RSS and sitemap) and the URLs in /root/bludit-credentials.txt, and it keeps the name across reboots:

sudo bludit-set-hostname <your-domain>

To use a certificate from your own certificate authority instead, copy it over the generated pair and reload nginx. Running bludit-set-hostname again replaces it with a self-signed certificate.

sudo install -m 0644 <your-domain>.crt /etc/nginx/ssl/bludit.crt
sudo install -m 0600 <your-domain>.key /etc/nginx/ssl/bludit.key
sudo nginx -t && sudo systemctl reload nginx

Once browsers trust the certificate, you can also add an HSTS header (add_header Strict-Transport-Security "max-age=31536000" always;) to the HTTPS server in /etc/nginx/sites-available/sac-bludit.

The image does not send one. Browsers ignore HSTS from a site whose certificate they do not trust, so it only takes effect with a trusted certificate.

11

Password and upgrades

bludit-set-password gives the admin user a new random password, with a new salt and API token, and records it in /root/bludit-credentials.txt. Run it without arguments, or pass your own password (24 to 64 letters and digits) on stdin.

You can also change the password of any user in the admin panel under Users.

sudo bludit-set-password printf '%s\n' '<your-new-password>' | sudo bludit-set-password --stdin

To move to a newer Bludit release later, snapshot the instance and download the release zip from bludit.com or GitHub. Replace index.php and the bl-kernel, bl-languages, bl-plugins and bl-themes folders under /var/www/bludit, and keep them owned by root.

Your site is untouched, because it lives on the content volume. Do not copy the release's install.php into the web root. The image ships the version named in the listing.

12

Server components

  • Bludit code (root-owned): /var/www/bludit
  • Content (pages, uploads, settings, users): /var/lib/bludit-content (own EBS volume; /var/www/bludit/bl-content points to it)
  • nginx site: /etc/nginx/sites-available/sac-bludit
  • PHP settings: /etc/php/8.3/fpm/conf.d/99-sac-bludit.ini
  • Certificate and key: /etc/nginx/ssl/
  • First boot script: /usr/local/sbin/bludit-firstboot.sh
  • Helpers: /usr/local/sbin/bludit-set-hostname, /usr/local/sbin/bludit-set-password, /usr/local/sbin/bludit-reset-lockout
  • Credentials: /root/bludit-credentials.txt (mode 0600)
13

Security recommendations

  • Allow port 22 in the security group from your own networks only.
  • Keep the admin password secret, and rotate it if it may have been shared (Step 11). Give other people their own Editor or Author accounts instead of sharing admin.
  • Use your own DNS name and a certificate your browsers trust (Step 10).
  • Keep the operating system patched. Unattended security upgrades are on, and sudo apt-get update && sudo apt-get upgrade applies everything else.
  • Snapshot the content volume regularly (Step 8).

Support and licensing

Bludit is open source under the MIT licence (a copy is at /usr/share/doc/bludit/LICENSE). There is no per-user or per-CPU licence fee. The AMI price covers SecureAnyCloud's hardening, first-boot setup and support.

  • Email: sales@secureanycloud.com
  • Website: https://secureanycloud.com
  • Support: 24/7, with a 24-hour response SLA

Deploy on AWS

Launch Bludit Flat-File CMS 3.22.0 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.

View on Marketplace

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on AWS