Ibexa OSS 5.0.10
Overview
This guide covers launching and using the Ibexa OSS 5.0.10 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.
Ibexa OSS is the open-source edition of the Ibexa content platform (the successor of eZ Platform and eZ Publish), built on Symfony 7.4 and PHP 8.3. You model your content with content types and fields. You organise it in a content tree with sections, languages, roles and policies. You edit it in the back office at /admin with a rich text editor and serve it through Symfony templates. A REST API and a GraphQL API come with it.
The SecureAnyCloud image gives you a hardened, ready-to-run installation. Each instance creates its own database, secrets and certificate at first boot.
What you get:
- No shared database and no default password. A stock Ibexa installation creates two accounts with the well-known password
publish: the administrator accountadminand theanonymousaccount every visitor uses. This image ships no database at all (the MariaDB data directory is empty) and no.env.local(noAPP_SECRET, no database password). Your instance's first boot initialises its own database, writes its own.env.localand runs Ibexa's installer. It replaces the password of both accounts with values generated on your instance before the web server or PHP start, sopublishnever signs anyone in. - Secrets of your instance's own, never on a command line. The database password,
APP_SECRET, the administrator password and the TLS key are generated on your instance. Nothing from the image build is reused. Passwords are handed to Ibexa in files that only root and the web server can read, never as command-line arguments. - The current release with refreshed Symfony. Ibexa OSS 5.0.10 is the newest release (it fixes Ibexa's security advisory IBEXA-SA-2026-004). Its lock file pins
symfony/http-foundation7.4.16, which has a denial of service any visitor can trigger with a request header (CVE-2026-108082). This image installs Ibexa from that lock and then updates the Symfony packages to their latest 7.4 patch releases inside Ibexa's own version constraints. Step 3 lists every package that changed. - Closed by default. The REST API answers anonymous callers
401(signing in is the only public call), the GraphQL endpoint, the GraphiQL console and the API documentation are not served, the Symfony profiler does not exist (production mode) and public registration is off. - HTTPS from the first boot. nginx serves Ibexa on port 443 with a certificate generated on your instance's first boot. Port 80 redirects to HTTPS.
- Fail closed. nginx and PHP do not start until first boot has finished. If first boot cannot complete, the site stays offline rather than open.
- Only the front controller runs PHP. Every request goes through Symfony's
public/index.php, and every other PHP file is never run. The content storage that holds uploaded images and files (/var/...) and Ibexa's file downloads (/content/download/...) are served withnosniffand a sandboxing content security policy on every response, and only passive types (images, PDF, fonts, audio and video) open in the browser; anything else is sent as a download. - A rate-limited sign-in. nginx gives every sign-in route (the site and back-office sign-in, the REST API session, forgotten and reset password, registration and password change) one shared budget of 20 a minute from one address after a burst of 20. nginx uses the address of the connection, never a header a client sends.
- The real host and client address. nginx hands Ibexa the host name you configure and nothing a request claims. Symfony's trusted host list and default URI are pinned to it, so every link, password reset e-mails included, uses your host name. nginx removes
X-Forwarded-For,Client-IPand the other forwarding headers before PHP sees them. - Links from other sites cannot sign you out or change state. Signing out, marking notifications read, the content create and translate shortcuts, drafts, focus mode and emptying the trash only follow links opened from your own site.
- No calls home and no third-party scripts. Measured on the build: the server makes no outbound connection while the back office and the site are used, and the site's welcome page no longer loads Google Fonts.
- Hardened defaults. The Ibexa code belongs to root and is read-only to PHP. Only
var/and the content storage are writable, and they are kept private to the web server. PHP cannot run shell commands. MariaDB has no network listener at all (Ibexa talks to it over a local socket), and itsrootaccount 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. - Your data on its own volume. The database and the content storage live on a separate 30 GiB EBS volume mounted at
/var/lib/ibexa, which you can grow or snapshot on its own. - Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
- 24/7 SecureAnyCloud support
What is on the image: Ibexa OSS 5.0.10 (installed with composer from the release lock, Symfony 7.4 refreshed), MariaDB 10.11, PHP 8.3 FPM, nginx, composer, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent. Node.js is not on the image because the back-office assets were compiled when the image was built.
- 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 (Ibexa) and TCP 80 (redirects to HTTPS) from the networks that should reach them. Keep 22 open to your own networks only. Open 443 to your visitors for a public site, or only to your team while you build it.
Launch the instance
In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Pick Ibexa OSS 5.0.10 on Ubuntu 24.04 as the software version and select your Region. Then choose Launch through EC2.
Choose m5.large, your key pair and a security group as above. Keep the second volume (30 GiB, the data volume), because first boot will not set up Ibexa without it.
To launch with the AWS CLI instead, 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=ibexa}]'Connect to your instance
Connect over SSH as the ubuntu user, which is the SSH user for Ibexa OSS 5.0.10 on Ubuntu 24.04.
ssh -i <your-key.pem> ubuntu@<public-ip>Check the services
First boot takes about a minute, because it creates the database and installs Ibexa. Afterwards, nginx, PHP, MariaDB and the first boot unit are active. Check them:
systemctl is-active nginx php8.3-fpm mariadb ibexa-firstbootactive active active activenginx serves ports 80 and 443. PHP and MariaDB listen on local sockets only, so the only open ports are 22, 80 and 443. Check the listeners:
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"))Check the Ibexa release, the PHP and MariaDB versions, and the Symfony security fix:
python3 -c 'import json; P={p["name"]: p["version"] for p in json.load(open("/var/www/ibexa/vendor/composer/installed.json"))["packages"]}; [print(n, P[n]) for n in ("ibexa/oss", "ibexa/core", "symfony/http-foundation", "symfony/yaml", "symfony/expression-language")]' php -v | head -1 mariadb --versionibexa/oss v5.0.10 ibexa/core v5.0.10 symfony/http-foundation v7.4.21 symfony/yaml v7.4.21 symfony/expression-language v7.4.21 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 wrapperSee how the release was installed and every package the Symfony refresh changed:
cat /usr/share/doc/ibexa/RELEASE head -8 /usr/share/doc/ibexa/SYMFONY-UPDATE.txtIbexa OSS 5.0.10 (ibexa/oss-skeleton v5.0.10, commit 49630948f8736c5d97b35d9aa51f2bea7ded091b) licence GPL-2.0-only (the open-source edition; sac does not grant or imply the Ibexa BUL) skeleton composer.lock sha256 270ad5a59779d348680dd4459510d540b12cebf5685767291c787944ab9bab5f composer 2.10.3 (sha256 7a2d379d5b8ffdaa028580ef26494c36d2feef4b178d3dd1473a4dbc5e17c8d6); build-only Node.js v22.23.4 (sha256 1805bcd35e6815559bd2eb97db438d3fdb0eb3a5e6a977b7c1badca76337e9ce) Ibexa OSS 5.0.10: d-575(6) composer update 'symfony/*' --with-dependencies at build (2026-10-28T01:56:38Z UTC) package before after doctrine/lexer 3.0.1 3.0.3 monolog/monolog 3.10.0 3.12.1 phpdocumentor/reflection-common 2.2.0 2.2.1 phpstan/phpdoc-parser 2.3.3 2.3.9 symfony/cache v7.4.16 v7.4.21 symfony/clock v7.4.8 v7.4.21The full table is in /usr/share/doc/ibexa/SYMFONY-UPDATE.txt and the security audit of the installed packages in /usr/share/doc/ibexa/composer-audit.json. The one advisory it lists is a low-severity issue in league/flysystem 2.5 (a path check for control characters). Ibexa only reaches it with file names an editor uploads.
Get your sign-in details
The credentials file holds the address Ibexa is served as (your instance's public DNS name by default), the back-office address, the administrator login and password, and the database credentials. All of them are generated on this instance. Show the file:
sudo cat /root/ibexa-credentials.txtIBEXA_SITE_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/ IBEXA_ADMIN_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/admin/login IBEXA_ADMIN_LOGIN=admin IBEXA_ADMIN_PASSWORD=<24 letters and digits> IBEXA_DB_NAME=ibexa IBEXA_DB_USER=ibexa IBEXA_DB_PASSWORD=<48 hexadecimal characters>Visit the site and sign in
Open IBEXA_SITE_URL in your browser. The certificate is self-signed and generated on your instance. Accept the browser warning once, or install your own certificate (Step 11). A fresh site shows Ibexa's welcome page:
Open IBEXA_ADMIN_URL and sign in with the login admin and IBEXA_ADMIN_PASSWORD:
The back office opens on its Dashboard:
The admin account is an Administrator. Create a separate account for each editor and give it a role with only the policies it needs. Users and Roles are on the administration menu, behind the gear icon at the bottom of the menu. The same menu holds Languages, URL management and System information.
Content types, content and the site
Ibexa organises everything as content in a tree: Content structure holds the site, Media holds images and files, and the users are content too. To add a page, open Content structure and choose Create content. Pick a content type (for example Article or Folder), fill in the fields and choose Publish:
Content types define the fields each kind of content has. You find them in the menu under Settings. Uploaded images and files are stored under /var/lib/ibexa/var on the data volume. The site's templates live in /var/www/ibexa/templates. The Ibexa documentation explains how to build your own design with Symfony and Twig.
The closed-by-default settings
The REST API is closed to anonymous callers: only signing in (POST /api/ibexa/v2/user/sessions) is public, and everything else answers 401 until you are signed in (the back office uses it with your session). GraphQL, the GraphiQL console and the API documentation are not served, and the Symfony profiler does not exist. Verify this:
H=$(sudo sed -n 's#^IBEXA_SITE_URL=https://\(.*\)/$#\1#p' /root/ibexa-credentials.txt) for u in /api/ibexa/v2/content/locations/1/2 /graphql /api/docs /graphiql /_profiler /register; do printf '%-36s %s\n' "$u" "$(curl -sk --resolve "$H:443:127.0.0.1" -o /dev/null -w '%{http_code}' "https://$H$u")" done/api/ibexa/v2/content/locations/1/2 401 /graphql 404 /api/docs 404 /graphiql 404 /_profiler 404 /register 401The image serves two siteaccesses. The default is site, with no prefix (Ibexa also answers it as /site/...). The other is admin, the back office at /admin. Ibexa picks the siteaccess from the first part of the path, so every closed route and every rule above also applies under /site/, /admin/ or any other first segment.
An anonymous visitor can do the following:
- View the published site (content in the Standard section, or the welcome page on a fresh site) and search it
- Open the sign-in and forgotten password forms
- Load the site's static files and the public JavaScript route and translation lists that the back office uses
Registration is off because the Anonymous role has no user/register policy.
To open the REST API to anonymous readers again, delete /var/www/ibexa/src/EventSubscriber/SacRestAnonymousSubscriber.php and clear the cache (sudo -u www-data php /var/www/ibexa/bin/console cache:clear).
To serve GraphQL, remove the graphql line from the $ibx_closed map in /etc/nginx/conf.d/sac-ibexa-guard.conf and reload nginx. The schema is already generated for your content types (/var/www/ibexa/config/graphql/types/ibexa). The endpoint uses the same sign-in and permissions as the back office.
Your data
The database and the content storage are on the data volume, a separate EBS volume mounted at /var/lib/ibexa. Inspect it:
findmnt -no SOURCE,FSTYPE,SIZE,TARGET /var/lib/ibexa
sudo ls /var/lib/ibexa
sudo mysql -N -e "SELECT @@datadir, @@skip_networking"/dev/nvme1n1 ext4 29.4G /var/lib/ibexa lost+found mysql var /var/lib/ibexa/mysql/ 1mysql is MariaDB's data directory and var is Ibexa's content storage (served as /var/...).
Back up by snapshotting the volume, or with sudo mysqldump ibexa plus a copy of /var/lib/ibexa/var. Keep /var/www/ibexa/.env.local (this instance's APP_SECRET and database password) with your backups, and keep it secret.
Security checks
The well-known installer password is refused for both built-in accounts, and the REST API refuses an anonymous read. The round-trip helper also proves that your own password signs in through the back-office form. Run the checks:
sudo ibexa-cred-roundtripOK https 301 + admin login + wrong and 'publish' passwords refused (form and REST, admin and anonymous) + anonymous REST 401PHP runs only through Symfony's front controller, and the content storage is static only, with a sandboxing policy. Verify this:
H=$(sudo sed -n 's#^IBEXA_SITE_URL=https://\(.*\)/$#\1#p' /root/ibexa-credentials.txt) for u in /index.php /index.php/admin/login /var/x.php /.env.local /composer.json; do printf '%-26s %s\n' "$u" "$(curl -sk --resolve "$H:443:127.0.0.1" -o /dev/null -w '%{http_code}' "https://$H$u")" done grep -A3 'map "$ibx_upload$ibx_passive" $ibx_up_csp' /etc/nginx/conf.d/sac-ibexa-guard.conf | sed -n 3p/index.php 404 /index.php/admin/login 404 /var/x.php 404 /.env.local 404 /composer.json 404 "~^1" "default-src 'none'; img-src 'self' data:; media-src 'self'; style-src 'unsafe-inline'; sandbox";The services are blocked from the instance metadata service, and the instance requires IMDSv2. Verify this:
for u in nginx php8.3-fpm mariadb ibexa-firstboot; do printf '%-16s %s\n' "$u" "$(systemctl show -p IPAddressDeny --value "$u")"; done curl -s -o /dev/null -w 'IMDSv1 from the shell: %{http_code}\n' http://169.254.169.254/latest/meta-data/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 ibexa-firstboot 169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128 IMDSv1 from the shell: 401SSH accepts keys only, the code belongs to root, and .env.local is readable by the web server only. Verify this:
sudo sshd -T | grep -E '^(passwordauthentication|permitrootlogin|x11forwarding) ' stat -c '%U:%G %a %n' /var/www/ibexa /var/www/ibexa/vendor /var/www/ibexa/var /var/www/ibexa/.env.local /var/lib/ibexa/varpermitrootlogin no passwordauthentication no x11forwarding no root:root 755 /var/www/ibexa root:root 755 /var/www/ibexa/vendor www-data:www-data 750 /var/www/ibexa/var root:www-data 640 /var/www/ibexa/.env.local www-data:www-data 750 /var/lib/ibexa/varBehind a proxy or load balancer
nginx removes every forwarding header and Symfony trusts no proxy, so behind a load balancer Ibexa records the balancer's address.
If you terminate TLS on an Application Load Balancer, keep the target on port 443 (the instance's own certificate). Set the host name with ibexa-set-hostname (Step 11).
To trust a balancer's X-Forwarded-For, add its subnet as SYMFONY_TRUSTED_PROXIES in /var/www/ibexa/.env.local. Then remove the fastcgi_param HTTP_X_FORWARDED_FOR ""; line from /etc/nginx/snippets/sac-ibexa-fastcgi.conf. Only do this when the instance is not reachable directly.
Your own DNS name and certificate
Point a DNS name at the instance, then pin Ibexa to it. This mints a new self-signed certificate for the name. It also pins nginx, Symfony's trusted hosts and default URI, and the cross-site guard to the name:
sudo ibexa-set-hostname cms.example.comFor a public certificate, install certbot (sudo apt install certbot) and obtain a certificate for the name with the webroot or DNS method. Point ssl_certificate and ssl_certificate_key in /etc/nginx/sites-available/sac-ibexa at it. Then run sudo nginx -t && sudo systemctl reload nginx. Add HSTS once the certificate is trusted.
Passwords, e-mail, updates
- Administrator password:
sudo ibexa-set-passwordgenerates a new one, writes it to/root/ibexa-credentials.txtand signs every session out.sudo ibexa-set-password admin --stdinsets one you type (24 to 96 letters and digits with an upper case letter, a lower case letter and a digit). For other accounts, runsudo ibexa-set-password <login>. - E-mail: the image sends no mail (
MAILER_DSN=null://null). SetMAILER_DSNin/var/www/ibexa/.env.localto your SMTP service (for example Amazon SES) so that password reset and notification e-mails are sent. - Operating system updates: unattended upgrades apply Ubuntu security updates automatically.
- Ibexa and Symfony updates: Ibexa is maintained with composer in
/var/www/ibexa. Installunzipandgitfirst (sudo apt install unzip git) and take a snapshot of both volumes. Then run composer as root, because the code belongs to root. An update that changes the back-office assets also needs Node.js 22 and yarn to rebuild them (composer run-script auto-scripts). Follow Ibexa's upgrade documentation, then clear the cache aswww-data. Check advisories withsudo composer audit --working-dir=/var/www/ibexa.
Server components
Each component lives in the following place:
- Ibexa OSS 5.0.10: /var/www/ibexa (code, root-owned) and /var/www/ibexa/.env.local (this instance's secrets)
- Content storage: /var/lib/ibexa/var on the data volume, served as /var/...
- MariaDB 10.11 data directory: /var/lib/ibexa/mysql on the data volume, local socket only
- PHP 8.3 FPM: /etc/php/8.3/fpm/conf.d/99-sac-ibexa.ini
- nginx: /etc/nginx/sites-available/sac-ibexa and /etc/nginx/conf.d/sac-ibexa-guard.conf
- First boot: ibexa-firstboot.service and /usr/local/sbin/ibexa-firstboot.sh
- Helpers: ibexa-set-hostname, ibexa-set-password and ibexa-cred-roundtrip in /usr/local/sbin
- Notes: /usr/share/doc/ibexa/SAC.txt
Security recommendations
- Keep SSH (22) open only to your own networks, and open 443 only to the visitors who need it while you build the site.
- Give every editor their own account with a role that has only the policies they need. Keep
adminfor administration. - Set up a real DNS name and certificate (Step 11) and e-mail (Step 12) before you go live.
- Snapshot the data volume regularly, and keep
.env.localwith your backups. - Watch Ibexa's security advisories and apply composer updates as Step 12 describes.
Support and licensing
Ibexa OSS is open-source software distributed under the GNU General Public License version 2 (GPL-2.0-only), and this image ships it under that licence. The licence text and Ibexa's copyright notice are in /usr/share/doc/ibexa.
Ibexa's commercial editions (Ibexa DXP) and their Business Use License are separate products that this image does not include. Ibexa and eZ Platform are trademarks of Ibexa AS. SecureAnyCloud is not affiliated with or endorsed by Ibexa AS.
SecureAnyCloud provides support for the image. See SecureAnyCloud support.
Deploy on AWS
Launch Ibexa OSS 5.0.10 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