Skip to content

Applications — track apps + restart EAT

The Applications system does three things:

  1. Tracks what should be running on a host (per app: type, identifier, expected state)
  2. Compares the actual state from inventory every 60 s against the expected
  3. Gives you one button to sign a TOTP-gated restart EAT for a specific app
  1. Sidebar → Applications (under ACTION)
  2. Top-right + Track an app button
  3. Fill in:
    • Agent — which host should run this app
    • Typesystemd unit / docker container / docker compose service / raw process
    • Name — free label for lists (e.g. “MyApp web”)
    • Identifier — concrete identifier per type:
      • systemd: unit name (nginx.service)
      • docker: container name (mycontainer)
      • compose: <project>::<service> (flowd_dev::app)
      • process: absolute path to binary (/opt/myapp/start.sh)
  4. Documentation (optional but recommended for MSP handover):
    • Owner email — who to ping when the app breaks
    • Runbook URL — link to internal docs
    • Notes — free text (deploy pipeline, dependencies, slack channel)
  5. Under Discovered on host you see the live list of systemd units + docker containers the agent just reported. Click a row to auto-fill Type + Identifier + Name
  6. Click the black Track this app button at the bottom

From now on: liveness worker starts within 60 s, expected state = running (you can change this later on the app’s detail page).

PhaseWhat
1. observeWorker reads current state from the LATEST inventory snapshot of the agent
2. compareexpected_state vs observed (running/stopped/unknown)
3. mismatchOn difference: emit app.state_mismatch signal + bump consecutive_mismatch counter
4. alertAfter 3 consecutive mismatches: alert with warning severity
5. dashboardApp row shows red pixel + last_state_change timestamp

unknown (worker finds no row for this identifier in the latest snapshot) does not count as a mismatch — agent may be briefly down or it’s a new deployment. Only counts after four consecutive unknowns.

Every app row has a Restart button. Click → TOTP prompt → hub signs a Level 2 Ed25519 EAT and pushes via WebSocket to the agent. Agent runs monsys-action restart-app <id> as dedicated user (no permanent root) and the wrapper picks:

  • systemd: systemctl restart <unit>
  • docker: docker restart <container>
  • compose: docker compose -p <project> restart <service>
  • process: the configured restart_command (absolute path required)

Result (exit_code + stdout/stderr) gets pushed back and lands in audit_log + transparency_log as evidence — the same flow as every other EAT action on the platform.

Apps inherit the tags of their agent. An app on a host with tag production-db shows up in every filter/SLA engine that filters on that tag. Want to group apps per environment? Tag the host (not the app).

Terminal window
# List all apps for a tenant
curl https://app.monsys.ai/api/v1/apps \
-H "Authorization: Bearer $TOKEN"
# Register an app
curl -X POST https://app.monsys.ai/api/v1/apps \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "<agent_uuid>",
"name": "MyApp web",
"app_type": "docker",
"identifier": "eurooffice",
"owner_email": "jeroen@gotrust.be",
"runbook_url": "https://wiki.example.com/runbooks/myapp",
"notes": "Deploys via GitOps · slack #platform · depends on redis-prod"
}'
# Change expected_state
curl -X PATCH https://app.monsys.ai/api/v1/apps/<id> \
-H "Authorization: Bearer $TOKEN" \
-d '{"expected_state": "stopped"}'
# Restart (requires TOTP header)
curl -X POST https://app.monsys.ai/api/v1/apps/<id>/restart \
-H "Authorization: Bearer $TOKEN" \
-H "X-TOTP-Code: 123456" \
-d '{"reason": "Memory leak per ticket TKT-9001"}'
# Stop tracking
curl -X DELETE https://app.monsys.ai/api/v1/apps/<id> \
-H "Authorization: Bearer $TOKEN"
  • Agent hasn’t shipped extended inventory yet: new agents push it every 6 h (default inventory_interval_secs). Wait or trigger manually with monsys-agent --once on the host
  • Agent is offline: check /agents/<id>last_seen_at. Stale agents don’t report
  • Agent is on a binary older than v0.1.0+20260519: extended inventory has shipped since then. Trigger auto-update or upgrade manually
  • Bug fixed on 2026-05-20: discovery query was missing latest-snapshot scope AND tenant guard. Both now in the hub. Hard-refresh your browser after this fix
  • Inventory itself (all services + packages + ports) → see Inventory tab on the agent detail page
  • Application CVE scanning (npm/pip/composer/go deps) → see Application CVEs
  • App-level alerts (cpu/mem/restart-count) → see Alert builder