Ga naar inhoud

Sysadmin — dag-dagelijks

1. Maandagochtend — wat is er over het weekend veranderd

In het dashboard

  1. Sidebar → Audit-log
  2. Filter: laatste 72u + groepeer op event_type
  3. Klik elke drift_event rij voor operator + reden
  4. Voor onverklaarde drift: agent → Inventaris → Restore

Klikpad:

  1. /audit-log → filter created_at >= now() - INTERVAL '72 hours' → sort op event_type
  2. /agents → “Drift events” panel — alle config-hashes die buiten een EAT-window veranderden
  3. Per verdachte agent: /agents/<id> → Kernel tab → Reboot history — wie heeft gereboot, EAT-driven of manueel

Equivalent in één SQL-query:

Of via API (geavanceerd — voor automatisering)

SELECT a.hostname, l.event_type, l.event_data->>'reason' AS reason,
u.email AS actor, l.created_at
FROM audit_log l
LEFT JOIN agents a ON a.id = l.agent_id
LEFT JOIN users u ON u.id = l.user_id
WHERE l.tenant_id = $1::UUID
AND l.created_at >= NOW() - INTERVAL '72 hours'
ORDER BY l.created_at DESC;

Wat je hierna typisch doet: voor elke drift_event zonder bijhorende emergency_token_issued-rij → checken of het een legitieme wijziging was. Zo niet → /agents/<id> → Inventory tab → Config hashes → Restore of het hostje quarantainen via IsolateNetwork EAT.


2. Fleet-wide kernel-update zonder downtime

In het dashboard

  1. Sidebar → Kernel CVE’s → tab Actieve batches
  2. Knop ‘Nieuwe batch’ → kies tag-selector + target kernel + reboot-strategie
  3. TOTP invullen → Start canary
  4. Volg canary → primary → completed in dezelfde view

Stel: USN-2026-1234 raakt 80 Ubuntu-hosts in productie. Target kernel is 6.8.0-49.49.

Of via API (geavanceerd — voor automatisering)

Terminal window
curl -X POST https://app.monsys.ai/api/v1/kernel-updates/batches \
-H "Authorization: Bearer $TOKEN" \
-H "X-TOTP-Code: 123456" \
-H "Content-Type: application/json" \
-d '{
"title": "USN-2026-1234 — kernel 6.8.0-49.49",
"target_kernel": "6.8.0-49.49",
"package_manager": "apt",
"reboot_strategy": "auto-at-window",
"selector_kind": "tag",
"selector_value": {"tag":"production"},
"maintenance_window_id": "8c34…"
}'

Wat er gebeurt achter de schermen:

  • Hub kiest 3 canary-hosts (10% van 80 = 8, capped op 3)
  • Voor elke canary: Ed25519-EAT signed, gepushed via WebSocket
  • Agent shell out naar /usr/local/sbin/monsys-kernel-update (alleen via sudoers-rule die deze ene wrapper toestaat)
  • Wrapper installeert kernel + headers, draait update-grub, zet /var/run/reboot-required, en — als binnen het maintenance-window — shutdown -r +5
  • Hub detecteert running_release flip bij volgende ingest → markeert fase rebooted_new
  • Pas wanneer alle 3 canary op rebooted_new staan → primary fires (77 EATs in één tick)
  • Eén canary die phase='failed' rapporteert → batch aborted, geen primary EATs verstuurd
  • Canary die binnen 2u niet beweegt → automatisch aborted (“canary timeout”)

Status volgen: /kernel-cves → Actieve batches tab. Of:

Terminal window
curl https://app.monsys.ai/api/v1/kernel-updates/batches/<id> \
-H "Authorization: Bearer $TOKEN" | jq .members

3. Eén applicatie is traag — waar kijk je

In het dashboard

  1. Sidebar → Apps → klik op host web-03 → tab Metrics
  2. Tab Processes voor top CPU/RAM verbruikers
  3. Tab Topology voor blast-radius afhankelijkheden
  4. Tab Logs voor recente WARN/ERROR van de agent

Klikpad voor host web-03:

  1. /agents/web-03 → Metrics tab — CPU/mem/load over laatste 6u
  2. /agents/web-03 → Processes tab — top 10 CPU/RAM-verbruikers
  3. /agents/web-03 → Topology tab — welke andere agents/apps hangen eraan vast (afhankelijkheidsgraaf)
  4. /agents/web-03 → Containers tabrestart_count per container
  5. /agents/web-03 → Logs tab — laatste 200 WARN/ERROR-regels van de agent zelf (geen volledige syslog — die staan in Loki)
  6. /alerts filter agent=web-03 AND is_resolved=false

Veelvoorkomende root causes:

SymptoomEerst checken
CPU 100% gedurende urenProcesses tab — welke PID? Daarna /agents/web-03 → Logs
Memory langzaam volCapacity tab — RAM trend + swap-gebruik
App reageert nietContainers tab — restart_count + Inventory → systemd_services voor service state
DB-foutenTopology tab — is de DB-agent stale? last_seen_at check

4. Auto-reboot enkel in het weekend

In het dashboard

  1. Sidebar → Settings → Maintenance windows → ‘Nieuw venster’
  2. Configureer recurrence: zaterdag 02:00-06:00 met tag-target ‘production’
  3. Bij kernel-batch creation: reboot_strategy = auto-at-window
  4. Wrapper runt shutdown -r +5 alleen binnen actief venster

Definieer eerst een maintenance window:

Of via API (geavanceerd — voor automatisering)

Terminal window
curl -X POST https://app.monsys.ai/api/v1/maintenance-windows \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Weekend reboot window",
"starts_at": "2026-05-23T02:00:00Z",
"ends_at": "2026-05-23T06:00:00Z",
"recurrence": "weekly",
"target_type": "tag",
"target_filter": {"tag":"production"},
"silence_categories": []
}'

Bij kernel-update batch creation: zet reboot_strategy=auto-at-window. De wrapper monsys-kernel-update doet shutdown -r +5 alleen wanneer de host binnen een actief window valt; daarbuiten blijft het bij “reboot required” en valt het op de operator om te bevestigen.


5. Config drift na een migratie

In het dashboard

  1. Sidebar → Agents → klik host → tab Inventory → sectie Config hashes
  2. Tabel toont sha256 huidig vs baseline per gewatcht pad
  3. Per drift event: ‘Accept as baseline’ OF ‘Investigate’
  4. Drift zonder linked_eat_id = onverklaard, vereist actie

Per agent zie je sha256 van alle gewatchte paden (default: /etc/passwd, /etc/shadow, /etc/sudoers, /etc/ssh/sshd_config,

  • 4 andere).

Of via API (geavanceerd — voor automatisering)

Terminal window
curl https://app.monsys.ai/api/v1/agents/<id>/drift-events?limit=50 \
-H "Authorization: Bearer $TOKEN"

Voor elke drift-event toon je:

  • path — welk bestand
  • prev_sha256 / new_sha256
  • detected_at
  • linked_eat_idnull betekent: niemand heeft hier een EAT voor geautoriseerd, dit is onverklaarde drift

Workflow:

  1. Als het een legitieme wijziging was (manueel patchen, migratie): POST /api/v1/agents/<id>/drift-events/<id>/accept — baseline bumpt
  2. Als het verdacht is: POST /api/v1/agents/<id>/emergency met action IsolateNetwork + TOTP, dan handmatig inspecteren

6. Vind alle Ubuntu 20.04 servers (end-of-standard-support 2025-04)

In het dashboard

  1. Sidebar → Agents → filter os_name=Ubuntu + os_version~20.04
  2. Bulk-select de getoonde hosts
  3. Knop ‘Add tag’ → tag = ‘eol-2025’
  4. Sidebar → Settings → Alert rules → nieuw met threshold-datum 2025-04-30

Of via API (geavanceerd — voor automatisering)

Terminal window
curl 'https://app.monsys.ai/api/v1/agents?os_name=Ubuntu&os_version_like=20.04' \
-H "Authorization: Bearer $TOKEN" | jq '.[] | .hostname'

Of in SQL:

SELECT hostname, ip_addresses, last_seen_at
FROM agents
WHERE tenant_id = $1::UUID
AND os_name = 'Ubuntu'
AND os_version LIKE '20.04%'
AND is_active = true
ORDER BY last_seen_at DESC;

Daarna typisch: tag deze hosts met eol-2025 via bulk-tagging in /groups, en bouw een SLA-alert die fires zodra er na 2025-04-30 nog agents in die tag zitten.


7. “Waarom kreeg ik 438 CPU-alerts vannacht?”

In het dashboard

  1. Sidebar → Alerts → tab ‘Grouped by title’
  2. Sorteer descending op count
  3. Klik op grootste groep — bevat de title een waarde?
  4. Settings → Alert rules → bewerk de regel zodat waarde in description komt

Sinds de alert-storm fix (sessie 17) doet InsertAlert 30-minuten dedup per (tenant, agent, category, title). Krijg je toch storm: meest waarschijnlijk een veranderende title (bv. count in titel) die de dedup-key elke keer anders maakt.

Quick check:

Of via API (geavanceerd — voor automatisering)

SELECT title, COUNT(*), MIN(created_at), MAX(created_at)
FROM alerts
WHERE tenant_id = $1::UUID
AND created_at >= NOW() - INTERVAL '24 hours'
GROUP BY title
ORDER BY 2 DESC LIMIT 10;

Als één title 100+ keer voorkomt → bug. Als 100 unieke titles 1× elk → de title bevat een waarde (count, percentage, timestamp). Fix de emittende worker om de waarde naar description te verhuizen.


8. Werknemer vertrokken — wat had die persoon allemaal

In het dashboard

  1. Sidebar → Identity surface → zoek alice@
  2. Bekijk gekoppelde systemen (hosts, SSH keys, Copilot/OpenAI seats)
  3. Per systeem ‘Revoke’ knop OF één playbook EAT ‘revoke-user’ over alle hosts
  4. Audit-log toont ‘identity_revoked’ per uitgevoerde revocatie

/identity/surface → search "alice@…" toont:

  • Dashboard-account (rollen per tenant)
  • Lokale users op welke hosts (inventory_users.username='alice')
  • SSH-keys waar publickey-fingerprint matched
  • GitHub Copilot seat (als Copilot Audit module aan staat)
  • OpenAI org-member (als OpenAI Audit module aan staat)
  • Sudo-rechten (inventory_sudo_rules.who='alice')

Bulk-revoke vanuit de Identity-surface page: ofwel per systeem (POST /api/v1/identity/persons/<id>/revoke), ofwel als één RunPlaybook EAT die alle hosts in één keer afhandelt.


9. On-call rotation timezone-aware

In het dashboard

  1. Sidebar → Settings → On-call rotations → ‘Nieuwe rotation’
  2. Voor team eu-ops: shifts ma-vr 09:00-18:00 Europe/Brussels
  3. Voeg buddy fallback toe voor buiten kantoor
  4. NotifyWorker resolveert per alert welke shift open is en routeert naar ntfy

Of via API (geavanceerd — voor automatisering)

-- Voor team eu-ops, 09:00-18:00 Brussel-tijd, ma-vr, met fallback naar buddy
INSERT INTO oncall_shifts (tenant_id, group_id, person_id, weekday,
start_time, end_time, timezone)
VALUES
($1, $2, $alice, 1, '09:00', '18:00', 'Europe/Brussels'),
($1, $2, $alice, 2, '09:00', '18:00', 'Europe/Brussels'),
-- … en
($1, $2, $bob, 1, '18:00', '09:00', 'Europe/Brussels'); -- buddy

NotifyWorker resolveert per alert welke shift open is op alerts.created_at, en routeert naar de juiste ntfy-topic + e-mail.


10. Backups van productie-DBs — werken ze echt nog

In het dashboard

  1. Sidebar → Inventaris → tab Backups → filter tag ‘production-db’
  2. Sorteer ‘Last successful’ ascending
  3. Per stale host (>25u): klik ‘Create alert rule’
  4. Threshold = 25u + severity = critical

Of via API (geavanceerd — voor automatisering)

SELECT a.hostname,
b.tool AS backup_tool,
b.destination AS target,
b.last_successful_run AS last_ok,
NOW() - b.last_successful_run AS age,
b.last_failure_message
FROM backup_configs b
JOIN agents a ON a.id = b.agent_id
WHERE b.tenant_id = $1::UUID
AND 'production-db' = ANY(a.tags)
ORDER BY b.last_successful_run NULLS FIRST;

Alert-regel als age > 25h (default schedule = dagelijks):

Terminal window
curl -X POST https://app.monsys.ai/api/v1/alert-rules \
-H "Authorization: Bearer $TOKEN" \
-d '{
"name": "Backup stale > 25h on production-db",
"tag": "production-db",
"category": "backup",
"metric": "backup_age_hours",
"operator": ">",
"threshold": 25,
"severity": "critical"
}'