Demo Deployment Runbook
Use this page when you want the shortest executable path to launch the first hosted full-stack demo.
This runbook assumes:
- backend runtime uses
docker-compose.demo.yml - backend config starts from
.env.demo.example - frontend build starts from
.env.demo-live.example - the first rollout is evaluator-only or read-mostly, not a fully open writable public environment
1. Prepare the backend host
Minimum host capabilities:
- Docker Engine with Compose support
- one public HTTPS entry for the API
- private container networking for MySQL and Redis
- enough disk for images, database, Redis appendonly data, and logs
Recommended baseline:
- 2 vCPU
- 4 GB RAM
- persistent volume for database and Redis
2. Prepare backend configuration
On the backend host:
cp .env.demo.example .env.demoReplace at least these values:
APP_URLREVERB_HOSTREVERB_APP_KEYREVERB_APP_SECRETAPP_KEY- mail sender values if you do not want placeholder addresses
Do not reuse production secrets in the demo environment.
3. Start the backend runtime
docker compose -f docker-compose.demo.yml pull
docker compose -f docker-compose.demo.yml up -d
docker compose -f docker-compose.demo.yml exec app php artisan key:generate --force
docker compose -f docker-compose.demo.yml exec app php artisan migrate:fresh --seed --forceIf you need a non-destructive update after the first seed, replace migrate:fresh --seed with:
docker compose -f docker-compose.demo.yml exec app php artisan migrate --force4. Verify the backend
Use these checks before pairing the frontend:
curl --fail --silent https://demo-api.example.com/api/health/live
curl --fail --silent https://demo-api.example.com/api/health/ready
docker compose -f docker-compose.demo.yml exec app php artisan about --only=environmentExpected result:
- live returns
status: alive - ready returns success
- artisan bootstrap succeeds inside the running container
5. Build the frontend against the live backend
In the frontend repository:
cp .env.demo-live.example .env.demo-liveSet these values to the demo backend:
VITE_SERVICE_BASE_URLVITE_OTHER_SERVICE_BASE_URLVITE_REVERB_SCHEMEVITE_REVERB_HOSTVITE_REVERB_PORTVITE_REVERB_APP_KEY
Then build:
pnpm install
pnpm build --mode demo-liveDeploy the generated dist bundle to your static host.
6. Verify the full stack
Before sharing the environment externally, run these checks:
Backend repository
php artisan openapi:lint
php artisan security:baselineFrontend repository
pnpm typecheck:api
pnpm test:fullstackBrowser-level sanity
Confirm manually:
- login works with seeded demo credentials
- tenant switching works
- user list loads
- audit list loads
- selected writable demo drawers still save correctly
7. Reset policy
For the first hosted demo, use one of these two policies:
- evaluator demo:
migrate:fresh --seedon every controlled redeploy - read-mostly public demo: nightly
migrate:fresh --seed
If you expose low-risk writable flows publicly, add an hourly cleanup for known demo-only records.
8. Rollback
Use immutable backend image tags and immutable frontend build artifacts.
Rollback sequence:
- redeploy the previous frontend bundle
- switch
APP_RUNTIME_IMAGEin the backend environment to the previous GHCR tag - restart the backend stack
- rerun live and ready probes
If the issue is data-related rather than image-related:
- stop public access temporarily
- run
migrate:fresh --seed - restore the previous frontend and backend versions only if code drift is involved
9. First public promotion checklist
Do not share the demo URL until all of these are true:
- backend docs site is public
- frontend docs site is public
- frontend preview is public
- full-stack pairing smoke is green
- backend runtime health probes are green
- the demo reset policy is documented
- the seeded credentials and access policy are documented