---
tags: [vps, zeroclaw, matrix, tuwunel, cron]
type: note
description: "ZeroClaw + Matrix sur datagrandest : canal kamio_zc, 3 bugs corrigés (section malformée, liaison agent↔canal, auto-join cron), modèle de sessions."
nature: documentation
projects:
  - [[03_PROJETS/VPS-IA]]
---

# VPS-IA_ZeroClaw-Matrix-2026-11-08

**Date** : 2026-11-08 — **Agent** : vps-admin — **Serveur** : `datagrandest.net` (VPS principal, OVH / Yunohost)

Installation de ZeroClaw **0.8.7** sur le VPS principal et branchement du canal **Matrix** (`matrix.datagrandest.net`, serveur **tuwunel**). Validation finale : le bot `@zc:matrix.datagrandest.net` répond dans les salons, auto-join opérationnel, `doctor` = 29 ok / 1 warning / 0 erreur.

## Architecture

| Élément | Valeur |
|---|---|
| Binaire | `/home/zeroclaw/.cargo/bin/zeroclaw` (+ `zerocode`) — installé via cargo, **pas dans le PATH** |
| User | `zeroclaw` (uid 1002), HOME `/home/zeroclaw` |
| Service | unit **system** `/etc/systemd/system/zeroclaw.service` (`User=zeroclaw`, `ExecStart=…/zeroclaw daemon`) |
| Config | `/home/zeroclaw/.zeroclaw/config.toml` (schema v3) — dossier **700** : `opencode` ne peut ni lire ni exécuter le CLI |
| Gateway / dashboard | `127.0.0.1:42617`, socket RPC `data/daemon.sock` |
| Homeserver | `https://matrix.datagrandest.net` (tuwunel), compte `@zc:matrix.datagrandest.net` |
| Canal | alias `kamio_zc` → section `[channels.matrix.kamio_zc]` |
| Peer group | `[peer_groups.matrix]` : `channel="matrix.kamio_zc"`, `agents=["kamio_zc"]`, `external_peers=["@shizendo:matrix.datagrandest.net"]`, `output_modality="mirror"` |
| Agent | `agents.kamio_zc` → `model_provider=openrouter.openrouter`, `channels=["matrix.kamio_zc"]` |
| Bridge jumeau | `opencode-matrix.service` (`@bot`) = **autre** bot, distinct de `@zc` |

## Les 3 bugs diagnostiqués (dans l'ordre)

### 1. Section Matrix « malformed » → ignorée en silence

```
warning: config section `channels.matrix.<id>` … is malformed and was reset to
defaults for this run. Values in that section are NOT in effect.
```

- Le warning apparaît **à chaque démarrage** dans `journalctl -u zeroclaw` ; la section est remise aux defaults → canal inactif alors que `enabled=true` partout.
- L'id a changé pendant la session (`matrix` → `main` → `kamio_zc`) : le problème venait du **contenu**, pas du nom.
- Diagnostic : `sudo -u zeroclaw <bin> --config-dir … config migrate --json` → `{"valid": true, "migrated": false}` une fois corrigé. Sur shogun, la cause était `missing field homeserver` dans un bloc laissé vide.

### 2. Liaison agent ↔ canal cassée

```
agents.kamio_zc.channels = ["matrix.matrix"]   # canal inexistant
```

Conséquence : `doctor` → `⚠️ no channel components tracked yet`, aucun login, aucune réponse. Fix :

```bash
sudo -u zeroclaw env HOME=/home/zeroclaw XDG_RUNTIME_DIR=/run/user/1002 \
  /home/zeroclaw/.cargo/bin/zeroclaw --config-dir /home/zeroclaw/.zeroclaw \
  config set agents.kamio_zc.channels matrix.kamio_zc
```

**Le CLI doit tourner en tant que `zeroclaw`** : lancé en root, `config set` échoue en `-32010 Credential rejected` (coordination avec le daemon). Preuve de succès dans le trace : `channel binding(s) activated … bindings:["matrix.kamio_zc"]`, puis `matrix: starting sync loop`.

### 3. Auto-join absent + cron ignoré silencieusement

- ZC 0.8.7 **n'accepte aucune invitation** (pas d'`auto_join` dans `MatrixConfig`) → cron `*/2` installé (même schéma que shogun).
- **Piège rédhibitoire rencontré** : un fichier `/etc/cron.d/<x>` **sans newline final** est rejeté par cron :

```
(*system*zeroclaw-autojoin) ERROR (Missing newline before EOF, this crontab file will be ignored)
```

→ le fichier existe, `ls` est normal, le service cron tourne, **et rien ne s'exécute**. Vérification obligatoire : `grep zeroclaw-autojoin /var/log/syslog` (attendu : `RELOAD` sans `ERROR`).

## Modèle de sessions (vérifié sur `sessions.db`)

| Niveau | Clé / emplacement | Granularité |
|---|---|---|
| Session Matrix (device) | `.zeroclaw/state/matrix/<canal>/session.json` (**hors `data/`**) | 1 par canal → **1 seul `/sync`** pour tous les salons |
| Session de conversation | SQLite `.zeroclaw/data/sessions/sessions.db` → `session_metadata` | **salon × expéditeur** : `matrix_<canal>__<room>__<sender>` |
| Sessions hors salon | mêmes tables, `channel_id`/`room_id` NULL | `rpc_*` (API), `gw_*` (dashboard) |
| Trace / coûts | `.zeroclaw/data/state/runtime-trace.jsonl`, `costs.jsonl` | — |

Leaving un salon ne casse rien (la session device est commune) mais laisse une session orpheline en base : **pas de GC connu**.

## Synthèse — ZeroClaw vs bridge OpenCode

Deux bots Matrix cohabitent sur ce VPS, **distincts** : `@zc` (ZeroClaw, agent `kamio_zc`) et `@bot` (bridge `opencode-chat-bridge` v0.7.1, à jour au 08/11, agent `chat-bridge`).

| | ZeroClaw 0.8.7 (`@zc`) | Bridge OpenCode (`@bot`) |
|---|---|---|
| Granularité de session | **salon × expéditeur** | **par salon** |
| Clé de session | `matrix_<canal>__<room>__<sender>` | `roomId` (ou `roomId:threadRoot` si `threadIsolation:true`) |
| Persistance | SQLite `.zeroclaw/data/sessions/sessions.db` (`session_metadata` + tours dans `sessions`) | `.opencode/chat-sessions.json` → `sessionId` OpenCode + `cwd` par session |
| Session Matrix (device) | **1 par canal** (`.zeroclaw/state/matrix/<canal>/session.json`) → 1 seul `/sync` pour tous les salons | 1 compte bridge, store crypto dans `SESSION_BASE_DIR` |
| Sessions hors salon | `rpc_*` (API) et `gw_*` (dashboard), `channel_id`/`room_id` NULL | — |
| Déclencheur | `mention_only:false` → répond sans être taggé | `triggerPatterns:["!oc "]` (déclencheur explicite) |
| Auto-join | **absent** en 0.8.7 → cron `*/2` installé | `autoJoin:true` natif |
| E2EE | ✔ `recovery_key` (SSSS) + cross-signing | ✔ Rust crypto + SQLite, device `wJUe7SVWmt` |
| Nettoyage | session orpheline après `leave` (pas de GC connu) | idem (entrée du fichier de mapping) |

⚠️ **Piège de lecture (bridge)** : `chat-bridge.json` porte `encryption.enabled: false`, mais cette clé n'est **jamais lue** par `connectors/matrix.ts` (grep : aucune occurrence) — le connecteur construit systématiquement `RustSdkCryptoStorageProvider` et logge `E2EE: enabled (Rust crypto with SQLite)` au démarrage. Se fier au log + au store (`crypto/matrix-sdk-crypto.sqlite3`), pas à la clé de config.

Voir aussi : [[VPS-IA_ZeroClaw-Installation-2026-11-08]] (installation, unit systemd, config complète commentée) · [[VPS-IA_Installation-OpenCode-Chat-Bridge-Matrix]] (installation, usage et choix du bridge — synthèse renvoyée depuis cette note).

## Chemins & commandes de référence

```bash
# erreurs de config
journalctl -u zeroclaw --since -10min --no-pager | grep -i 'malformed\|error'
# état réel (pas le fichier)
sudo -u zeroclaw env HOME=/home/zeroclaw XDG_RUNTIME_DIR=/run/user/1002 \
  /home/zeroclaw/.cargo/bin/zeroclaw --config-dir /home/zeroclaw/.zeroclaw doctor
# token Matrix du bot, sans jamais l'afficher (header file, jamais en argv)
umask 077
sudo -u zeroclaw python3 -c "import json,glob;f=glob.glob('/home/zeroclaw/.zeroclaw/state/matrix/*/session.json')[0];print('Authorization: Bearer '+json.load(open(f))['access_token'])" > /tmp/zc.hdr
curl -s -H @/tmp/zc.hdr https://matrix.datagrandest.net/_matrix/client/v3/joined_rooms; rm -f /tmp/zc.hdr
```

## Fichiers en place

```
/usr/local/sbin/cron-2min-zeroclaw-autojoin.sh   (755, token lu à l'exécution)
/etc/cron.d/zeroclaw-autojoin                    (*/2, root, NOUVELLE LIGNE FINALE obligatoire)
/etc/logrotate.d/zeroclaw-autojoin               (daily, 7, copytruncate)
/var/log/zeroclaw-autojoin.log                   (1 ligne par join accepté seulement)
/var/lib/opencode/zeroclaw/                      (sources des 3 fichiers ci-dessus)
/home/zeroclaw/.zeroclaw/config.toml.bak-20261108 (+ .bak-1950)
```

## Reste à faire

- [ ] Clé OpenRouter dédiée du canal : la dupliquer dans le coffre `pass` (`opencode/zeroclaw-openrouter-key`).
- [ ] `memory.search_mode = "hybrid"` sans embedding provider → passer en `"bm25"` ou configurer un provider (warning doctor).
- [ ] Purger les sessions SQLite des salons de test quittés (pas de GC automatique).
- [ ] Activer TOTP / rotation des tokens si besoin ; backup megolm de `@zc` si les clés de salle doivent survivre.

## Voir aussi

[[VPS-SHOGUN_ZEROCLAW]] (install shogun, même version, mêmes pièges) · [[04_NOTES/VPS-IA_Garde-fous-OpenCode-ZeroClaw-20261102]] · skill [[80_CONFIG/IA_SKILLS/shogun-admin]]