Files
bab-backend-ansible/docs/summaries/handoff-2026-03-14-appwrite-bootstrap-backup.md

6.2 KiB

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.canot 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 CORSapidev.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/<timestamp>/
  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