# Session Handoff: Appwrite Bootstrap, Backup, and Bug Fixes **Date:** 2026-03-14 **Session Duration:** ~3 hours **Session Focus:** Fix Appwrite console crash, add bootstrap and backup playbooks **Context Usage at Handoff:** ~85% --- ## What Was Accomplished 1. Fixed `_APP_DOMAIN_TARGET_CNAME` null crash → `playbooks/templates/appwrite.env.j2` 2. Fixed idempotency: removed `force: true` from compose download → `playbooks/install_appwrite.yml` 3. Fixed `appwrite_response_format` undefined error → `playbooks/provision_database.yml`, `playbooks/provision_users.yml` 4. Created Appwrite bootstrap playbook → `playbooks/bootstrap_appwrite.yml` 5. Created Appwrite backup playbook → `playbooks/backup_appwrite.yml` 6. Diagnosed nginx CORS 405 on `apidev.bab.toal.ca` — **not fixed, open** 7. Written decision record → `docs/summaries/decisions-2026-03-14-domain-target-fix.md` --- ## Exact State of Work in Progress - **CORS / nginx**: `apidev.bab.toal.ca` returns HTTP 405 on OPTIONS preflight from nginx/1.20.1. Root cause: nginx config does not pass OPTIONS to backend. `appwrite.toal.ca` works fine. nginx config is managed by `nginxinc.nginx_core` role; no config templates exist in this repo yet. - **backup_appwrite.yml**: Written and structurally correct but **not yet run successfully end-to-end**. Needs a test run and restore verification. --- ## Decisions Made This Session | Decision | Rationale | Status | |----------|-----------|--------| | `_APP_DOMAIN_TARGET_CNAME` replaces `_APP_DOMAIN_TARGET` | Deprecated since Appwrite 1.7.0; compose `environment:` blocks list the new var, not the old one — old var silently never reached containers | CONFIRMED | | `appwrite_response_format \| default('1.6')` | Var undefined at module_defaults evaluation time; `1.6` is correct format for Appwrite 1.8.x | CONFIRMED | | bootstrap: no account creation task | Appwrite only grants console `owner` role via web UI signup; REST API creates `role: users` which lacks `projects.write` | CONFIRMED | | bootstrap: JWT required for console API | Session cookie alone gives `role: users`; JWT carries team membership claims including `projects.write` | CONFIRMED | | bootstrap: `teamId` fetched from `GET /v1/teams` | Required field in `POST /v1/projects` for Appwrite 1.8.x; discovered from browser network capture | CONFIRMED | | bootstrap: `['$id']` bracket notation | Jinja2 rejects `.$id` — `$` is a special character | CONFIRMED | | bootstrap: `vault_kv2_write` at `kv/oys/bab-appwrite-api-key` | `vault_kv2_put` does not exist; no PATCH operation — dedicated path avoids full-overwrite of other secrets | CONFIRMED | | backup: mysqldump runs while service UP | `--single-transaction` gives consistent InnoDB snapshot; service must be up for `docker compose exec` | CONFIRMED | | backup: `block/rescue/always` | Ensures `systemctl start appwrite` fires even if volume backup fails | CONFIRMED | --- ## Key Numbers - `appwrite_response_format` default: `1.6` - Vault path for API key: `kv/oys/bab-appwrite-api-key`, key: `appwrite_api_key` - Backup destination: `/var/backups/appwrite/YYYYMMDDTHHMMSS/` - Volumes backed up (8): `appwrite-uploads`, `appwrite-functions`, `appwrite-builds`, `appwrite-sites`, `appwrite-certificates`, `appwrite-config`, `appwrite-cache`, `appwrite-redis` - Volume excluded: `appwrite-mariadb` (covered by mysqldump) --- ## Conditional Logic Established - IF `appwrite_compose_project` not set THEN `_compose_project` defaults to `basename(appwrite_dir)` = `appwrite` → Docker volume names are `appwrite_appwrite-uploads`, etc. - IF bootstrap re-run THEN second API key created AND Vault entry overwritten — delete old key from console manually - IF backup fails during volume tar THEN `always` block restarts Appwrite — playbook exits failed, partial backup remains in `backup_dir` --- ## Files Created or Modified | File Path | Action | Description | |-----------|--------|-------------| | `playbooks/templates/appwrite.env.j2` | Modified | Replaced `_APP_DOMAIN_TARGET` with `_APP_DOMAIN_TARGET_CNAME`; added `_APP_DOMAIN_TARGET_CAA` | | `playbooks/install_appwrite.yml` | Modified | Removed `force: true` from `get_url` | | `playbooks/provision_database.yml` | Modified | `appwrite_response_format \| default('1.6')`; fixed long URL line | | `playbooks/provision_users.yml` | Modified | `appwrite_response_format \| default('1.6')` | | `playbooks/bootstrap_appwrite.yml` | Created | Session→JWT→teams→project→API key→Vault | | `playbooks/backup_appwrite.yml` | Created | mysqldump + volume tar + .env, block/rescue/always | | `docs/summaries/decisions-2026-03-14-domain-target-fix.md` | Created | Decision record for domain var fix and idempotency | | `CLAUDE.md` | Modified | Added trailing newline rule | --- ## What the NEXT Session Should Do 1. **Fix nginx CORS** — `apidev.bab.toal.ca` returns 405 on OPTIONS. Load `playbooks/install_nginx.yml`; find where `nginxinc.nginx_core.nginx_config` vars are defined in inventory and add OPTIONS passthrough. 2. **Test backup end-to-end** — run `ansible-navigator run playbooks/backup_appwrite.yml --mode stdout`, verify 8 volume tarballs + `mariadb-dump.sql` + `.env` in `/var/backups/appwrite//` 3. **Validate volume name prefix** — run `docker volume ls | grep appwrite` on bab1 to confirm prefix is `appwrite_` --- ## Open Questions Requiring User Input - [ ] **CORS fix scope**: Should nginx config live in this repo as templates, or managed elsewhere? — impacts `install_nginx.yml` completion - [ ] **Backup retention**: No rotation yet — each run adds a timestamped dir. Add cleanup task? - [ ] **Backup offsite**: 3-2-1 rule — is S3/rsync in scope? --- ## Assumptions That Need Validation - ASSUMED: Docker Compose project name for volumes is `appwrite` (basename of `/home/ptoal/appwrite`) — validate with `docker volume ls` - ASSUMED: `teams[0]` in bootstrap is always the admin's personal team — valid only if admin has one team --- ## What NOT to Re-Read - `docs/summaries/handoff-2026-03-14-appwrite-setup-final.md` — superseded; moved to archive --- ## Files to Load Next Session - `playbooks/install_nginx.yml` — if working on CORS fix - `playbooks/backup_appwrite.yml` — if testing/fixing backup - `docs/context/architecture.md` — for Appwrite API or EDA work