# Production Deployment Guide Deploying the XAMXAM production nginx configuration and administering the site. ## Overview - **Host**: `xamxam` (SSH alias), app root `/var/www/xamxam/` - **PHP Version**: 8.4 - **SSL/TLS**: Terminated by an upstream reverse proxy (nginx itself listens on 80) - **Document Root**: `/var/www/xamxam/public/` (deployed flat, not under `app/`) - **Web / FPM user**: `www-data`, app group: `xamxam` ## Quick deployment (recommended) Everything is orchestrated from your local machine through the justfile. `just deploy-nginx` uploads both `nginx/xamxam.conf` and `scripts/deploy-server.sh` to the server, runs the latter as root (installing the config, fixing permissions, testing and reloading nginx and php-fpm), then cleans up the remote temp files: ```bash just deploy-nginx ``` No manual server-side step is needed — the recipe already does it. For a full code + dependencies + migrations deploy, run `just deploy` (which includes `deploy-nginx`). See [`../../docs/deployment.md`](../../docs/deployment.md). What `scripts/deploy-server.sh` does (as root): - Fixes ownership to `www-data:xamxam` across `/var/www/xamxam/` - Sets directory permissions to **2775** (setgid) and files to **664** - Locks SQLite databases (and WAL/SHM sidecars) to **660**; `.env` to **640** - Creates writable cache / upload-tmp / `var/{cache,logs,tmp}` dirs for php-fpm - Provisions `/var/log/xamxam/` (app log dir) and `/var/backups/xamxam/` (backups) - Installs a php-fpm session-GC tuning file (`zz-xamxam-session.ini`) - Installs `nginx/xamxam.conf` into `sites-available`, symlinks it, backs up old uploads, prunes old backups, validates with `nginx -t`, and reloads nginx + php-fpm ## Admin authentication The admin panel is protected by the application's **PHP session auth layer** (`src/AdminAuth.php`), **not** by nginx `htpasswd`/Basic-auth. The user supplies a single password on `/admin/login.php`; no username, no `/etc/nginx/.htpasswd`. Configure the admin password in the admin panel at `/admin/parametres` → Account tab (a fresh DB starts unauthenticated until a password is set). See [`PHP_AUTH_LAYER.md`](PHP_AUTH_LAYER.md) for the full authentication details. ## Verification After a successful deploy: ```bash curl -I https://xamxam.erg.be/ # expect 200 curl -I https://xamxam.erg.be/admin/ # expect 200 (login page / 302 to it) curl -I https://xamxam.erg.be/storage/xamxam.db # expect 404 / 403 (blocked) curl -I https://xamxam.erg.be/src/Database.php # expect 404 / 403 (blocked) just deploy-verify-permissions # expect "All permissions OK" ``` Security headers (`X-Frame-Options`, `X-Content-Type-Options`, `Strict-Transport-Security`, `Referrer-Policy`, `Permissions-Policy`, `Content-Security-Policy`) are emitted by the nginx config; see [`SECURITY_HEADERS.md`](SECURITY_HEADERS.md). ## Troubleshooting ### 502 Bad Gateway ```bash sudo systemctl status php8.4-fpm sudo systemctl restart php8.4-fpm ``` ### Nginx config error ```bash ssh xamxam sudo nginx -t ``` ### Still getting 403 Forbidden Check ownership/group and that `www-data` is a member of the `xamxam` group: ```bash ls -la /var/www/xamxam/public/index.php groups www-data # should include xamxam ``` If permissions are wrong, re-run the permission-fixing deploy script: ```bash just deploy-nginx # re-applies deploy-server.sh (perms + config) ``` ## See also - [`QUICK_REFERENCE.md`](QUICK_REFERENCE.md) — command reference - [`PHP_AUTH_LAYER.md`](PHP_AUTH_LAYER.md) — admin authentication - [`SECURITY_HEADERS.md`](SECURITY_HEADERS.md) — security headers - [`../../docs/deployment.md`](../../docs/deployment.md) — full deployment, backups, rollback