diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 527565e..11de117 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -141,6 +141,74 @@ Deploy API endpoint used by CI: - `GET /api/v1/deploy?uuid=` - Authorization: `Bearer ` +### 3.1 Token Requirements (Important) + +If CI fails with `Coolify API token rejected during preflight (HTTP 403)`, token exists but lacks access to API target. + +Use this checklist: + +1. Create token in same Coolify instance that hosts `omo-bot-backend` and `omo-bot-dashboard` resources. +2. Ensure token owner has access to project/team containing those resources. +3. Ensure token is API token (not UI session token/cookie). +4. Set `COOLIFY_BASE_URL` to Coolify root URL only (example: `https://coolify.yourdomain.com`), no extra path like `/project/...`. +5. Rotate token if unsure, then update Gitea secret `COOLIFY_API_TOKEN`. + +Required permissions to grant (minimum): + +- Project/resource read access for both deploy targets (`omo-bot-backend`, `omo-bot-dashboard`) +- Deploy/trigger permission on both resources +- Team/project membership that includes those resources (not observer/read-only) + +If your Coolify token form shows these permissions: + +- root +- write +- deploy +- read +- read:sensitive + +Use this selection for CI deploy token: + +- Required: read + deploy +- Optional: write (only if your instance still blocks deploy with read+deploy) +- Avoid for CI: root +- Optional and sensitive: read:sensitive (only needed when debugging APIs that must return secrets/log internals) + +Tip: Start with read + deploy. If preflight still returns 403, temporarily add write to verify scope mismatch, then reduce to least-privilege that still works. + +Preflight check from local shell (should NOT return `401` or `403`): + +```bash +curl -i \ + -H "Authorization: Bearer $COOLIFY_API_TOKEN" \ + "$COOLIFY_BASE_URL/api/v1/deploy" +``` + +Resource trigger checks (match CI fallback logic): + +```bash +# Variant 1: GET + Bearer +curl -i -G \ + -H "Authorization: Bearer $COOLIFY_API_TOKEN" \ + --data-urlencode "uuid=$COOLIFY_RESOURCE_UUID" \ + "$COOLIFY_BASE_URL/api/v1/deploy" + +# Variant 2: POST JSON + Bearer +curl -i -X POST \ + -H "Authorization: Bearer $COOLIFY_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d "{\"uuid\":\"$COOLIFY_RESOURCE_UUID\"}" \ + "$COOLIFY_BASE_URL/api/v1/deploy" + +# Variant 3: GET + raw Authorization token +curl -i -G \ + -H "Authorization: $COOLIFY_API_TOKEN" \ + --data-urlencode "uuid=$COOLIFY_RESOURCE_UUID" \ + "$COOLIFY_BASE_URL/api/v1/deploy" +``` + +If all variants return `403`, issue is permissions/scope in Coolify, not Gitea secret injection. + ## 4. Configure Gitea Action Secrets/Variables In Gitea repository settings, add Actions secrets: @@ -180,3 +248,15 @@ Current workflow in `.gitea/workflows/ci-cd.yml` triggers backend and dashboard 3. Open dashboard URL and run OAuth login flow. 4. Confirm Discord redirects back to `https://admin.openmicodyssey.com/oauth/discord/callback` without `404`. 5. Validate Admin API auth behavior with and without bearer token. + +## 7. Coolify 403 Troubleshooting + +When CI fails in `Validate Coolify API access` with HTTP `403`: + +1. Confirm token belongs to correct Coolify instance and team/project. +2. Confirm resource UUIDs are from same instance and still valid. +3. Re-run local preflight curl from section 3.1. +4. Recreate token and update Gitea secret. +5. Re-run pipeline. + +Current CI workflow already prints sanitized response snippets for deploy failures and tries auth/method fallback variants in `.gitea/workflows/ci-cd.yml`.