# dotnews-paas — working notes for Claude Self-hosted, Docker-free deployment platform: Caddy → (Varnish) → app, driven by one bash CLI (`bin/paas`, the ONLY writer of server state) and a Fastify/EJS panel (`panel/`) that shells out to it. Full architecture: `docs/README.md`. ## Runtimes / flavours - Per **app**: `RUNTIME=node|laravel` in `/srv/paas/apps.d/.conf`, fixed at creation. Node = PM2 process on `127.0.0.1:PORT`; Laravel = PHP-FPM pool + Caddy `php_fastcgi` (+ loopback `http://127.0.0.1:PORT` site so health/monitoring keep the port contract). Varnish is refused for Laravel (VCL strips cookies). - Per **server**: `bootstrap.sh` plain = Node-only (production today); `WITH_LARAVEL=1` adds PHP 8.3/8.4, composer, MariaDB and writes `RUNTIMES=node,laravel` to `/srv/paas/paas.conf` — the flag panel + CLI gate on. Never install PHP/MariaDB on node-only servers; keep every Laravel/DB feature capability-gated so existing servers see zero change. - `paas db` (MariaDB per app, creds into `shared/.env`) is runtime-agnostic. ## Golden template policy (Proxmox, prox3.younex.de) - There is **exactly one** golden template (`infra/golden-template.md` names the current VMID). It is generic — no instance state — and serves both flavours; the flavour is chosen on the clone by the wizard `sudo paas-init` (`bin/paas-init`), which asks panel domain, admin password, Node.js/Laravel, system-domain base, ACME e-mail, pulls the repo and runs `bootstrap.sh`. - **Whenever a feature lands in production (committed + deployed), refresh the template**: clone current template → `git pull` → `bootstrap.sh` → `sudo PREINSTALL_LARAVEL=1 infra/generalize-golden.sh` → `qm template` → set the Notes from `infra/golden-template-notes.md` (Markdown only, no HTML — Proxmox shows HTML literally) → verify with one test clone → **destroy the previous template and the test clone**. Update the VMID/table in `infra/golden-template.md` and the r-number in the same commit. - Each spawned instance needs its own panel domain (production: `deploy.younex.de`). ## Conventions - `paas` runs as user `deploy`, never root; anything needing root goes through the exact-command sudoers allowlists (`/etc/sudoers.d/paas`, `paas-laravel`). - Generated configs follow stage → validate → commit → reload (`regen_caddy`, `regen_vcl`, `regen_fpm`); never hand-edit generated files. - Releases are immutable dirs + `current` symlink; deploys are health-gated on `PORT+1000` before the flip. Laravel deploys never reload php-fpm (`resolve_root_symlink` keys opcache per release). - Registry keys are added to `reset_app_vars` in `bin/paas`; panel reads them via `paas info`. New project flags follow the `multi_label` precedent (`panel/lib/db.js` migration block, `server.js` route, `project.ejs` toggle). - Lint before committing: `bash -n` + `shellcheck -S warning` for bash, `node --check` for the panel; EJS can be render-tested with mock data. - Pushing `main` deploys the platform to production automatically (LAN Jenkins job `paas-platform` → `ci/Jenkinsfile.platform` → `paas-self-deploy` on the VM, `docs/ci-platform-deploy.md`). No manual rsync/bootstrap on production; verify with `sudo paas-self-deploy status|verify`, undo with `rollback`.