Applications AWS

REDAXO CMS 5.21.6 on AWS User Guide

| Product: REDAXO CMS 5.21.6 on Ubuntu 24.04 on AWS

Overview

This guide covers launching and using the REDAXO CMS 5.21.6 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.

REDAXO is a free and open source content management system written in PHP. You build a site from a page tree (Structure), your own Templates and Modules, a Mediapool for files and the Media Manager for image sizes, with users and roles, multilingual content and a large addon ecosystem installed through REDAXO's Installer.

The cloudimg image adds:

  • The current release, verified. REDAXO 5.21.6 is the official release file, checked against its published SHA-256 and, file by file, against a manifest of the whole release. 5.21.3 to 5.21.6 fix a critical and several high severity advisories that affect 5.21.2 and earlier (among them GHSA-px8f-whj8-hrpq, an authentication bypass in the history plugin).
  • No reachable setup wizard, no shared database. REDAXO's browser setup creates the site and the first administrator for whoever opens it first. This image ships no database at all (the MariaDB data directory is empty) and no configuration file. Your instance's first boot initialises its own database and runs REDAXO's own console setup before the web server starts. Afterwards the configuration says setup is finished, and nginx refuses every request for the setup wizard.
  • Secrets of your instance's own, never on a command line. The database password, the administrator password and the TLS key are generated on your instance; nothing from the image build is reused. REDAXO's console reads the passwords from a file only it and root can read, never from its command line, so they never reach a process list or a log.
  • HTTPS from the first boot. nginx serves REDAXO on port 443 with a certificate generated on your instance's first boot. Port 80 redirects to HTTPS, and REDAXO itself is set to HTTPS with secure session cookies.
  • Fail closed. nginx does not start until first boot has finished; if first boot cannot complete, the site stays offline rather than open.
  • Only REDAXO's front controllers run PHP. The site runs through /index.php and the backend through /redaxo/; every other PHP file is never run. REDAXO's source, data (with the configuration), cache and console folders are never served. The folders PHP writes to and serves, media and assets, are static only: every file gets nosniff and a sandboxing content security policy, and only passive types (images, PDF, fonts, audio and video) open in the browser; anything else, SVG and HTML included, is sent as a download (stylesheets and scripts still load on pages).
  • A rate-limited sign in. nginx allows 10 backend sign-in attempts a minute from one address (after a burst of 10), using the address of the connection, never a header a client sends; REDAXO adds its own delay after three failed attempts on an account.
  • Links from other sites cannot act for you. Backend pages, the backend's sign out and safe mode switches and REDAXO's API calls only work when they come from your site itself (Step 9).
  • The real host and client address. nginx hands REDAXO the host name you configure and nothing a request claims, and REDAXO's website address is set to it. nginx removes X-Forwarded-For, Client-IP and the other forwarding headers, and REDAXO records the address of the connection.
  • Hardened defaults. REDAXO's own design needs PHP to write its assets, media, redaxo/cache, redaxo/data and redaxo/src folders (its Installer adds addons there), so those belong to the web server with no access for other users; the front controllers belong to root. Root never runs REDAXO's code: the cloudimg tools run REDAXO's console as the web server's user. PHP cannot run shell commands and is confined to the site folder. MariaDB has no network listener at all (REDAXO talks to it over a local socket) and its root account signs in only through the socket as the operating system's root. nginx, PHP, MariaDB and the first boot service are blocked from the instance metadata service, the AMI requires IMDSv2, and requests for a host name the instance does not serve are dropped.
  • Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.

What is on the image: REDAXO 5.21.6 (the upstream release, checksum verified), MariaDB 10.11, PHP 8.3 FPM, nginx, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent.

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 (REDAXO) and TCP 80 (redirects to HTTPS) from the networks that should reach them. Keep 22 to your own networks. Open 443 to your visitors for a public site, or only to your team while you build it.

Step 1: Launch the instance

In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick REDAXO CMS 5.21.6 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose m5.large, your key pair and a security group as above. The root volume holds the site, the database and your media: size it for your content.

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=redaxo}]'

Step 2: Connect to your instance

Version SSH user
REDAXO CMS 5.21.6 on Ubuntu 24.04 ubuntu
ssh -i <your-key.pem> ubuntu@<public-ip>

Step 3: Check the services

First boot takes under a minute (it creates the database and runs REDAXO's setup). Then nginx, PHP, MariaDB and the first boot unit are active:

systemctl is-active nginx php8.3-fpm mariadb redaxo-firstboot
active
active
active
active

nginx serves ports 80 and 443; PHP and MariaDB listen on local sockets only, so the only open ports are 22, 80 and 443:

sudo ss -tlnp | awk 'NR==1 || /nginx|sshd|php|maria/' | awk '{print $1, $4, $6}' | sed -E 's/,pid=[0-9]+,fd=[0-9]+//g'
State Local Peer
LISTEN 0.0.0.0:22 users:(("sshd"),("systemd"))
LISTEN 0.0.0.0:80 users:(("nginx"),("nginx"),("nginx"))
LISTEN 0.0.0.0:443 users:(("nginx"),("nginx"),("nginx"))
LISTEN [::]:22 users:(("sshd"),("systemd"))
LISTEN [::]:80 users:(("nginx"),("nginx"),("nginx"))
LISTEN [::]:443 users:(("nginx"),("nginx"),("nginx"))

How the download was verified, and that every file is still the release's:

cat /usr/share/doc/redaxo/RELEASE
cd /var/www/redaxo && sudo sha256sum -c --quiet /usr/share/doc/redaxo/REDAXO-5.21.6.sha256 && echo "1953 files match the REDAXO 5.21.6 release"
php -v | head -1
mariadb --version
REDAXO 5.21.6
source https://github.com/redaxo/redaxo/releases/download/5.21.6/redaxo_5.21.6.zip
sha256 efc5f39151c52114700b040a075b93736e711921f846932966adb90e429e2dff
licence MIT (LICENSE.md sha256 7559f14ab6f510dacdd03cb1cb82c60dd8e0da0db7226524a7e68debc89b01da; attribution rider: the backend keeps the www.redaxo.org link and the REDAXO logo)
1953 files match the REDAXO 5.21.6 release
PHP 8.3.6 (cli) (built: Oct 19 2026 15:16:58) (NTS)
mariadb  Ver 15.1 Distrib 10.11.14-MariaDB, for debian-linux-gnu (x86_64) using  EditLine wrapper

(Files REDAXO adds later, such as your media and its caches, are not in the list; the check covers every file the release shipped.)

Step 4: Get your sign-in details

The credentials file holds the address REDAXO is served as (your instance's public DNS name by default), the backend address, the administrator's user name and password, and the database credentials, all generated on this instance. Show it with:

sudo cat /root/redaxo-credentials.txt
REDAXO_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/
REDAXO_BACKEND_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/redaxo/
REDAXO_ADMIN_USERNAME=cloudimg
REDAXO_ADMIN_PASSWORD=<24 letters and digits>
REDAXO_DB_NAME=redaxo
REDAXO_DB_USER=redaxo
REDAXO_DB_PASSWORD=<48 hexadecimal characters>

Step 5: Visit the site and sign in

Open REDAXO_URL in your browser. The certificate is self signed (generated on your instance), so your browser warns once: compare the certificate's SHA-256 fingerprint with the one on the instance (sudo openssl x509 -in /etc/nginx/ssl/redaxo.crt -noout -fingerprint -sha256) and continue, or install a certificate from your own certificate authority (Step 11). A fresh site shows a starter page, an ordinary REDAXO article you can edit or delete:

The REDAXO starter page of a fresh site

Open REDAXO_BACKEND_URL and sign in with REDAXO_ADMIN_USERNAME and REDAXO_ADMIN_PASSWORD:

The REDAXO backend sign in page

The backend opens on Structure, the page tree, with the starter article Home:

The REDAXO structure page with the Home article

Open the backend from /redaxo/ and move around by its menu: links into the backend that come from another site, a bookmark or the address bar are refused (Step 9), while /redaxo/ itself always opens. The administrator can do everything; for editors, create accounts and roles under User with only the permissions they need.

Step 6: Build your site

REDAXO separates the page tree from its presentation. Templates hold the page layout, Modules define the content blocks editors fill in, and articles in Structure combine them. Open an article to edit its content blocks:

The REDAXO content editor for the Home article

The starter page uses a template called cloudimg Starter with no modules; create your own template and modules, then switch the article over or replace it. Upload images and documents in the Mediapool; they are served from /media/ as static files:

The REDAXO media pool

Addons extend REDAXO: AddOns lists the installed ones, and the Installer downloads more from the REDAXO repository (for example yrewrite for friendly URLs, which this image's nginx configuration already routes to REDAXO, or yform for forms). The Installer contacts www.redaxo.org only when you open it.

Step 7: Settings and REDAXO's console

System shows the website address (set to your host name), the website name, the error e-mail address and REDAXO's version:

The REDAXO System settings page

Set your own Email address in case of errors there (it starts as admin@example.com). REDAXO's command line console runs as the web server's user through redaxo-console; it prints a notice that REDAXO's top folder belongs to root, which is deliberate on this image:

sudo redaxo-console --version
sudo redaxo-console config:get use_https | tail -1
sudo grep -x 'setup: false' /var/www/redaxo/redaxo/data/core/config.yml

 [WARNING] Current user: www-data
           Owner of redaxo: root

           Running the console with a different user might cause unexpected
           side-effects.

REDAXO 5.21.6
true
setup: false

sudo redaxo-console list shows every command (clearing the cache, users, addons, database dumps). Never pass a password to it as an argument; use redaxo-set-password (Step 12).

REDAXO sends a content security policy that keeps the backend out of other sites' frames, and nginx adds one that lets its pages connect only to your own server (browsers apply both):

H=$(sed -n 's/^set \$redaxo_host "\(.*\)";$/\1/p' /etc/nginx/redaxo-host.conf)
curl -sk -D - -o /dev/null --resolve "$H:443:127.0.0.1" "https://$H/redaxo/" | tr -d '\r' | grep -i '^content-security-policy'
content-security-policy: frame-ancestors 'self'
content-security-policy: connect-src 'self'; frame-ancestors 'self'

Step 8: Your data

Everything that makes your site lives in the redaxo database in MariaDB, your files in /var/www/redaxo/media, and REDAXO's own data (the configuration, addon data) in /var/www/redaxo/redaxo/data. The caches in /var/www/redaxo/redaxo/cache are rebuilt automatically. Keep redaxo/data/core/config.yml with your backup: it holds this site's database password.

Back up the database to a file only root can read (MariaDB's root signs in over the local socket without a password, so no password appears on the command line), and the files:

sudo sh -c 'umask 077; mysqldump --single-transaction redaxo > /root/redaxo-$(date +%F).sql'
sudo tar -C /var/www/redaxo -czf /root/redaxo-files-$(date +%F).tgz media redaxo/data

REDAXO's Backup addon in the backend exports the database too. For a whole-instance copy, snapshot the EBS volume.

Step 9: Security checks

Port 80 sends browsers to HTTPS, the health endpoint answers for load balancer checks, and the configuration, REDAXO's source, cache and console, the setup wizard and stray PHP files in the writable folders are not reachable:

H=$(sed -n 's/^set \$redaxo_host "\(.*\)";$/\1/p' /etc/nginx/redaxo-host.conf)
curl -s -o /dev/null -w 'port 80: %{http_code} -> %{redirect_url}\n' --resolve "$H:80:127.0.0.1" "http://$H/redaxo/" | sed -E 's#https://[^/]+#https://<your host>#'
curl -sk --resolve "$H:443:127.0.0.1" "https://$H/healthz"
for p in /redaxo/data/core/config.yml /redaxo/src/core/boot.php /redaxo/bin/console /redaxo/cache/ '/redaxo/index.php?page=setup' '/redaxo/index.php?setup_token=x' /media/x.php /assets/x.php; do
  curl -sk -o /dev/null -w "$p: %{http_code}\n" -H 'Sec-Fetch-Site: same-origin' --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://<your host>/redaxo/
ok
/redaxo/data/core/config.yml: 404
/redaxo/src/core/boot.php: 404
/redaxo/bin/console: 404
/redaxo/cache/: 404
/redaxo/index.php?page=setup: 404
/redaxo/index.php?setup_token=x: 404
/media/x.php: 404
/assets/x.php: 404
unknown host name: 000

(000 means nginx closed the connection without an answer.) A backend page opens when the request comes from your own site, and is refused when it comes from anywhere else (another site, a bookmark, the address bar), so a link on another site cannot make your signed-in browser act in the backend:

H=$(sed -n 's/^set \$redaxo_host "\(.*\)";$/\1/p' /etc/nginx/redaxo-host.conf)
for s in same-origin cross-site none; do
  curl -sk -o /dev/null -w "Sec-Fetch-Site $s: %{http_code}\n" -H "Sec-Fetch-Site: $s" --resolve "$H:443:127.0.0.1" "https://$H/redaxo/index.php?page=system/settings"
done
Sec-Fetch-Site same-origin: 200
Sec-Fetch-Site cross-site: 403
Sec-Fetch-Site none: 403

The rule covers backend pages (/redaxo/index.php?page=...), the sign out and safe mode switches and REDAXO's API calls (rex-api-call) anywhere on the site. It lives in /etc/nginx/conf.d/cloudimg-xsite-guard.conf, pinned to your host name by redaxo-set-hostname.

The credentials file is readable by root only, the configuration by the web server only, and the front controllers belong to root; MariaDB has no network listener, and nginx, PHP, MariaDB and first boot cannot reach the instance metadata service:

sudo stat -c '%a %U:%G %n' /root/redaxo-credentials.txt /var/www/redaxo/redaxo/data/core/config.yml /var/www/redaxo/redaxo/data /var/www/redaxo/index.php /var/www/redaxo/redaxo/index.php
sudo mysql -N -e 'SELECT @@skip_networking, @@bind_address'
for u in nginx php8.3-fpm mariadb redaxo-firstboot; do printf '%s: %s\n' "$u" "$(systemctl show -p IPAddressDeny --value $u)"; done
600 root:root /root/redaxo-credentials.txt
640 www-data:www-data /var/www/redaxo/redaxo/data/core/config.yml
750 www-data:www-data /var/www/redaxo/redaxo/data
644 root:root /var/www/redaxo/index.php
644 root:root /var/www/redaxo/redaxo/index.php
1   127.0.0.1
nginx: 169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128
php8.3-fpm: 169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128
mariadb: 169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128
redaxo-firstboot: 169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128

sudo redaxo-cred-roundtrip signs in through the real backend form with the password from the credentials file and checks that wrong passwords are refused.

Step 10: Behind a proxy or load balancer

nginx removes X-Forwarded-For, X-Real-IP, Client-IP and Forwarded from every request, and REDAXO reads the client address from the connection, so the backend's session list and the logs use the address of the connection. Behind an AWS load balancer that is the load balancer's address; nginx's own access log (/var/log/nginx/access.log) records it the same way. To record visitors' addresses, use nginx's real_ip module with set_real_ip_from set to your load balancer's subnet only.

Step 11: Your own DNS name and certificate

Point a DNS record at the instance, then set the name REDAXO is served as. This mints a new self signed certificate for the name, updates nginx (which hands the name to REDAXO), the cross-site rule and REDAXO's website address, clears REDAXO's cache, updates the addresses in /root/redaxo-credentials.txt and keeps the name across reboots:

sudo redaxo-set-hostname <your-domain>

To use a certificate from your own certificate authority instead, copy it over the generated pair and reload nginx (running redaxo-set-hostname again replaces it with a self signed one):

sudo install -m 0644 <your-domain>.crt /etc/nginx/ssl/redaxo.crt
sudo install -m 0600 <your-domain>.key /etc/nginx/ssl/redaxo.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 /etc/nginx/snippets/cloudimg-redaxo-headers.conf. The image does not send one: browsers ignore HSTS from a site whose certificate they do not trust.

Step 12: Passwords, e-mail, addons and upgrades

redaxo-set-password gives the administrator a new random password with REDAXO's own console, signs out every session and records the password in /root/redaxo-credentials.txt. Run it without arguments, or pass your own password (24 to 72 letters and digits) on stdin. Users change their own password under their profile.

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

The setup wizard. REDAXO's backend offers to run setup again (System); on this image the wizard's page is refused by nginx, so it cannot be opened in a browser by anyone. Re-run setup from the console when you need it: sudo redaxo-console setup:run.

E-mail. REDAXO's core sends no mail. Install the PHPMailer addon (shipped, not active) under AddOns and set an SMTP server there before you rely on e-mail from addons.

Addons. Install and update addons through the Installer or AddOns in the backend; REDAXO writes them to redaxo/src/addons and copies their assets to assets. Install only addons you trust: they run with the web server's rights.

Upgrades. The Installer also offers REDAXO core updates (Installer > Update). Take a snapshot first. After an update, /usr/share/doc/redaxo/REDAXO-5.21.6.sha256 describes the old release, so the check in Step 3 then reports the changed files.

Step 13: Server components

Component Path
REDAXO (site front controller root owned) /var/www/redaxo
Backend front controller and console /var/www/redaxo/redaxo/index.php, /var/www/redaxo/redaxo/bin/console
Configuration (this instance's database password) /var/www/redaxo/redaxo/data/core/config.yml
Media and addon assets /var/www/redaxo/media, /var/www/redaxo/assets
Caches (rebuilt automatically) /var/www/redaxo/redaxo/cache
Database (MariaDB datadir) /var/lib/mysql
nginx site, request limits and cross-site link rules /etc/nginx/sites-available/cloudimg-redaxo, /etc/nginx/conf.d/cloudimg-redaxo-guard.conf, /etc/nginx/conf.d/cloudimg-xsite-guard.conf, /etc/nginx/snippets/cloudimg-redaxo-*.conf
PHP settings /etc/php/8.3/fpm/conf.d/99-cloudimg-redaxo.ini
MariaDB settings /etc/mysql/mariadb.conf.d/99-cloudimg-redaxo.cnf
Certificate and key /etc/nginx/ssl/
First boot script and helpers /usr/local/sbin/redaxo-firstboot.sh, /usr/local/lib/cloudimg/redaxo/
Helpers /usr/local/sbin/redaxo-console, redaxo-set-hostname, redaxo-set-password, redaxo-cred-roundtrip
Licence, release, manifest and image notes /usr/share/doc/redaxo/
Credentials /root/redaxo-credentials.txt (mode 0600)

Step 14: Security recommendations

  • Allow port 22 in the security group from your own networks only.
  • Keep the administrator password secret and rotate it if it may have been shared (Step 12); give editors their own accounts with limited roles.
  • Keep config.yml and your database backups secret (Step 8).
  • Use your own DNS name and a certificate your browsers trust (Step 11).
  • Keep REDAXO and its addons on their newest releases (Step 12) and install only addons you trust.
  • Keep the operating system patched; unattended security upgrades are on, and sudo apt-get update && sudo apt-get upgrade applies everything else. MariaDB and PHP-FPM with its zip and intl extensions come from Ubuntu's universe repository; sudo pro security-status --esm-apps shows whether Ubuntu Pro (ESM Apps) has security updates for them (none were pending when the image was built).

Support and licensing

REDAXO is open source software by Yakamara Media GmbH & Co. KG under the MIT licence (a copy is at /usr/share/doc/redaxo/LICENSE.md); its licence asks that the backend keeps the link to www.redaxo.org and the REDAXO logo visible, which the image's stock backend does. The bundled libraries carry their own open source licences (MIT, LGPL-2.1 for PHPMailer, GPL-2.0-or-later for svg-sanitize). There is no per user or per CPU licence fee and no licence key. This image installs the unmodified upstream release plus the cloudimg first boot, settings and helpers described above. 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