Gamine CMS¶
Status: Scaffolded (NOT YET DEPLOYED) — Vikunja critical path: #610→#611→#600→#601→...
Decision: ADR-0005 — Wagtail chosen over Strapi/Ghost/WordPress
Wagtail 6.x CMS for the gamine.org public website. Replaces the legacy WordPress installation on SiteGround.
Architecture¶
gamine-brain (intelligence) ──POST /api/cms/import/post/──► gamine-cms (Wagtail)
│
infra-postgres
(gamine_cms DB)
│
MinIO (gamine-cms-media)
│
infra-nginx ──► gamine.org
Factory → Product model: Approved content suggestions from gamine-brain flow automatically into Wagtail as drafts via a single authenticated POST endpoint. Editors (Marta, Alice) review and publish from the Wagtail admin.
Key paths¶
| Item | Path |
|---|---|
| Source code (local) | ~/Documents/JB_Hostinger/gamine-cms/ |
| VPS deployment | /opt/gamine-cms/ (when deployed) |
| Forgejo repo | joaobrazao/gamine-cms |
| Compose file | /opt/rabbithall-compose/ (to be added) |
| DB | gamine_cms on infra-postgres |
| MinIO bucket | gamine-cms-media |
| Admin URL | https://gamine.org/cms-admin/ |
Stack¶
| Component | Choice |
|---|---|
| CMS framework | Wagtail 6.x |
| Backend | Django + Python 3.11 |
| Database | PostgreSQL (gamine_cms schema) |
| Media storage | MinIO (gamine-cms-media bucket) |
| Multilingual | wagtail-localize (PT + EN) |
| Admin 2FA | django-otp (TOTP) |
| Container | Docker (single gamine-cms service) |
| Port | 8200 internal |
Environment variables¶
DJANGO_SECRET_KEY=<from Vaultwarden>
DATABASE_URL=postgresql://litellm:<pwd>@infra-postgres:5432/gamine_cms
MINIO_ENDPOINT=minio:9000
MINIO_BUCKET=gamine-cms-media
MINIO_ACCESS_KEY=<from Vaultwarden>
MINIO_SECRET_KEY=<from Vaultwarden>
CMS_IMPORT_API_KEY=<from Vaultwarden> # used by gamine-brain to POST drafts
ALLOWED_HOSTS=gamine.org,localhost
Deployment critical path¶
All 53 tasks are tracked in Vikunja (#600–#668). High-level sequence:
- #610 Generate
CMS_IMPORT_API_KEY+ store in Vaultwarden - #611 All secrets in Vaultwarden
- #600 Clone repo to VPS + create
.env+ creategamine_cmsDB - #601 First Docker deploy +
manage.py migrate+createsuperuser - #613 gamine-brain rebuild with
/api/cms/import/post/endpoint - #614 Frontend build + "↗ Site" button in gamine-brain UI
- #635+#636 2FA + rate limiting
- #639+#640 RGPD pages
- #621 Marta validates brand book
- #625 E2E test: approve → draft → publish → live
User roles¶
| User | Role | Access |
|---|---|---|
| Marta | Admin | Full Wagtail admin |
| Alice | Editor | Create/edit pages, submit for review |
| Cristina | Editor | Create/edit pages, submit for review |
Security notes¶
/cms-admin/and/django-admin/rate-limited at 10 req/min via nginx (#636)- All admin users require TOTP 2FA via django-otp (#635)
- CSRF enforced by Django (default)
- Session cookies: httpOnly + SameSite=Lax
- Content-Security-Policy tuned via nginx (#638)
Backup and restore¶
Daily backup via /opt/backup.sh → gamine_cms_<DATE>.sql.gz kept 30 days.
Restore procedure: see Runbook — Restore gamine-cms DB
Related¶
- ADR-0005: Wagtail for gamine-cms
- Runbook: Restore gamine-cms DB
- Vikunja tasks: #600–#668