Deployment
Deployment
A few practical rules for shipping changes to the production server. Keep specific addresses, access details and credentials out of public documentation and out of the repository (in .env and your private notes).
Web architecture
A typical production setup: nginx in front serves all static files (css/js/img) directly, while PHP is proxied to Apache/PHP-FPM (which reads .htaccess). The key rules below follow from this.
After editing templates (.tpl)
Compiled templates are cached in storage/cache/tpl/. After changing a .tpl in production, clear the cache:
rm -f storage/cache/tpl/*
Locally the cache invalidates by file modification time automatically; the admin has Settings → Performance → Clear cache. It's also useful to reload PHP-FPM to reset opcache.
After editing static files (.css/.js)
nginx caches static files for a long time (e.g. 30 days). After changing a file, bump the version in the include:
<link rel="stylesheet" href="/templates/<theme>/assets/landing.css?v=6">
?v=6 → ?v=7. Otherwise returning visitors get the old version from cache. Cache headers are configured in the nginx config, not in .htaccess (for static files .htaccess doesn't apply — nginx serves them).
File permissions
Site files usually belong to a dedicated system user. After copying new files, restore the owner (chown) and, if needed, permissions so the PHP process can read/write (storage/, public/assets/plugins/).
Database
- Local — PostgreSQL, production — MySQL: write cross-database code (see Migrations).
- Before
DELETE/ALTERin production — back up (mysqldumpof the relevant table) and use narrowWHEREconditions. - MySQL implicitly commits DDL — keep this in mind when relying on rollback.
Pitfalls (don't step on these)
| Symptom | Cause | Fix |
|---|---|---|
| Visitors see old CSS/JS | nginx static cache | bump ?v= |
| Old look after editing a .tpl | compiled-template cache | clear storage/cache/tpl/* |
| Apache 500 | <Directory>/php_flag in .htaccess with PHP-FPM | remove these directives |
| External script doesn't work | CSP blocks the CDN | host the asset locally |
| Cache headers not applied | set in .htaccess | set in the nginx config |
Post-deploy check
A simple self-test of the home page (with a User-Agent so bot filters don't kick in):
curl -s -o /dev/null -w '%{http_code}' -A "Mozilla/5.0" https://<domain>/
200 means all good. Check key sections too after large changes.