Skip to content

Monitoring audit 2026-07-31 — nálezy, backlog úklidu, návrh vlastního agenta

Stav: otevřené, práce pozastavena na Liborův pokyn („vrátíme se k tomu"). Kontext vzniku: vzešlo z dotazu na telegram hlášky „? Unknown error" a na to, jestli je https://sentinel.studio60.cz/status/ realita. Není to plánovaný audit, je to řetěz nálezů. Vše níž je změřené, ne odhadnuté — u každého bodu je uvedeno čím.

1. Proč to vzniklo: monitoring nikdo dlouhodobě nehlídá

Společný jmenovatel všech nálezů z 30.–31. 7.:

Nález Jak dlouho nepovšimnuto Kdo to našel
Cert bi.studio60.cz expirovaný 31. 5. 2026 ~2 měsíce sentinel 31. 7.
Cert docs.s60dev.cz vydaný na jiný hostname (be.s60dev.cz) neznámo sentinel 31. 7.
GlitchTip healthcheck volal neexistující wget → falešně unhealthy 3 měsíce (failing streak 301218) sentinel 30. 7.
SENTRY_DSN s pomlčkami → 3 služby neposílaly do GlitchTipu nic měsíce sentinel 30. 7.
13 Kuma monitorů, které nikdy nebyly UP od 31. 3. sentinel 31. 7.
5 pauznutých monitorů zobrazených na status page se 6 týdnů starými daty od 15. 6. sentinel 31. 7.

Nic z toho nebylo těžké najít. Chybí pravidelná revize — sentinel je reaktivní (přijde release → nasadím → ověřím), monitoring potřebuje někoho, kdo se na něj dívá i když se nic neděje.

2. Status page https://sentinel.studio60.cz/status/

Mechanismus je reálný a živý (ověřeno 31. 7.):

  • HTML je JS aplikace, data tahá z KUMA_API='/status/api' a METRICS_API='/metrics/api'
  • /status/api/status-page/studio6083 monitorů v 6 skupinách (Produkce, Produkce — Deep Health, Infrastruktura, Hub (staging), Hub — Deep Health, Auto-discovered)
  • /metrics/api/metrics/current → metriky hostů s age ≈ 39 s = živé
  • heartbeaty čerstvé v řádu sekund

Obsah je ale zaneřáděný: z 83 svítí 17 červeně a ani jedna z nich není skutečný výpadek.

⚠️ Důsledek: stránka dnes nedokáže říct, že se něco rozbilo — trvale červené položky splývají s případnou reálnou.

3. Rozpad těch 17 červených

3a. Aktivní, ale NIKDY nebyly UP (12) — chyba konfigurace, ne služby

ID Monitor Hláška Diagnóza
20 api.studio60.cz (prod-alfa) 404 hlídá kořen https://api.studio60.cz, ale routy jsou pod /api/api/health vrací 200 (ověřeno curl) — ✅ OPRAVENO 2026-08-01
25 api.s60hub.cz (hub-alfa) 404 totéž — ✅ OPRAVENO 2026-08-01
34 api.s60dev.cz (cerebro) 404 totéž — ✅ OPRAVENO 2026-08-01
23 pdf.studio60.cz (prod-alfa) 403 chráněné
26 pdf.s60hub.cz (hub-alfa) 403 chráněné
39 cerebro.studio60.cz (cerebro) 403 chráněné
44 fess.studio60.cz (cerebro) 403 chráněné
45 kb.studio60.cz (cerebro) 404 chráněné/neexistuje
60 zoe.studio60.cz (cerebro) 403 chráněné
93 domains.studio60.cz (forge) 404 vhost je záměrně neprůrazný (location / { return 404; }) — ✅ OPRAVENO 2026-08-01, forge přidal /health
41 bi.studio60.cz (cerebro) certificate has expired REÁLNÁ VADA — cert platil do 31. 5. 2026 (ověřeno openssl s_client)
42 docs.s60dev.cz (cerebro) Hostname/IP does not match certificate REÁLNÁ VADA — cert má CN = be.s60dev.cz, platnost do 22. 9. (ověřeno openssl)

| 58 | wash.studio60.cz (cerebro) | 403 | chráněné — doplněno 2026-08-01, v původní tabulce chybělo (88 380 beatů od 31. 3., nikdy UP) |

⚠️ Oprava původního závěru (2026-08-01). V první verzi tu stálo, že api.* je nejnebezpečnější kategorie, protože „skutečný výpadek produkčního API by zanikl v šumu". To bylo přehnané. Produkční i hub API byly celou dobu korektně hlídané jinými monitory, které byly zelené:

ID Monitor URL
12 BadWolf Deep https://api.studio60.cz/api/health
72 BadWolf https://api.studio60.cz/api/health
68 Hub: BadWolf https://api.s60hub.cz/api/health

Reálná díra byla jen u dev (api.s60dev.cz), který žádný /api/health monitor neměl. Monitory 20/25/34 byly primárně šum, ne slepé místo. Původní počet „13 nikdy UP" byl navíc podhodnocený — s wash (58) jich bylo 14.

3b. PAUZNUTÉ, ale pořád na status page (5) — stará data se tváří jako stav

ID Monitor Poslední heartbeat
28 be.s60hub.cz (hub-alfa) 2026-06-15
31 be.s60dev.cz (cerebro) 2026-06-15
36 hive.studio60.cz (cerebro) 2026-06-15
38 fess.s60dev.cz (cerebro) 2026-06-15
74 dl.s60dev.cz (cerebro) 2026-06-15 (getaddrinfo ENOTFOUND)

Nekontrolují se, ale stránka je zobrazuje červeně podle šest týdnů starého záznamu.

3c. Zdravá část

66 monitorů UP s čerstvými heartbeaty, 0 monitorů, které bývaly UP a spadly → 31. 7. neprobíhal žádný výpadek.

4. Kaylee — vyřešeno jen částečně

  • kaylee.studio60.cz (cerebro), monitor id 50, přidán 31. 3.
  • 87 637 heartbeatů, všechny 403, ani jeden UP za 4 měsíce
  • Libor: kaylee běžet nemá → monitor hlídá pozůstatek po mrtvé službě
  • Sentinel 31. 7. přidal 403 mezi přijímané kódy (["200-299","301","302","403"]) + restart Kumy → monitor poprvé UP
  • ⚠️ Tahle změna stála na chybném předpokladu, že služba má běžet. Když běžet nemá, je trvale zelený monitor horší než červený.
  • Rollback: UPDATE monitor SET accepted_statuscodes_json='["200-299","301","302"]', active=0 WHERE id=50;
  • Otevřené: kaylee není v katalogu služeb ani v routing tabulce — nikdo neví, co to bylo

5. Telegram boti — tři různí

⚠️ PŘEMĚŘENO 2026-08-01 — tabulka níž měla DVĚ chyby. Kuma neposílá přes „Wash"; notifikace id=1 se jmenuje Sentinel Telegram a používá @s60_sentinel_bot. A @wash_s60_bot se nenašel nikde — ten údaj byl nepodložený. Aktuální inventura níž.

Úplná inventura botů (2026-08-01, ověřeno getMe u každého tokenu)

Bot Kde token žije
@s60_sentinel_bot sentinel /root/secrets/telegram/.env + Kuma notifikace id=1
@cerebro_s60_bot cerebro (.env, s60-tools/telegram-pm.sh, běžící dev procesy) + n8n prod credential „Telegram Bot"
@cortex_s60_bot cortex /opt/s60-cs/.env + cerebro s60-cs/.env
@zoe_s60_bot cerebro (nexus, kontejner s60-nexus-zoe)
@Fess84bot cerebro (nexus, openclaw, fess agent)
@s60monitor_bot cerebro s60-infra/tools/attack-watch.sh
@s60_badwolf_bot sentinel secrets + hub/prod /opt/badwolf/.env (přidán 2026-08-01)

Prohledáno: soubory na sentinel / cerebro / hub / prod / cortex / pg-alfa, env běžících kontejnerů (hub, prod, cerebro), /proc/*/environ běžících procesů na cerebru, Kuma SQLite a rozšifrované n8n credentials (n8n export:credentials --decrypted).

@kaylee_s60_bot NENÍ ani na jednom z nich. Zbývající místa mimo dosah sentinelu: forge (SSH host key nepřijat — řeší Libor sám), merlin (port 22 timeout), Liborův Mac Mini, externí SaaS.

Postup pro dohledání kdekoli jinde:

grep -rhoE '[0-9]{8,10}:[A-Za-z0-9_-]{35}' /root /opt /etc 2>/dev/null | sort -u
# každý nález pak:  curl -s "https://api.telegram.org/bot<TOKEN>/getMe"

Původní (chybná) tabulka z 31. 7. | Bot | `getMe` | Kde je token | Co posílá | |---|---|---|---| | Cerebro | `@cerebro_s60_bot` | `/root/secrets/telegram/.env` | relay agent ↔ Libor | | Wash | `@wash_s60_bot` | **uvnitř Kuma DB**, notifikace id=1 `My Telegram Alert` | Kuma alerty | | „kaylee" | ? | **na sentinelu NENÍ** (prohledány secrets, skripty, compose) | ? |

Chat ID je u Kumy i relay stejné (8532871856 = Libor).

Rozdělení potvrzené Liborem 2026-07-31:

  • Wash = Kuma monitoring alerty ✅ (sedí s konfigurací notifikace id=1)
  • kaylee = dostává dál ty „? Unknown error" hlášky — NENÍ to Kuma

⚠️ Historie oprav (ať se to nemotá): sentinel nejdřív správně určil „nechodí to z Kumy". Pak to podle Liborova průběžného pozorování („po tvých změnách chodí smysluplnější zprávy") mylně odvolal. Libor to 31. 7. upřesnil: ty smysluplné zprávy chodí přes Wash, kaylee dál dostává ten samý šum. Platí tedy původní závěr: zdroj „? Unknown error" NENÍ Kuma a NENÍ na sentinelu.

Jak to dohledat (nejlevnější první):

  1. Libor v Telegramu klikne na jméno bota → zobrazí se @username ⇒ jednoznačná identifikace, kterého bota to je
  2. s tím @username pak kaizen/infra grepnou cerebro na odpovídající token ([0-9]{8,10}:[A-Za-z0-9_-]{35}) a najdou proces, který ho volá
  3. hypotéza k ověření: druhá instance Uptime Kumy nebo jiný monitoring na cerebru — „? Unknown error" je formátem podobné notifikaci, jen s nevyplněnou zprávou

6. Proč se po restartu spustila záplava notifikací

resendInterval = 0 → Kuma posílá jen při změně stavu (important=1). Restart 31. 7. resetoval stav v paměti, takže všech 13 trvale rozbitých monitorů vygenerovalo přechod → 10 notifikací v 04:46–04:47. Není to výpadek, je to dávka dlouho neviditelných pravd.

7. Backlog úklidu (nic z toho zatím neuděláno)

# Úkol Kdo Pozn.
1 ~~Opravit URL u api.studio60.cz, api.s60hub.cz, api.s60dev.cz/api/health~~ sentinel HOTOVO 2026-08-01 (+ domains.studio60.cz/health), viz §9
2 Rozhodnout o 8 „403/404 chráněných" monitorech: akceptovat kód, nebo smazat Libor rozhodne u kaylee Libor už řekl, že běžet nemá
3 Vrátit kaylee změnu + monitor deaktivovat sentinel rollback SQL viz §4
4 Odstranit 5 pauznutých monitorů ze status page sentinel jinak zobrazují stav z 15. 6.
5 Nahlásit 2 certifikáty na cerebru (bi.studio60.cz expirovaný, docs.s60dev.cz špatný CN) infra / kaizen sentinel nemá SSH na cerebro
6 Zvážit sjednocení Telegram botů (Kuma jede přes Wash, relay přes Cerebro) Libor dnes nevadí, ale mate
7 Dohledat, co posílá „kaylee" hlášky kaizen / infra token není na sentinelu → běží to jinde
8 Zavést hlídání expirace certifikátů napříč doménami sentinel / nový agent dnes to nedělá nikdo — proto §1

8. Návrh: samostatný agent na sentinelu — backup & monitoring

Liborův nápad (31. 7.), rozšířený týž den: agent na sentinelu, jehož zodpovědností je backup A monitoring, a který to pravidelně hlídá.

Doména — monitoring: Kuma (monitory, status page), GlitchTip (projekty, DSN, retence), sledování expirace certifikátů, pravidelná revize „co je trvale červené a proč", routing nálezů na správného agenta.

Doména — backup: pokrytí zálohovací rotace (které DB/volumes v ní nejsou), kontrola že zálohy reálně vznikají a nejsou prázdné, retence, sync na storagebox, periodické ověření obnovitelnosti (dump, který nikdo nikdy nezkusil restorovat, není záloha).

Proč to patří k sobě: obojí je „nikdo se na to nedívá, dokud to nebolí". Backup díra z 31. 7. je učebnicová — s60_kb (375 MB, jediný domov KB) nebyla v rotaci a odhalilo se to jen proto, že se agent kb sám náhodou zeptal. Kontrola po tom nálezu ukázala dalších 9 databází mimo zálohy: s60_auth_staging, s60_keycloak_test, bazarai, kiwi, s60_n8n_staging, s60_badwolf_staging, hive_scrapper, s60_cs_kb, fess_context. Systémová příčina: seznam DATABASES v /usr/local/bin/s60-backup.sh je statický, takže nová databáze se do záloh nikdy nedostane sama — přesně jako monitor, který nikdo nezkontroluje, jestli byl někdy zelený.

Co mu NEDÁVAT: deploy práva a SSH zápis na hub/prod. Jinak vzniknou dva agenti sahající na produkci a padá pravidlo [[feedback_only_sentinel_deploys]]. Model: on diagnostikuje, sentinel/infra zasahuje.

Podmínka pořadí (sentinelův názor): nejdřív úklid §7, teprve pak předání. Agent, který zdědí 17 trvale červených položek, se naučí ignorovat červenou stejně jako my.

Stav: nezaloženo, čeká na Liborovo rozhodnutí.

9. Provedená oprava 2026-08-01 (backlog #1)

Schváleno Liborem („oprav 93 i api trojici najednou"). Spouštěčem byl forge, který zjistil, že domains.studio60.cz má vhost záměrně neprůrazný (location / { return 404; }) a přidal /health, takže monitor stačilo přesměrovat.

ID Bylo Je Výsledek
20 https://api.studio60.cz https://api.studio60.cz/api/health 200 - OK
25 https://api.s60hub.cz https://api.s60hub.cz/api/health 200 - OK
34 https://api.s60dev.cz https://api.s60dev.cz/api/health 200 - OK
93 https://domains.studio60.cz https://domains.studio60.cz/health 200 - OK

Monitor 93 byl poprvé UP za celou svou existenci — 23 332 heartbeatů od založení, do 1. 8. ani jeden úspěšný.

Postup: docker stop s60-uptime-kumaUPDATE v transakci přes jednorázový kontejner (docker run --rm -i -v /opt/uptime-kuma/data:/data --entrypoint sqlite3 louislam/uptime-kuma:1) → docker start. Plná kopie DB se nedělala (1,5 GB souboru kvůli 4 stringům při 78 % zaplnění disku); místo toho přesný rollback skript: ../runbooks/rollback-kuma-monitors-20260801.sql.

Stav po opravě: 79 aktivních monitorů → 70 UP, 9 nikoli (23, 26, 39, 41, 42, 44, 45, 58, 60).

⚠️ Past při měření: Kuma používá status 0=DOWN, 1=UP, 2=PENDING, 3=MAINTENANCE. Po restartu jdou rozbité monitory nejdřív do PENDING (dobíhají maxretries), takže dotaz WHERE status=0 hlásí falešnou nulu. Vždy počítat status <> 1.

Ověřovací příkazy (pro návrat k tématu)

# POZOR: sqlite3 v kontejneru JE (/usr/bin/sqlite3) — dřívější poznámka „chybí" byla mylná:
#   docker exec s60-uptime-kuma sqlite3 /app/data/kuma.db "..."
# Alternativa read-only z hostu (host sqlite3 nainstalovaný nemá):
python3 -c "
import sqlite3
c=sqlite3.connect('file:/opt/uptime-kuma/data/kuma.db?mode=ro',uri=True)
for mid,nm in c.execute('SELECT id,name FROM monitor WHERE active=1'):
    up=c.execute('SELECT 1 FROM heartbeat WHERE monitor_id=? AND status=1 LIMIT 1',(mid,)).fetchone()
    if not up: print('NIKDY UP:', mid, nm)"

# živá data status page
curl -s https://sentinel.studio60.cz/status/api/status-page/studio60
curl -s https://sentinel.studio60.cz/metrics/api/metrics/current

# expirace certu
echo | openssl s_client -servername bi.studio60.cz -connect bi.studio60.cz:443 2>/dev/null | openssl x509 -noout -dates

Související

✅ VYŘEŠENO 2026-08-12 — 7 pauznutých monitorů sundáno ze status page

Liborův pokyn („monitoring vsech sedmi muzes vypnout"). Monitoring byl přitom vypnutý už od 2026-06-15 — všech sedm mělo active=0. Jediné, co zbývalo, bylo, že pořád visely na status page, tedy se tvářily jako sledované, aniž by se cokoli měřilo.

monitor poslední měření stav tehdy stav 2026-08-12
19 be.studio60.cz (prod-alfa) 2026-06-15
28 be.s60hub.cz (hub-alfa) 2026-06-15
31 be.s60dev.cz (cerebro) 2026-06-15
33 be.studio60.cz (cerebro) 2026-06-15
36 hive.studio60.cz (cerebro) 2026-06-15 502 pořád 502 (DNS → cerebro 178.63.52.57; vhost stojí, backend pryč — Hive Scrapper běží na Liborově Mac Mini)
38 fess.s60dev.cz (cerebro) 2026-06-15
74 dl.s60dev.cz (cerebro) 2026-06-15 ENOTFOUND DNS záznam neexistuje

Shodné datum u všech sedmi ⇒ nešlo o sedm rozhodnutí, ale o jedno hromadné vypnutí (nejspíš aby přestaly řvát). Čtyři z nich jsou be.*, tedy starý backend na merlinu.

Co se provedlo: DELETE FROM monitor_group WHERE monitor_id IN (… active=0) — odebrána jen vazba na status page. Definice monitorů ani historie se nemazaly.

Ověřeno: skupina „Auto-discovered" 53 → 46; 7 monitorů dál existuje s active=0; 379 579 heartbeatů zachováno; aktivní monitoring běží dál (79 monitorů, 180 měření za 3 min po restartu). Kontrola provedena i na veřejném API status page (/api/status-page/studio60), ne jen v DB — žádný ze šesti hostnames se v odpovědi nevyskytuje.

Rollback: runbooks/rollback-kuma-statuspage-20260812.sql (7 INSERTů + restart kontejneru).

⚠️ Změna přes SQLite vyžaduje restart s60-uptime-kuma — Kuma drží stav v paměti.