Run the VM deployment on a real VM before the deploy-and-build-a-frontend story is told publicly
- Dominant language
- C#
- Stars
- 6
- Forks
- 7
- Avg merge
- 4h 42m
- Merged PRs (30d)
- 307
Description
`docker-compose.vm.yml`, `.env.vm.example` and `docs/deploy-on-a-vm.md` are on `claude/barakocms-hardcoded-roles-xnx3g0` (#307). Most of what could go wrong is now covered by CI; what remains is the part CI genuinely cannot do.
## Now automated — `.github/workflows/deploy-smoke.yml`
**`compose` job** (verified locally, passes):
- Every compose file parses, including `quickstart/`, which guards three variables with `:?` and ships no `.env.example`.
- The VM stack **refuses to resolve** with a blank `JWT_KEY`. If the `${VAR:?}` guards ever stop working, this fails.
- The resolved config lands on `ASPNETCORE_ENVIRONMENT=Production`, version-pinned images, no `build:` anywhere, the frontend origin present in `CORS__AllowedOrigins`, and `NEXT_PUBLIC_API_URL` as a runtime variable.
**`smoke` job** (written, not yet run — first CI execution is the proof):
- Boots the suite image in **Production against an empty database**. Nothing else in CI does this: `IntegrationTestFixture` forces Development, so `AutoCreate.CreateOnly` has never run anywhere. That makes this a partial instance of #277.
- Signs in as the seeded admin, defines a publicly deliverable type, publishes an item, reads it back **anonymously** through `/api/public/{type}`.
- Asserts a CORS preflight from the configured frontend origin is allowed **and** one from an unlisted origin is refused.
- Asserts the admin image serves `/env-config.js` carrying an API URL supplied at runtime, with no build arg — the mechanism #309 is about.
- Dumps and restores into a scratch database, then asserts the published row is actually present rather than that the restore merely exited zero (#282).
## Still needs a real VM
CI cannot reach the two things that only exist on a real machine:
1. **TLS issuance.** Caddy requests certificates on first boot and Let's Encrypt validates over HTTP, so both A records must resolve *before* the stack starts. Getting the ordering wrong rate-limits you for the rest of the hour. The smoke job runs without Caddy for exactly this reason.
2. **A real browser on a real third origin.** CI asserts the preflight headers with `curl`; it does not prove a browser is satisfied by them.
Worth also confirming on the VM, since CI approximates rather than covers them: first-boot ordering on a cold machine, and an upgrade by bumping `BARAKO_TAG` and re-pulling.
## The run to do
On a clean VM with two A records already pointing at it:
1. `cp .env.vm.example .env.vm`, fill it, bring the stack up.
2. Both domains serve over HTTPS with valid certificates.
3. Sign in to the admin.
4. Create a type with `isPubliclyDeliverable: true` and a `Public` field, publish an item.
5. From a page on a third origin listed in `FRONTEND_ORIGINS`, `fetch` it **in a browser**.
6. Confirm a backup lands in `./backups`, restore it, boot against it.
7. Bump `BARAKO_TAG`, `pull`, `up -d`.
Step 5 is the product promise. Step 7 after step 4 is a small real instance of #277.
Fix `docs/deploy-on-a-vm.md` as you go — a guide that has been followed once beats one written from the source.
## Done when
- Steps 1–7 have been run on a real VM by someone who did not write the files.
- The `smoke` job has passed at least once in CI.
- Anything that failed is fixed or written down as a known rough edge.
Related: #307, #309, #277, #282, #283.
Contributor guide
Assessment
This issue has not been assessed yet.