# Server — dvla-api Production host for the `dvla-api` Laravel application. Single VPS, single app. This file is the source of truth for how the box is configured. Update it when you change the box. ## Host - **Provider / type:** Hetzner Cloud CX23 (2 vCPU, 4 GB RAM, 80 GB disk) - **OS:** Ubuntu 24.04 LTS (noble) - **Public IP:** 37.27.203.46 - **Hostname:** ubuntu-4gb-dvla-api - **Swap:** 2 GB swapfile at `/swapfile` (mounted via `/etc/fstab`) ## Users (UPDATED) - deploy (UID 1000) — human admin, sudo, your SSH key - deploy-dvla (UID 1001) — owns and runs dvla-api, no sudo, your SSH key - www-data — nginx only, no group memberships in app users ## PHP-FPM (UPDATED) - Pool: /etc/php/8.4/fpm/pool.d/dvla-api.conf - Runs as deploy-dvla - Socket: /run/php/php8.4-fpm-dvla.sock - pm.max_children = 3 - Default www.conf disabled (renamed to www.conf.disabled) ## Filesystem perms - /var/www/dvla-api: 2755 (traversable so nginx can reach public/) - App subdirs: 2750 (deploy-dvla owner+group only) - public/: 755/644 (world-readable, intentional) - .env: 600 - storage/, bootstrap/cache/: 2770 (writable by deploy-dvla) - database/: 2770, database.sqlite: 660 ## Known gaps - No backups - No HTTPS yet - Token-based git auth (not SSH) — Pangolin doesn't forward SSH to Gitea o ## Web stack - **nginx** 1.24 — site config: `/etc/nginx/sites-available/dvla-api` - Listens on `:80` (HTTP only — TLS pending) - `server_name 37.27.203.46;` - Document root: `/var/www/dvla-api/public` - **PHP-FPM** 8.4 — pool: default `www.conf` - Runs as `www-data:www-data` - Socket: `/run/php/php8.4-fpm.sock` - `pm = dynamic`, `pm.max_children = 5` (CX23-appropriate) ## Application - **Path:** `/var/www/dvla-api` - **Owner:** `deploy:www-data`, directories have SGID bit (`drwxrwsr-x`) so new files inherit the `www-data` group automatically - **Framework:** Laravel 11 on PHP 8.4 - **Git remote:** SSH to Gitea via deploy key (see `DEPLOY.md`) - **Branch deployed:** `main` ## Database — SQLite - **File:** `/var/www/dvla-api/database/database.sqlite` - **Perms:** file `660`, directory `770`, both owned `deploy:www-data` - Directory must be writable by `www-data` so SQLite can create `-journal` / `-wal` / `-shm` siblings - **Journal mode:** WAL (enabled with `sqlite3 database/database.sqlite "PRAGMA journal_mode=WAL;"`) - **Backups:** __ `SESSION_DRIVER`, `CACHE_STORE`, and `QUEUE_CONNECTION` are all `database`, meaning sessions/cache/queue tables live in the same SQLite file as app data. Acceptable for low traffic; revisit if write contention shows up (`database is locked` errors in `storage/logs/laravel.log`). ## Queue / scheduler - **Worker:** __ - **Scheduler:** __ ## Network / firewall - **UFW:** __ - **Open ports (verified via `ss -tlnp`):** - 22 — SSH - 80 — HTTP (nginx) - 53 — systemd-resolved, loopback only (not public) - **TLS:** __ ## Backups __ ## Known divergences from the multi-app pattern in project chats This box was set up for a single app and intentionally simplified: - Single `deploy` user instead of `deploy-` - Default `www-data` PHP-FPM pool instead of a per-app pool - No Redis (cache/sessions/queue all on SQLite) These are acceptable as long as this box hosts one app. Revisit the older project chats before adding a second app to this VPS.