diff --git a/hermes-nyora/dsh-vps-rotation-cles-incident-apikey-invalide.md b/hermes-nyora/dsh-vps-rotation-cles-incident-apikey-invalide.md new file mode 100644 index 0000000..37b58b6 --- /dev/null +++ b/hermes-nyora/dsh-vps-rotation-cles-incident-apikey-invalide.md @@ -0,0 +1,55 @@ +# DSH VPS — Rotation des cles API et incident « API key is invalid » + +**Instance auteur** : hermes-nyora +**Date** : 2026-08-25 +**Tags** : dsh, vps-contabo, docker, secrets, rotation, bifrost, opencode +**Statut** : clos — rotation complete, revocation confirmee, tour UI web verifie au vert + +--- + +## Contexte + +Rotation des deux cles du dsh-vps (VK Bifrost `sk-bf-37***` + cle OpenCode Zen `sk-DWb***`) apres double exposition : passage par canal de chat (Telegram) ET commit initial du depot `bolbol/dsh-vps` (22a18ae) embarquant les valeurs reelles en fallback heredoc de `entrypoint.sh` et en dur dans `docker-compose.yml`. + +Rotation executee par Nabil via script local (saisie `read -s`, valeurs jamais passees par un canal) : ecriture atomique de `$DSH_HOME/.credentials.yaml` (volume `dsh_vps_home`) + `.env` projet. + +## L'incident (25/08) + +Apres rotation : « This turn failed — API key is invalid » dans l'UI web DSH, alors que tous les fichiers de configuration semblaient a jour. + +Diagnostic structure (mission Gemini, cadrage hermes-nyora, 3 hypotheses a discriminer) : + +| Hypothese | Test | Verdict | +|---|---|---| +| H1 session navigateur perimee | sonde headless echouait aussi (401 AuthError) | eliminee | +| H2 process demarre avant la rotation | StartedAt conteneur < rotation, ENV conteneur = anciennes cles | confirnee partielle | +| H3 residus de configuration | cles revoquees EN DUR dans `docker-compose.yml` hote + `entrypoint.sh` | cause racine | + +**Piege de verification central** : le depot Gitea montrait les valeurs tronquees (`sk-bf-...e9d4`, sanitisation manuelle lors du commit) mais le fichier REEL sur l'hote portait les cles completes. Les preuves du premier rapport portaient sur le repo, le runtime lisait l'hote. + +## Fix final + +1. Cles externalisees dans `/home/dsh-agent/dsh-vps/.env` (chmod 600, couvert par `*.env` du .gitignore), injection via `env_file:` (commit 7cdda5d). +2. Fallbacks interdits : `${VAR:-sk-reelle}` remplace par `${VAR:?variable manquante}` partout (commit 7cdf4c1) — le scaffold echoue bruyamment plutot que de demarrer avec une vieille valeur. +3. `docker compose up -d --build` (recreation, pas restart), prefixes ENV du conteneur verifies alignes sur `.env`. +4. `verify-dsh.sh` durci : `process.exit` explicite sur les tests node http sinon un test echoue peut passer vert (commit e9ef336). +5. Revocation des anciennes cles : admin Bifrost (VK) + dashboard OpenCode — confirmee par Nabil. +6. Validation finale : session UI web NEUVE, tour reel reussi (le symptome initial reproduit au vert). + +## Ce qui ne fonctionne PAS + +| Tentative | Resultat | Raison | +|---|---|---| +| `docker compose restart` apres changement de cles | anciennes vars conservees | restart ne relit NI le `.env` NI le compose | +| Sanitiser uniquement rapports/preuves | secrets vivants dans les fichiers scaffoldes | lire INTEGRALEMENT chaque fichier qui entre en Git | +| Diagnostiquer depuis des curls externes seuls | ne voit pas ce que le process charge | comparer StartedAt vs horodatages config + printenv DANS le conteneur | + +## Regle fleet-wide associee + +Posee dans context-hub (scope infra, cle `secrets_rule`, relue en live le 25/08) : aucune valeur de cle/secret en clair dans un message, rapport ou mail. Depot obligatoire dans `/volume1/docker/.secrets-staging/.env` (hors git), reference par chemin uniquement. Reproduite dans l'`AGENTS.md` du workspace DSH (mecanisme natif `dsh-agent-instructions`). + +## References + +- Depots : `bolbol/dsh-vps` (22a18ae → 43c5dec), `bolbol/context-hub` (e7f78f8, lecon coding-bp-0001) +- Script de rotation : `workspace/scripts/rotate-dsh-keys.sh` (hermes-nyora) +- Garde-fou rejouable : `.agents/verify-dsh.sh` (5 tests : pnpm, plugin, MCP authentifie, isolation 403, nettoyage skill mort)