Files
nas-runbooks/hermes-nyora/dsh-vps-rotation-cles-incident-apikey-invalide.md
T

56 lines
3.7 KiB
Markdown

# 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/<projet>.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)