No description
  • Python 47.8%
  • Shell 47.8%
  • Dockerfile 1.5%
  • Ruby 1.5%
  • Nix 1.4%
Find a file
Nicolas Sanitas a92e3fc19d backlog(TASK-149): régression latence chaude 0.17 (~20s vs 2,9s) — ticket optimisation
G3 non mesuré avant le flip (mea culpa : supposé 'moteur constant = latence OK', faux).
Toléré par Nicolas mais à optimiser (trimmer défauts 0.17 environment_probe/guidances/
coding_context qui gonflent le prefill). NEXT_TASK_ID 149->150.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 09:45:13 +02:00
.claude/skills governance(TASK-66): sign-off humain pour ratification ADR + allocateur ID anti-collision 2026-05-27 21:40:48 +02:00
.planning/reports Round 7 oMLX BLINDÉ : 11 phases / 250-350 tests / TTFT killer test SSD cache / contribution benchmark public oMLX 2026-05-16 15:06:54 +02:00
atlas backlog(TASK-79): Done — cache idle persist 30min+, verdict accepter le cold rare 2026-05-29 17:34:37 +02:00
backlog backlog(TASK-149): régression latence chaude 0.17 (~20s vs 2,9s) — ticket optimisation 2026-06-26 09:45:13 +02:00
docs backlog: park TASK-146 (spike STOP, 2 transports KO) + TASK-148 (intégration 401) + capitalise 0.17 2026-06-25 11:10:17 +02:00
miniflux hermes(TASK-102): feeds-as-code OPML + /suis Telegram + GitOps auto-commit 2026-06-02 17:45:05 +02:00
nix atlas(TASK-140): OLLAMA_ORIGINS pour Web Clipper + déploiement plist ollama via GitOps Atlas 2026-06-24 12:00:39 +02:00
queue-staging atlas: gitops brew-only + formula 0.3.9rc1 + cleanup stale queue-staging 2026-05-20 06:59:23 +00:00
scripts fix(gitops): garde-fou anti-revert forward-only — empêche le miroir GitHub périmé de reverter la prod 2026-06-25 11:42:26 +02:00
secrets TASK-132 Done: Telegram restauré + SOPS-backup secrets 2026-06-12 19:48:52 +02:00
vault-templates vault-templates(35-Actions): rattachements en liste YAML + wikilinks quotés (sync vault — fix Obsidian Properties clickable) 2026-06-03 10:38:28 +02:00
vps hermes(TASK-144): PROMOTION 0.17.0 en prod — decision-27 ratifiée (GO Nicolas 2026-06-25) 2026-06-25 11:17:08 +02:00
.gitignore task-106 + task-105: inbox unique 00-Inbox + dispatch (étage 1) + branche action + digest-actions 2026-06-03 01:45:55 +02:00
.mcp.json feat(backlog): ticketing Backlog.md + runner ticket-agent (3 types) + MCP 2026-05-22 11:36:32 +00:00
.sops.yaml secrets: commit infra.yaml.sops (rmfakecloud JWT chiffré) + sops regex accepte .yaml.sops 2026-06-10 18:01:56 +02:00
CLAUDE.md governance(TASK-66): sign-off humain pour ratification ADR + allocateur ID anti-collision 2026-05-27 21:40:48 +02:00
COWORK-START-HERE.md run-cowork-onboarding: bootstrap des nouvelles sessions Cowork 2026-05-19 16:36:55 +00:00
cron-desired.txt veille(TASK-65): cron 8h agenda + 13h mail-triage + notif Telegram (HITL) 2026-05-27 21:29:50 +02:00
README.md chore(night2): housekeeping massif post-Mission 4 + fix gitignore .claude/ 2026-05-18 13:29:49 +02:00
watch-releases.txt TASK-118 HOLD + TASK-119 Done: QAT gated 0.30, veille post-WWDC26 livrée 2026-06-10 12:34:48 +02:00

infra/ — Infrastructure-as-Code Second Brain Nicolas

Repo source-of-truth de toute l'infra du second cerveau. Idempotent, déclaratif, rejouable depuis zéro en quelques commandes.

Dernière mise à jour : 2026-05-17 (post-Mission 3c)

Architecture en bref

atlas      = Mac mini M4 Pro 24 GB    user: exalti    (oMLX — pure inférence LLM)
apollon    = VPS Hostinger Paris      user: nicolas   (Hermes, CouchDB, livesync-cli, Caddy, Forgejo, Miniflux, vault source-of-truth)
artemis    = MacBook                  user: nicolas   (Claude Code, Obsidian, dev/devops)
echo       = iPhone                                   (Obsidian iOS, Telegram, WhatsApp)

⚠️ Convention SSH asymétrique : exalti@atlas, nicolas@apollon, nicolas@artemis.

  • Tailnet Tailscale : taildcde56.ts.net (Free plan, MagicDNS résout atlas, apollon, artemis, echo).
  • Domaine public : exalti.cloud (wildcard *.exalti.cloud72.61.104.153 chez Hostinger).
  • Services HTTPS publics : vault.exalti.cloud (CouchDB), hermes.exalti.cloud (Hermes), forgejo.exalti.cloud, news.exalti.cloud (Miniflux).

Stack par machine

Atlas — Pure inférence LLM (post-Mission 1)

  • oMLX servi via eu.exalti.omlx.plist (launchd, KeepAlive auto-restart)
  • Modèles dans ~/models/, paged SSD cache ~/.omlx/cache/
  • Endpoint OpenAI-compatible : http://atlas:8000/v1
  • Modèle prod : gemma-4-26b-a4b-it-4bit (verdict Round 7)
  • Healthcheck cron */5 min : scripts/healthcheck-omlx.sh
  • Logs : ~/.omlx/logs/server.log + ~/Library/Logs/omlx.{out,err}.log (rotation via newsyslog.d)
  • Ollama complètement désinstallé (Mission 1 — +222 GB libérés)

Apollon — VPS infra full Docker

Stack docker-compose (vps/docker-compose.yml) :

Service Rôle
caddy Reverse proxy + TLS automatique
couchdb DB sync vault (utilisée par plugin Obsidian LiveSync + livesync-cli)
hermes Agent IA Nous Research, accède au vault via bind-mount /vault
livesync-cli Container daemon qui propage vault filesystem ↔ CouchDB (Mission 3c)
forgejo Forge Git self-hosted
miniflux RSS reader self-hosted

Vault source-of-truth : /home/nicolas/vault/ (66 .md, autocommit cron */30 min).

Secrets prod (vps/.env) : COUCHDB_PASSWORD. NE JAMAIS commit (ignoré par .gitignore).

Artemis — Workstation Nicolas

  • Obsidian + plugin Self-hosted LiveSync (sync via CouchDB)
  • Claude Code (sessions interactives + missions structurées)
  • Repo ~/projets/infra/iac (commits + push depuis ici uniquement, convention)

Echo — iPhone

  • Obsidian iOS + plugin Self-hosted LiveSync
  • Telegram, WhatsApp (futur intake pour Hermes — Mission 5)

Structure repo

iac/
├── CLAUDE.md                ← onboarding agent
├── README.md                ← ce fichier
├── .gitignore + .sops.yaml
├── atlas/
│   ├── omlx/                ← config oMLX prod (settings.json)
│   └── archived/ollama-pre-omlx/   ← Modelfiles historiques (Rounds 1-7)
├── vps/
│   ├── docker-compose.yml   ← stack Apollon (6 services)
│   ├── .env.example         ← template (jamais le vrai .env)
│   ├── bootstrap.sh + init-user.sh   ← setup from zero
│   ├── caddy/Caddyfile
│   ├── couchdb/local.ini
│   ├── hermes/{config.yaml, skills/}
│   └── systemd/archived/    ← legacy livesync-cli.service (avant Mission 3c)
├── nix/
│   ├── launchd/             ← plists macOS prod + archived/
│   └── newsyslog.d/         ← rotation logs
├── scripts/
│   ├── eval-model*.sh       ← benchmark LLM (réutilisable rounds futurs)
│   ├── healthcheck-omlx.sh
│   ├── setup-couchdb.sh
│   ├── vault-autocommit-apollon.sh
│   ├── recovery/            ← 4 scripts disaster recovery idempotents
│   └── archived/            ← legacy + prompts de bench archivés
├── secrets/                 ← chiffrés age+sops
└── docs/
    ├── runbook.md           ← procédures opérationnelles globales
    ├── runbook-omlx.md      ← oMLX prod
    ├── runbook-vault.md     ← vault sync (livesync-cli + autocommit)
    ├── runbook-vault-rag.md ← RAG vault Hermes
    ├── local-llm-hermes-agent.md
    ├── apollon-from-zero.md
    ├── macs-setup.md
    ├── couchdb-setup.md
    ├── templates-frontmatter.md
    ├── post-round7-consolidation-report-2026-05-18.md
    ├── roadmap-2026-05-17.md
    └── archived/            ← handovers exécutés, rapports, test-results

Workflows courants

Mettre à jour Apollon (Docker)

ssh nicolas@apollon
cd ~/iac && git pull
cd vps && docker compose pull && docker compose up -d

⚠️ Vérifier .env présent AVANT tout docker compose up qui touche couchdb (cf. piège incident Mission 3c).

Mettre à jour Atlas (oMLX)

ssh exalti@atlas
cd ~/projets/infra/iac && git pull
# Si binaire oMLX à mettre à jour :
brew upgrade jundot/omlx/omlx
launchctl unload ~/Library/LaunchAgents/eu.exalti.omlx.plist
launchctl load ~/Library/LaunchAgents/eu.exalti.omlx.plist

Disaster recovery

Voir scripts/recovery/ :

  • bootstrap-atlas.sh — remonter Atlas from zero (oMLX + plist + healthcheck + newsyslog)
  • bootstrap-apollon.sh — remonter Apollon from zero (Docker + Tailscale + stack compose + secrets)
  • restore-vault.sh — restaurer le vault depuis CouchDB (livesync-cli mirror) ou depuis Git
  • sanity-check-all.sh — vérifier l'état de tous les services prod (Atlas + Apollon)

Procédures détaillées : docs/runbook.md.

Rotation des secrets

sops secrets/infra.yaml.sops   # décrypte pour édition
# modifier, sauver — sops réencrypte
git add secrets/infra.yaml.sops && git commit -m "rotate: <quelle clé>" && git push

Roadmap

Vision Now/Next/Later : docs/roadmap-2026-05-17.md.

État courant (2026-05-18)

Milestone État
M0 Fondations sécurité TERMINÉ (2026-05-12)
M1 Vault Obsidian + LiveSync TERMINÉ (2026-05-14)
M2 Hermes + Ollama puis oMLX TERMINÉ (2026-05-17, Rounds 1-7)
Mission 1 Cleanup Ollama + oMLX prod-grade TERMINÉ (+222 GB libérés)
Mission 2 RAG vault Hermes — solution zéro-custom TERMINÉ
Mission 3 / 3b / 3c Vault source-of-truth Apollon + livesync-cli daemon Docker TERMINÉ
Stress test v1 + v2 + Quick Wins TERMINÉ — 3 bugs identifiés, 1 fixé (UTF-8 + TZ)
Fix UTF-8 + timezone Hermes TERMINÉ (LANG=C.UTF-8 + TZ=Europe/Paris)
Mission 4 RAG CRM vault opérationnel (SCHEMA + skills + cron) 🟡 PARTIEL — vault CRM en place, skills + 2 cron OK, MCP MS365 désactivé (context overflow 161K tokens)
Mission 4b MS365 via Graph API custom (script Python ~100 lignes, scopes restreints "draft only") À briefer — voir lettre du matin
Mission 5 Messaging Telegram/WhatsApp Backlog
Mission 6 Forgejo + GitOps post-receive hook Backlog — le "game changer" pour stopper le jardinage sync entre machines

Documents de référence

  • Architecture globale + conventions : CLAUDE.md (onboarding agent)
  • Apollon from zero : docs/apollon-from-zero.md
  • Macs setup (Atlas + Artemis) : docs/macs-setup.md
  • CouchDB setup + pièges : docs/couchdb-setup.md
  • Runbook général + DR : docs/runbook.md
  • Runbook oMLX : docs/runbook-omlx.md
  • Runbook vault sync : docs/runbook-vault.md
  • Runbook RAG CRM vault : docs/runbook-vault-rag.md
  • Templates vault : docs/templates-frontmatter.md
  • Brief technique Hermes Agent : docs/local-llm-hermes-agent.md
  • Roadmap courante : docs/roadmap-2026-05-17.md (Now/Next/Later/Maybe)
  • Archives : docs/archived/ (handovers exécutés, rapports, test-results, synthèses)