REDAXO on AWS User Guide
Overview
REDAXO is an open source PHP content management system that has been developed continuously since 2004 by Yakamara Media. It is deliberately unopinionated. Instead of imposing a fixed page model, REDAXO gives you templates and modules that you define yourself, so the editing interface ends up matching the site you are actually building rather than the other way round. Editors get a clean backend with a structured page tree, a media pool and reusable content blocks; developers get plain PHP templates, a documented API, a command line console and an addon system.
This image runs REDAXO 5.21.2 on a LAMP stack assembled entirely from the distribution archives, with no third party package repositories: Apache 2.4 with mod_php, PHP 8.3 with OPcache, and MariaDB 10.11 bound to the loopback interface only. The database directory and the application tree each sit on their own EBS volume, separate from the operating system disk.
The important difference from a do-it-yourself install is that there is no installer waiting on your public IP address. The published image contains no configuration file, no database and no user account. On first boot a one shot service generates a fresh database password and a fresh administrator password, creates the database and a least privilege database user, runs the REDAXO console setup, seeds a starter page and then closes the setup routine permanently. Until that has finished, the web server answers every request with HTTP 503 rather than an installation wizard.
Backed by 24/7 cloudimg support.
Connecting to your instance
| Image variant | SSH login user | Example |
|---|---|---|
| Ubuntu 24.04 | ubuntu |
ssh -i your-key.pem ubuntu@<public-ip> |
The instance opens three inbound ports: 22 for SSH, 80 for the site and 443 for TLS once you configure it. The database listens on 127.0.0.1:3306 only and is never reachable from the network.
Launching the instance
From AWS Marketplace
- Open the product page and choose Continue to Subscribe, then Continue to Configuration.
- Pick your region and the software version, then Continue to Launch.
- Choose Launch through EC2. Select an instance type (m5.large is the recommended size), your key pair, and a security group that allows inbound 22 from your own address and 80 and 443 from wherever your visitors are.
- Launch, then wait for the instance to reach 2/2 checks passed.
From the EC2 CLI
Substitute your own AMI id, key pair, subnet and security group.
aws ec2 run-instances \
--region us-east-1 \
--image-id ami-0123456789abcdef0 \
--instance-type m5.large \
--key-name your-key \
--security-group-ids sg-0123456789abcdef0 \
--subnet-id subnet-0123456789abcdef0 \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=redaxo}]'
First boot takes roughly a minute after the instance reports healthy. Until it completes, the site answers 503 by design.
Verifying the deployment
SSH in as the login user for your variant, then run the checks below.
Services
Both application services should be active, and the one shot first boot unit reports active because it is a RemainAfterExit oneshot that has already completed.
systemctl is-active mariadb apache2 redaxo-firstboot
active
active
active
Software versions
sudo -u www-data php /var/www/redaxo/redaxo/bin/console -V
php -v | head -1
apache2 -v | head -1
mariadb -N -B -e 'SELECT VERSION()'
REDAXO 5.21.2
PHP 8.3.6 (cli) (built: Jul 16 2026 18:30:41) (NTS)
Server version: Apache/2.4.58 (Ubuntu)
10.11.14-MariaDB-0ubuntu0.24.04.1
Dedicated data volumes
The content database and the application tree are on their own EBS volumes, so each can be resized and snapshotted independently of the operating system disk.
df -h /var/www /var/lib/mysql
Filesystem Size Used Avail Use% Mounted on
/dev/nvme1n1 20G 25M 19G 1% /var/www
/dev/nvme2n1 20G 191M 19G 2% /var/lib/mysql
Retrieving your credentials
Every instance generates its own administrator and database passwords on first boot and writes them to a root only file. Nothing is shared between deployments and nothing is recoverable from the published image.
sudo cat /root/redaxo-credentials.txt
# REDAXO - generated on first boot by redaxo-firstboot.service.
# These credentials are unique to this instance. Store them somewhere safe.
REDAXO_URL=http://<public-ip>/
REDAXO_BACKEND_URL=http://<public-ip>/redaxo/
REDAXO_ADMIN_USERNAME=cloudimg
REDAXO_ADMIN_PASSWORD=<REDAXO_ADMIN_PASSWORD>
REDAXO_DB_NAME=redaxo
REDAXO_DB_USER=redaxo
REDAXO_DB_PASSWORD=<REDAXO_DB_PASSWORD>
The file is 0600 root:root, so it is readable only through sudo.
Signing in to the backend
Browse to http://<public-ip>/redaxo/ and sign in with REDAXO_ADMIN_USERNAME and REDAXO_ADMIN_PASSWORD from that file.

The first thing you should do after signing in is change the password from your profile page.
You can confirm the sign in works from the command line as well. The check below signs in with the per instance password, then proves a wrong password is refused, and reports only its verdict.
sudo /usr/local/sbin/redaxo-login-check.sh
OK REDAXO backend accepted the per-instance password and refused a wrong one
What you land on
After signing in you arrive at Structure management, REDAXO's page tree. The image seeds one online article called Home on a template called cloudimg Starter, so the front end serves a real page immediately rather than a "not found" error.

The front end is already live on port 80:
CODE=$(curl -s -o /dev/null -w '%{http_code}' -m 20 http://127.0.0.1/)
BODY=$(curl -s -m 20 http://127.0.0.1/)
echo "front end HTTP ${CODE}"
[ "${CODE}" = "200" ] || { echo "FATAL: front end returned ${CODE}, expected 200"; exit 1; }
printf '%s' "${BODY}" | grep -q 'REDAXO is running' \
|| { echo "FATAL: the seeded starter article was not served"; exit 1; }
echo "starter article served"
front end HTTP 200
starter article served

The starter page is an ordinary article. Edit it, or delete it once you have templates of your own.
Creating your first page
REDAXO separates what a page looks like (a template) from what an editor may put on it (modules assembled into content slices).
- Open Templates and either edit cloudimg Starter or add your own. A template is plain PHP and HTML;
REX_ARTICLE[]marks where article content is rendered.

-
Open Modules and define the content blocks your editors will use, for example a heading, a rich text block, or an image with a caption. Each module has an input form and an output template.
-
Open Structure, add a category or an article, choose its template, and set it online.
-
Open the article and use Add slice to place your modules on the page.

Uploaded assets live in the Media Pool, and the Media Manager addon generates resized and cropped variants on demand.

Addons
The image ships REDAXO's complete core addon set, all of it MIT licensed. The Installer addon fetches further addons from the REDAXO repository.

sudo -u www-data php /var/www/redaxo/redaxo/bin/console list | sed -n '15,40p'
Available commands:
completion Dump the shell completion script
help Display help for a command
list List commands
assets
assets:sync Sync assets within the assets-dir with the sources-dir
be_style
be_style:compile [styles:compile] Converts Backend SCSS files to CSS
cache
cache:clear Clears the redaxo core cache
config
config:get Get config variables
config:set Set config variables
db
db:connection-options Dumps the db connection options for the mysql cli tool
db:dump-schema Dumps the schema of db tables as php code
db:set-connection Sets database connection credentials.
install
install:download Download an AddOn from redaxo.org
install:list List available packages on redaxo.org
install:update Updates an AddOn from redaxo.org
package
package:activate Activates the selected package
package:deactivate Deactivates the selected package
package:delete Deletes the selected package
package:install Installs the selected package
Managing users
Open User to add editors and administrators and to assign roles. Give day to day editors a non administrator account with only the permissions they need.

Verifying the security posture
These four checks are worth running once on any new deployment. They are the same properties the image asserts for itself before it is published.
The setup wizard is closed
The console setup wrote setup: false into the configuration when it completed, so REDAXO will never serve an installation wizard again.
CFG=/var/www/redaxo/redaxo/data/core/config.yml
grep -E '^setup:' "${CFG}" \
|| { echo "FATAL: no setup key in ${CFG}"; exit 1; }
grep -qE '^setup:[[:space:]]*false[[:space:]]*$' "${CFG}" \
|| { echo "FATAL: the REDAXO setup wizard is still open"; exit 1; }
echo "setup wizard closed"
setup: false
setup wizard closed
The database is not reachable from the network
MariaDB binds to loopback only. The listener list below should show the database on 127.0.0.1 and only SSH and Apache on a public address. (127.0.0.53 and 127.0.0.54 are the systemd DNS stub resolvers, also loopback.)
ss -tlnH | awk '{print $4}' | sort
BAD=""
while read -r addr; do
[ -n "${addr}" ] || continue
host="${addr%:*}"; host="${host%%%*}"; port="${addr##*:}"
case "${host}" in 127.*|"[::1]"|::1) continue ;; esac
case "${port}" in 22|80|443) continue ;; esac
BAD="${BAD} ${addr}"
done < <(ss -tlnH | awk '{print $4}')
[ -z "${BAD}" ] || { echo "FATAL: unexpected public listeners:${BAD}"; exit 1; }
ss -tlnH | awk '{print $4}' | grep -qx '127.0.0.1:3306' \
|| { echo "FATAL: the database is not bound to loopback"; exit 1; }
echo "only SSH and the web server are reachable; the database is loopback only"
*:80
0.0.0.0:22
127.0.0.1:3306
127.0.0.53%lo:53
127.0.0.54:53
[::]:22
only SSH and the web server are reachable; the database is loopback only
REDAXO's internal trees are not web readable
The source, data, cache and console directories are denied by both REDAXO's own .htaccess files and a vhost rule, so a request for any of them is refused.
for p in redaxo/src/core/boot.php redaxo/data/core/config.yml redaxo/cache/ redaxo/bin/console; do
C=$(curl -s -o /dev/null -w '%{http_code}' -m 10 "http://127.0.0.1/${p}")
echo "/${p} -> HTTP ${C}"
case "${C}" in 403|404) : ;; *) echo "FATAL: /${p} is readable over HTTP"; exit 1 ;; esac
done
echo "internal trees refused as expected"
/redaxo/src/core/boot.php -> HTTP 403
/redaxo/data/core/config.yml -> HTTP 403
/redaxo/cache/ -> HTTP 403
/redaxo/bin/console -> HTTP 403
internal trees refused as expected
The application database user is least privilege
The account REDAXO connects with is scoped to its own database and has no global privileges.
GRANTS=$(sudo mariadb -N -B -e "SHOW GRANTS FOR 'redaxo'@'127.0.0.1'")
echo "${GRANTS}" | sed -E "s/IDENTIFIED BY PASSWORD .*/IDENTIFIED BY PASSWORD <redacted>/"
printf '%s' "${GRANTS}" | grep -qi 'ALL PRIVILEGES ON \*\.\*' \
&& { echo "FATAL: the application user has global privileges"; exit 1; }
printf '%s' "${GRANTS}" | grep -q '`redaxo`' \
|| { echo "FATAL: no grant scoped to the redaxo database"; exit 1; }
echo "application database user is scoped to the redaxo database only"
GRANT USAGE ON *.* TO `redaxo`@`127.0.0.1` IDENTIFIED BY PASSWORD <redacted>
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, REFERENCES ON `redaxo`.* TO `redaxo`@`127.0.0.1`
application database user is scoped to the redaxo database only
Reaching the database
Because MariaDB is loopback only, connect through an SSH tunnel from your own workstation rather than opening port 3306. Run this on your machine, not on the instance:
ssh -i your-key.pem -L 3306:127.0.0.1:3306 ubuntu@<public-ip>
Then point your client at 127.0.0.1:3306 with REDAXO_DB_USER and REDAXO_DB_PASSWORD from the credentials file.
Setting your real site URL
REDAXO records a site URL and an error e-mail address. The image sets the URL to the instance's public address at first boot and the error address to a placeholder, so change both once you have a domain. Either edit them in the backend under System, or from the command line:
sudo -u www-data php /var/www/redaxo/redaxo/bin/console config:set server https://<your-domain>/
sudo -u www-data php /var/www/redaxo/redaxo/bin/console config:set error_email you@<your-domain>
sudo -u www-data php /var/www/redaxo/redaxo/bin/console cache:clear
The backend and front end both work from the request host, so the site keeps answering on the instance IP, a private address or a custom domain without any further reconfiguration. The recorded URL is used for absolute links and outgoing mail.
Enabling HTTPS
The image is TLS ready but ships no certificate, because a certificate is specific to your domain. Two options:
AWS Certificate Manager behind a load balancer. Put an Application Load Balancer in front of the instance, attach an ACM certificate to the listener, and forward to port 80. This is the usual choice for production and needs no change on the instance.
Let's Encrypt directly on the instance. Point your domain at the instance's public address first, then:
sudo apt-get update
sudo apt-get install -y certbot python3-certbot-apache
sudo certbot --apache -d <your-domain> --agree-tos -m you@<your-domain> --redirect
Afterwards, tell REDAXO to use HTTPS so it generates https:// links:
sudo -u www-data php /var/www/redaxo/redaxo/bin/console config:set use_https true
sudo -u www-data php /var/www/redaxo/redaxo/bin/console cache:clear
Backups
Two things need backing up: the database and the application tree (which holds your templates, modules, the media pool and any addons you install).
Database, from the instance:
sudo mariadb-dump --single-transaction --default-character-set=utf8mb4 redaxo \
| gzip > /var/backups/redaxo-$(date +%F).sql.gz
Application tree:
sudo tar -czf /var/backups/redaxo-files-$(date +%F).tar.gz -C /var/www redaxo
Copy both off the instance, for example to Amazon S3. The backend's Backup addon can also export and import the database from the browser.
Because each tier is on its own EBS volume, an EBS snapshot of the /var/lib/mysql volume and the /var/www volume is an equally valid backup and is usually the simplest to schedule with Amazon Data Lifecycle Manager.
Keeping the system patched
The image ships fully patched, and unattended upgrades are left in their stock configuration so security updates continue to arrive. To apply everything immediately:
sudo apt-get update
sudo apt-get -y upgrade
REDAXO itself is upgraded from the backend: the Installer addon offers core and addon updates, and the Backup addon lets you export the database first.
Troubleshooting
The site returns 503. First boot has not finished, or it failed. Check it:
systemctl is-active redaxo-firstboot >/dev/null \
|| { echo "FATAL: first boot did not complete - run: journalctl -u redaxo-firstboot"; exit 1; }
test -f /var/lib/cloudimg/redaxo-firstboot.done \
|| { echo "FATAL: the first-boot sentinel is missing"; exit 1; }
echo "first boot completed"
first boot completed
If first boot did fail, journalctl -u redaxo-firstboot carries the reason. Apache deliberately refuses to start until it succeeds, so the setup wizard can never be exposed.
Signing in is rejected. Confirm you are using REDAXO_ADMIN_USERNAME from the credentials file, not a name of your own. After several wrong attempts REDAXO applies a short delay before the next try.
A page shows no content. A new article has no content slices until you add them, and it needs a template that is active and permitted for its category.
Something is slow. Check systemctl status apache2 mariadb and the Apache error log at /var/log/apache2/redaxo-error.log. For a busy site, move to a larger instance type or migrate the database to Amazon RDS.
Support
Every subscription includes 24/7 technical support from cloudimg engineers.
- Email: support@cloudimg.co.uk
- Live chat: available 24/7
We help with deployment, credential retrieval, upgrades, addon installation, template and module development, performance tuning, TLS configuration and database administration.
REDAXO is open source software published under the MIT licence by Yakamara Media GmbH & Co. KG. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.