Server
Requirements
Section titled “Requirements”| Software | Version |
|---|---|
| PHP | 8.5 or newer (CLI and FPM/module) |
| CodeIgniter | 4.7 or newer |
| MySQL | 8.0 or newer, 8.4 LTS recommended |
| Web server | any; the document root must be public/ |
PHP extensions:
| Extension | Needed for |
|---|---|
intl, mbstring, json, sodium |
Anvil itself (key ring, MFA secrets, API secrets) |
mysqli |
CodeIgniter’s MySQLi database driver |
fileinfo |
content type detection of uploads |
curl |
single sign-on with OpenID Connect (CodeIgniter’s CURLRequest) |
openssl, dom, libxml |
SAML (onelogin/php-saml) |
zip, xmlreader |
exports to XLSX (OpenSpout) |
Composer checks most of them; run the check on the target server with the locked versions:
composer check-platform-reqs --no-devphp spark phpini:checkphpini:check compares php.ini with recommended production values
(php spark phpini:check opcache for OPcache). Make sure post_max_size
and upload_max_filesize allow Config\Anvil::$fileMaxSize (10 MB by
default; one upload can carry up to 10 files).
Server layout
Section titled “Server layout”- The document root is
public/.app/,vendor/,writable/and.envmust not be reachable over HTTP. writable/is the only directory the PHP process writes to at runtime:cache/,logs/,session/(file sessions),anvil/files/(uploads),anvil/exports/(export files). Give it to the user PHP runs as and keep the application code read-only for that user.public/assets/anvil/(Config\Anvil::$assetsPath) is written byanvil:publishduring the deployment, not at runtime.- Uploads and exports can live elsewhere (
Config\Anvil::$filePath,$exportPath), but always outside the document root.
Web server
Section titled “Web server”Point the document root to public/ and send every request that is not a
file to index.php.
nginx with PHP-FPM
Section titled “nginx with PHP-FPM”server { listen 443 ssl; http2 on; server_name admin.example.com; root /var/www/app/public; index index.php;
client_max_body_size 12m; # at least Config\Anvil::$fileMaxSize
location / { try_files $uri $uri/ /index.php$is_args$args; }
location ~ \.php$ { include fastcgi_params; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; fastcgi_param DOCUMENT_ROOT $realpath_root; fastcgi_pass unix:/run/php/php8.5-fpm.sock; }
# Assets carry a version (?v=<hash>), so they can be cached long. location /assets/anvil/ { expires 1y; add_header Cache-Control "public, immutable" always; }
location ~ /\. { deny all; }}$realpath_root makes PHP-FPM follow the current symlink of a new
release, see Releases.
Apache
Section titled “Apache”<VirtualHost *:443> ServerName admin.example.com DocumentRoot /var/www/app/public
<Directory /var/www/app/public> AllowOverride All # the .htaccess of CodeIgniter Require all granted </Directory></VirtualHost>CodeIgniter’s public/.htaccess rewrites to index.php (mod_rewrite).
| Setting | Value |
|---|---|
upload_max_filesize, post_max_size |
at least $fileMaxSize; post_max_size a little larger (form fields) |
memory_limit |
256M; exports with many rows run in the queue worker |
max_execution_time |
30–60 s for web requests |
expose_php |
Off |
session.use_strict_mode |
1 |
opcache.enable |
1 |
opcache.validate_timestamps |
0 in production; reload PHP-FPM after every release |
php spark phpini:check and php spark phpini:check opcache compare the
current values with CodeIgniter’s recommendations.