Bludit Flat-File CMS 3.22.0 on AWS User Guide
Overview
This guide covers launching and using the Bludit Flat-File CMS 3.22.0 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg 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 cloudimg image adds:
- No web installer, no default password. Bludit's own
install.phptakes over a site on the first visit (and installs with the passworddemo123when 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, 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.
What is on the image: Bludit 3.22.0 (the official source release, checksum verified), 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.
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.
Step 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 and your Region, then Launch through EC2. Choose m5.large (Bludit is light; a smaller instance is fine for a small site), your key pair and a security group as above. Keep the second EBS volume in the launch settings: it is where your site lives.
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}]'
Step 2: Connect to your instance
| Version | SSH user |
|---|---|
| Bludit Flat-File CMS 3.22.0 on Ubuntu 24.04 | ubuntu |
ssh -i <your-key.pem> ubuntu@<public-ip>
Step 3: Check the services
First boot takes a few seconds. Then 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)
Step 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 with:
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>
The address lines alone (no password) come from:
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
Step 5: Visit your site and sign in
Open BLUDIT_URL in your browser. The certificate is self signed (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:

Step 6: Write and publish a page
Choose New content. Give the page a title, write the body in the editor (headings, lists, tables, links, images and embedded media from the toolbar), and use Options for the page type, category, tags, cover image and URL. Save publishes it, or keep it as a draft or schedule it from the status switch.

Step 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 and Plugins switches on extras such as a contact form, a sitemap or the REST API.


Leave Settings > Advanced > URL as it is unless you change the host name with bludit-set-hostname (Step 10), which sets it for you.
Step 8: Your content volume
Everything Bludit stores (pages, uploads, settings, users and plugin data) is on its own EBS volume:
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.
Step 9: Security checks
Port 80 sends browsers to HTTPS, the health endpoint answers for load balancer checks, and 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
(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/cloudimg/bludit/bludit-admin.php summary
users=admin:admin
url=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com
minutesBlocked=5
numberFailuresAllowed=10
blackList=0
The credentials file is readable by root only, the user database by the web server only, and the code is owned by root:
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 = cloudimg
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, and 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/cloudimg-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
Step 10: Your own DNS name and certificate
Point a DNS record at the instance, then set the name Bludit is served as. This mints a new self signed certificate for the name, updates nginx, Bludit's site URL (links, RSS and sitemap) and the URLs in /root/bludit-credentials.txt, and 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 one):
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/cloudimg-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.
Step 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 passwords for 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, download the release zip from bludit.com or GitHub, and replace index.php and the bl-kernel, bl-languages, bl-plugins and bl-themes folders under /var/www/bludit (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.
Step 12: Server components
| Component | Path |
|---|---|
| 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/cloudimg-bludit |
| PHP settings | /etc/php/8.3/fpm/conf.d/99-cloudimg-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) |
Step 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 upgradeapplies 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 cloudimg's hardening, first boot setup and support.
- Email: support@cloudimg.co.uk
- Website: https://www.cloudimg.co.uk
- Support: 24/7, with a 24 hour response SLA