SPIP 4.4.28
Overview
This guide covers launching and using the SPIP 4.4.28 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.
SPIP (Système de Publication pour l'Internet) is a mature open-source content management system built for editorial and publishing websites. It provides articles organised in sections, an editorial workflow (articles are proposed, reviewed and published), authors with roles, multilingual content, documents and images, and a public site rendered from templates (skeletons).
It is widely used for newsrooms, associations, public bodies and documentation sites. This is SPIP the CMS, not spiped the secure pipe daemon.
What you get:
- No reachable web installer, no shared database. A plain SPIP installation offers its web installer (
ecrire/?exec=install) to whoever opens it first, and that person chooses the database and creates the first webmestre. This image ships no database at all. The MariaDB data directory is empty in the image, and your instance's first boot initialises its own database, runs SPIP's own installer over a private loopback connection before the web server starts, and creates the webmestreadminwith a password generated on your instance. nginx refuses the installer address afterwards, and SPIP itself refuses it once it is installed. - Secrets unique to your instance. The database password, the webmestre password and SPIP's secret keys (
config/cles.php, which sign SPIP's forms and actions and pepper every password hash) are generated on your instance's first boot. Nothing from the image build is reused. - The current release. SPIP 4.4.28 is the newest stable release. It fixes the security issues reported against earlier 4.4 releases. Among them are two remote code execution flaws exploited in the wild in August 2026 (fixed in 4.4.20 and 4.4.21), a blind SQL injection, missing authorisation checks on private actions and a server-side request forgery through redirects. The download is verified against a pinned checksum, and SPIP's security screen (
config/ecran_securite.php, version 1.6.7) is in place and active. - HTTPS from the first boot. nginx serves SPIP on port 443 with a certificate generated on your instance's first boot. Port 80 redirects to HTTPS.
- Fail closed. nginx does not start until first boot has finished. If first boot cannot complete, the site stays offline rather than open.
- Only SPIP's entry points run. PHP runs only through
spip.php,index.phpand the private areaecrire/. SPIP's configuration (config/), its working folder (tmp/: sessions, caches, logs) and its libraries are never served. No other PHP file in the installation can be called, and documents inIMG/are served as static files only, with a sandboxing content security policy for SVG and HTML files. - A rate-limited login. SPIP does not throttle sign-in attempts. On this image, nginx limits sign-in and password reset requests to 6 a minute from one address after a burst of 10. The address comes from the connection, never from a header a client sends, and SPIP accepts the sign-in form only on its own page so the limit cannot be sidestepped. HTTP Basic authentication is switched off.
- Hardened defaults. The SPIP code and configuration belong to
rootand are read-only to PHP. PHP cannot run shell commands and is confined to SPIP's folders. MariaDB has no network listener at all (SPIP talks to it over a local socket), and its root account signs in only through the socket as the operating system's root. - Metadata and host-name protection. nginx, PHP and MariaDB 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 SPIP always sees the host name you configure, never one a request claims.
- Fully patched. Ubuntu 24.04 LTS is fully patched at build time, with unattended security upgrades switched on.
- What is on the image: SPIP 4.4.28 (the official release with its bundled plugins, checksum verified), MariaDB 10.11, PHP 8.3 FPM, nginx, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent.
- Separate data volume. The database and SPIP's documents are on a separate 30 GiB EBS volume mounted at
/var/lib/spip. - Defaults: 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 (SPIP) and TCP 80 (redirects to HTTPS) from the networks that should reach them. Keep 22 to your own networks. Open 443 to your readers for a public site, or only to your editors while you prepare it.
Launch the instance
In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Pick SPIP 4.4.28 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 (the database and documents) in the launch settings. You can make it larger there.
Alternatively, launch with the AWS CLI, replacing 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=spip}]'Connect to your instance
Connect over SSH. For SPIP 4.4.28 on Ubuntu 24.04, the SSH user is ubuntu:
ssh -i <your-key.pem> ubuntu@<public-ip>Check the services
First boot takes about half a minute, because it creates the database and runs SPIP's installer. Afterwards, nginx, PHP, MariaDB and the first-boot unit are all active:
systemctl is-active nginx php8.3-fpm mariadb spip-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:
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 SPIP release, the security screen, the PHP and MariaDB versions and the data volume:
grep "^\$spip_version_branche = " /var/www/spip/ecrire/inc_version.php
sudo grep "define('_ECRAN_SECURITE'" /var/www/spip/config/ecran_securite.php php -v | head -1 mariadb --version findmnt -no TARGET,FSTYPE,SIZE /var/lib/spip$spip_version_branche = '4.4.28'; define('_ECRAN_SECURITE', '1.6.7'); // 2025-09-08 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 /var/lib/spip ext4 29.4GGet your sign-in details
The credentials file holds the address SPIP is served as (your instance's public DNS name by default), the private area address, the webmestre login and password, and the database credentials. All of them are generated on this instance. Print the file:
sudo cat /root/spip-credentials.txtSPIP_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/ SPIP_ADMIN_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/ecrire/ SPIP_ADMIN_USER=admin SPIP_ADMIN_PASSWORD=<24 letters and digits> SPIP_DB_NAME=spip SPIP_DB_USER=spip SPIP_DB_PASSWORD=<48 hexadecimal characters>Visit the site and sign in
Open SPIP_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 11).
The public site shows a welcome article that first boot created, so that a new site renders real content.
Open SPIP_ADMIN_URL (the private area, /ecrire/). SPIP sends you to its sign-in page. Sign in with the login admin and SPIP_ADMIN_PASSWORD.
The private area opens on your home page, with the latest editorial activity and the menus Edit, Publish, Templates, Maintenance and Configuration.
Open your own author page from the top bar to set your name and e-mail address (it starts as admin@localhost.localdomain) and to change the password.
Write and publish
SPIP organises a site in sections (rubriques), which hold articles and may hold sub-sections. Under Edit > Sections, create the sections of your site.
Inside a section, choose Write a new article, give it a title and a text, and save. SPIP's typographic shortcuts are shown under the text field. A new article is in progress. Set it to proposed for evaluation for review, and to published online to put it on the public site.
Add authors under Edit > Authors. A webmestre administers everything, an administrator manages content (optionally restricted to some sections), and an editor (rédacteur) writes and proposes articles. Give each person their own account with the narrowest status that works.
Site configuration and plugins
Configuration > Site identity sets the site name, slogan and description. Configuration > Interactivity, Site content and Multilingual switch on forums, the fields articles use and translations.
Configuration > Manage plugins lists the plugins. The 20 plugins bundled with SPIP (archives, uploads, documents, keywords, forums, statistics, referenced sites and more) are always active and listed under Locked.
Plugins you add (Add plugins, from SPIP's plugin repositories) go into /var/www/spip/plugins/auto, the one code folder the web server may write. Install only plugins you trust, because a plugin is PHP code that runs with SPIP's rights.
Email: SPIP sends password reset links and notifications with PHP's mail function, and the image has no mail server. Add the Facteur plugin (Manage plugins > Add plugins) to send through your SMTP server before you rely on e-mail. You can always reset the webmestre password from the shell (Step 12).
Your data
SPIP's data is on its own EBS volume at /var/lib/spip. It holds the MariaDB data directory (mysql, initialised on this instance's first boot) and SPIP's documents (IMG, which the site serves as /IMG/):
sudo ls -l /var/lib/spip | sed -E 's/ +/ /g' | cut -d' ' -f1,3,4,9-total drwxr-x--- www-data www-data IMG drwx------ root root lost+found drwxr-x--- mysql mysql mysqlThe site's configuration is in /var/www/spip/config. SPIP's installer wrote connect.php (the database connection) and cles.php (SPIP's secret keys) on first boot.
Keep cles.php with your backups. Every password hash and every signed form depends on it, so a database restored without its cles.php has no working passwords.
MariaDB has four accounts: the system accounts root and mysql (which sign in only through the local socket as the matching operating system user), the locked mariadb.sys, and spip, SPIP's own user with this instance's password. It has no network listener:
sudo mysql -N -e "SELECT CONCAT(User,'@',Host) FROM mysql.global_priv ORDER BY 1; SELECT @@skip_networking, @@datadir"mariadb.sys@localhost mysql@localhost root@localhost spip@localhost 1 /var/lib/spip/mysql/Back up the site with EBS snapshots of the data volume and the root volume, or as files:
sudo mysqldump --single-transaction spip | gzip > spip-db.sql.gz
sudo tar -czf spip-files.tar.gz -C / var/lib/spip/IMG var/www/spip/config/cles.php var/www/spip/config/connect.phpSPIP's own Maintenance > Backup the database option in the private area also writes a backup into tmp/dump/.
Security checks
Port 80 sends browsers to HTTPS, and the health endpoint answers for load balancer checks. The installer, the configuration, SPIP's working folder and its internal PHP files are not reachable. Verify this:
H=$(sed -n 's/^set \$spip_host "\(.*\)";$/\1/p' /etc/nginx/spip-host.conf)
curl -s -o /dev/null -w 'port 80: %{http_code} -> %{redirect_url}\n' --resolve "$H:80:127.0.0.1" "http://$H/ecrire/"
curl -sk --resolve "$H:443:127.0.0.1" "https://$H/healthz" for p in '/ecrire/?exec=install' /config/connect.php /config/cles.php /tmp/meta_cache.php /ecrire/inc_version.php /vendor/autoload.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/ || trueport 80: 301 -> https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/ecrire/ ok /ecrire/?exec=install: 404 /config/connect.php: 404 /config/cles.php: 404 /tmp/meta_cache.php: 404 /ecrire/inc_version.php: 404 /vendor/autoload.php: 404 unknown host name: 000A 000 result means nginx closed the connection without an answer.
The private area is closed until you sign in:
H=$(sed -n 's/^set \$spip_host "\(.*\)";$/\1/p' /etc/nginx/spip-host.conf)
curl -sk -o /dev/null -w 'private area: %{http_code} -> %{redirect_url}\n' --resolve "$H:443:127.0.0.1" "https://$H/ecrire/"private area: 302 -> https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/spip.php?page=login&url=%2Fecrire%2FThe credentials file is readable by root only. The configuration is readable by root and the web server's group, SPIP's working folder and documents by the web server only, and the code belongs to root:
sudo stat -c '%a %U:%G %n' /root/spip-credentials.txt /var/www/spip/config/connect.php /var/www/spip/config/cles.php /var/www/spip/config /var/www/spip/tmp /var/lib/spip/IMG /var/www/spip/spip.php600 root:root /root/spip-credentials.txt 640 root:www-data /var/www/spip/config/connect.php 640 root:www-data /var/www/spip/config/cles.php 750 root:www-data /var/www/spip/config 750 www-data:www-data /var/www/spip/tmp 750 www-data:www-data /var/lib/spip/IMG 644 root:root /var/www/spip/spip.phpThe certificate was generated on this instance and names its own addresses. Inspect it:
H=$(sed -n 's/^set \$spip_host "\(.*\)";$/\1/p' /etc/nginx/spip-host.conf)
echo | openssl s_client -connect 127.0.0.1:443 -servername "$H" 2>/dev/null | openssl x509 -noout -subject -ext subjectAltNamesubject=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:localhostnginx, PHP and MariaDB cannot reach the instance metadata service. PHP cannot run shell commands and is confined to SPIP's folders. nginx hands PHP the configured host name and the real client address from the connection, never values a client sends and never an Authorization header, and it rate-limits sign-in requests:
for u in nginx php8.3-fpm mariadb; do systemctl show $u -p IPAddressDeny; done 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|SERVER_NAME|HTTP_X_FORWARDED_FOR|HTTP_X_FORWARDED_HOST|HTTP_AUTHORIZATION) ' /etc/nginx/snippets/sac-spip-php.conf grep -h 'limit_req_zone\|limit_req_status' /etc/nginx/conf.d/sac-spip-login-guard.confIPAddressDeny=fd00:ec2::254/128 168.63.129.16/32 169.254.169.254/32 IPAddressDeny=fd00:ec2::254/128 168.63.129.16/32 169.254.169.254/32 IPAddressDeny=fd00:ec2::254/128 168.63.129.16/32 169.254.169.254/32 disable_functions => exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec expose_php => Off open_basedir => /var/www/spip/:/var/lib/spip/IMG/:/var/lib/php/sessions/:/tmp/:/usr/share/php/ fastcgi_param HTTP_HOST $spip_host; fastcgi_param SERVER_NAME $spip_host; fastcgi_param HTTP_X_FORWARDED_HOST ""; fastcgi_param HTTP_X_FORWARDED_FOR $remote_addr; fastcgi_param HTTP_AUTHORIZATION ""; limit_req_zone $spip_auth_key zone=spip_auth:10m rate=6r/m; limit_req_status 429;If a burst of wrong passwords rate-limits you (HTTP 429), wait a minute and try again. The limit only slows down repeated attempts from one address.
sudo spip-cred-roundtrip checks the whole sign-in path on the instance: the redirect to HTTPS, the refused installer and configuration, a sign-in with the password from the credentials file, and that wrong and common passwords are refused.
Server-side image processing
SPIP makes thumbnails and resized images with PHP's GD library, which works out of the box.
PHP on this image cannot run shell commands, so the optional ImageMagick (convert) and netpbm methods under Configuration > Advanced functions are not available, and their test images on that page stay broken. Keep GD selected.
Your own DNS name and certificate
Point a DNS record at the instance, then set the name SPIP is served as. This command mints a new self-signed certificate for the name, updates nginx, SPIP's site address (used in feeds, e-mails and absolute links) and the addresses in /root/spip-credentials.txt, clears SPIP's caches and keeps the name across reboots:
sudo spip-set-hostname <your-domain>To use a certificate from your own certificate authority instead, copy it over the generated pair and reload nginx. Running spip-set-hostname again replaces it with a self-signed one:
sudo install -m 0644 <your-domain>.crt /etc/nginx/ssl/spip.crt
sudo install -m 0600 <your-domain>.key /etc/nginx/ssl/spip.key
sudo nginx -t && sudo systemctl reload nginxOnce browsers trust the certificate, you can also add an HSTS header (add_header Strict-Transport-Security "max-age=31536000" always;) to /etc/nginx/snippets/sac-spip-headers.conf. The image does not send one, because browsers ignore HSTS from a site whose certificate they do not trust.
Passwords and upgrades
spip-set-password gives the webmestre admin a new random password with SPIP's own password scheme and records it in /root/spip-credentials.txt. Run it without arguments, or pass your own password (24 to 96 letters and digits) on stdin.
Authors change their own password on their author page, and the webmestre can change any author's.
sudo spip-set-password printf '%s\n' '<your-new-password>' | sudo spip-set-password --stdinSecurity screen. SPIP's security screen blocks known attack patterns before SPIP runs. Update it whenever SPIP announces a new version, and take a snapshot first:
curl -fsSL -o /tmp/ecran_securite.php https://git.spip.net/spip-contrib-outils/securite/raw/branch/master/ecran_securite.php php -l /tmp/ecran_securite.php && sudo install -o root -g root -m 0644 /tmp/ecran_securite.php /var/www/spip/config/ecran_securite.phpUpgrades. Snapshot the instance, download the new release zip from https://files.spip.net/spip/archives/ and read its release notes. Then replace the code as root, keeping config, IMG, tmp, local, plugins/auto and lib:
sudo apt-get install unzip unzip -q spip-v<version>.zip -d /tmp/spip-new
sudo systemctl stop nginx cd /var/www/spip && sudo rm -rf ecrire prive plugins-dist squelettes-dist vendor spip.php index.php
sudo cp -a /tmp/spip-new/{ecrire,prive,plugins-dist,squelettes-dist,vendor,spip.php,index.php} /var/www/spip/
sudo chown -R root:root /var/www/spip/{ecrire,prive,plugins-dist,squelettes-dist,vendor,spip.php,index.php}
sudo systemctl start nginxThen sign in to the private area. SPIP runs its database upgrade itself when the webmestre visits it.
Server components
These are the main components and where they live on the instance:
- SPIP code (root-owned): /var/www/spip
- Configuration (database connection, secret keys, site options): /var/www/spip/config/ (
connect.php,cles.php, mes_options.php) - Security screen: /var/www/spip/config/ecran_securite.php
- Working folder (sessions, caches, logs, backups): /var/www/spip/tmp, /var/www/spip/local
- Database (MariaDB datadir) and documents: /var/lib/spip/mysql, /var/lib/spip/IMG (their own EBS volume)
- nginx site and login rate limit: /etc/nginx/sites-available/sac-spip, /etc/nginx/conf.d/sac-spip-login-guard.conf
- PHP settings: /etc/php/8.3/fpm/conf.d/99-sac-spip.ini
- MariaDB settings: /etc/mysql/mariadb.conf.d/99-sac-spip.cnf
- Certificate and key: /etc/nginx/ssl/
- First-boot script: /usr/local/sbin/spip-firstboot.sh
- Helpers: /usr/local/sbin/spip-set-hostname,
spip-set-password, spip-cred-roundtrip - Licence, changelog and image notes: /usr/share/doc/spip/
- Credentials:
/root/spip-credentials.txt(mode 0600)
Security recommendations
- Restrict SSH. Allow port 22 in the security group from your own networks only.
- Protect the webmestre password. Keep it secret and rotate it if it may have been shared (Step 12). Give each person their own author account with the narrowest status that works.
- Protect the secret keys. Keep
config/cles.phpsecret and backed up with the database (Step 8). - Use a trusted certificate. Use your own DNS name and a certificate your browsers trust (Step 11).
- Keep SPIP current. Keep SPIP and its security screen current (Step 12), and install only plugins you trust.
- Patch the operating system. Unattended security upgrades are on, and
sudo apt-get update && sudo apt-get upgradeapplies everything else. MariaDB, PHP-FPM and PHP's zip extension come from Ubuntu's universe repository.sudo pro security-status --esm-appsshows whether Ubuntu Pro (ESM Apps) has security updates for them (none were pending when the image was built). - Take snapshots. Snapshot the data volume regularly (Step 8).
Support and licensing
SPIP is free software under the GNU General Public License version 3 (a copy is at /usr/share/doc/spip/LICENSE), and there is no per-user or per-CPU licence fee. This image installs the unmodified upstream release, without its test suites, plus the SecureAnyCloud site options file config/mes_options.php described above. 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 SPIP 4.4.28 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