Applications — track apps + restart EAT
The Applications system does three things:
- Tracks what should be running on a host (per app: type, identifier, expected state)
- Compares the actual state from inventory every 60 s against the expected
- Gives you one button to sign a TOTP-gated restart EAT for a specific app
In the dashboard — registering an app
- Sidebar → Applications (under ACTION)
- Top-right
+ Track an appbutton - Fill in:
- Agent — which host should run this app
- Type —
systemd 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)
- systemd: unit name (
- 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)
- Under
Discovered on hostyou see the live list of systemd units + docker containers the agent just reported. Click a row to auto-fill Type + Identifier + Name - Click the black
Track this appbutton 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).
What happens next (per app, every 60 s)
| Phase | What |
|---|---|
| 1. observe | Worker reads current state from the LATEST inventory snapshot of the agent |
| 2. compare | expected_state vs observed (running/stopped/unknown) |
| 3. mismatch | On difference: emit app.state_mismatch signal + bump consecutive_mismatch counter |
| 4. alert | After 3 consecutive mismatches: alert with warning severity |
| 5. dashboard | App 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.
Restart via EAT (Emergency Action Token)
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.
Tags + grouping
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).
Or via API (advanced — for automation)
# List all apps for a tenantcurl https://app.monsys.ai/api/v1/apps \ -H "Authorization: Bearer $TOKEN"
# Register an appcurl -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_statecurl -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 trackingcurl -X DELETE https://app.monsys.ai/api/v1/apps/<id> \ -H "Authorization: Bearer $TOKEN"Discovered list is empty — what now
- Agent hasn’t shipped extended inventory yet: new agents push it
every 6 h (default
inventory_interval_secs). Wait or trigger manually withmonsys-agent --onceon 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
What does NOT belong on this page
- 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