Level.io
Level.io is Opentra’s RMM connector. Devices and alerts flow in, and alerts can become tickets so monitoring lives in the same queue as everything else.
What it does
Section titled “What it does”- Device sync. Level devices land against the right client organisation.
- Alerts → tickets. Alerts can raise tickets automatically, routed to the matching org.
- Runs on a daily sync, plus the device and alert feeds.
Device-to-client mapping
Section titled “Device-to-client mapping”Resolution order when the sync runs:
- An explicit group → organisation mapping you’ve set.
- An exact group-name equals org-name match.
- Otherwise, the existing assignment is preserved — Opentra never guesses or clobbers.
- In Settings → Integrations, connect Level.io.
- Map each device group to an organisation.
- Devices and alerts sync in; alerts route to the mapped org.
Proxmox VE facts
Section titled “Proxmox VE facts”The Level agent only reports the Debian base OS on Proxmox hosts — never the PVE version, subscription status, or pending-update count. And because those hosts sit behind client-site firewalls, Opentra can’t reach the Proxmox API directly. Instead, a Level automation runs a small script on each host (over the agent’s existing outbound channel) and pushes the facts to Opentra, where they appear on the device page.
What’s captured
Section titled “What’s captured”- PVE version (e.g.
8.4.19) — shown on the device header and in a dedicated Proxmox VE card. Versions on the 8.x line show a reminder that VE 8 support ends 2026-08-31. - Subscription status —
Activebadge, or the raw status (e.g.notfound) for unsubscribed hosts. - Pending updates — a count, flagged amber when non-zero.
- Reported — how long ago the host last checked in.
How to wire it up
Section titled “How to wire it up”-
Set a dedicated secret on the Level.io integration config (
proxmoxFactsSecret). This is separate from the alert webhook secret on purpose — it lives on client hosts, so it must never be able to forge sessions or alter alert handling. Because that’s its entire blast radius (an attacker who reads it can only push cosmetic version numbers), it’s fine to inline it in the script rather than fight Level’s variable substitution. -
Create a Level Automation (scheduled daily, plus run-on-demand) targeting your Proxmox device group. The script self-skips non-PVE hosts, identifies itself by its own hostname, then signs and POSTs the facts. It uses no Level template variables — deliberately, since hand-typed
{{...}}tokens are not substituted (only variables inserted via Level’s{x}picker are), which is a common source of401s:#!/usr/bin/env bashcommand -v pveversion >/dev/null 2>&1 || exit 0 # skip non-Proxmox hostsOPENTRA_URL="https://opentra.example.com" # your Opentra host — no angle brackets!SECRET="paste-your-proxmoxFactsSecret-here" # must equal Opentra's proxmoxFactsSecretHOST=$(hostname -s) # matches the synced deviceVER=$(pveversion | sed -n 's/^pve-manager\/\([^ /]*\).*/\1/p') # e.g. 8.4.19SUB=$(pvesubscription get 2>/dev/null | sed -n 's/^status: *//p') # active / notfoundUPD=$(apt-get -s upgrade 2>/dev/null | grep -c '^Inst ') # pending updatesTS=$(date +%s)BODY=$(printf '{"hostname":"%s","proxmoxVersion":"%s","subscription":"%s","pendingUpdates":%s,"ts":%s}' \"$HOST" "$VER" "$SUB" "$UPD" "$TS")SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -r | cut -d' ' -f1)curl -fsS -X POST "$OPENTRA_URL/api/integrations/proxmox/facts" \-H "Content-Type: application/json" -H "X-Opentra-Signature: sha256=$SIG" \--data "$BODY"hostname -smust match the device’s hostname as synced from Level (it does for the standard<client>-pvenaming). If you’d rather key on the Level device ID instead, POSTdeviceId(the device’s Level external ID) in place ofhostname— the endpoint accepts either.
Where you see it, and how the team is notified
Section titled “Where you see it, and how the team is notified”Each host’s facts show on its device page — a PVE <version> chip in the header and a Proxmox VE card (version, subscription, pending updates, “reported” age, and a VE 8 end-of-life reminder).
A daily health monitor (08:00) turns those facts into proactive signal. It evaluates every reporting host and, for anything at risk, notifies the team through every channel at once:
| Condition | Severity | What happens |
|---|---|---|
| End-of-life — Proxmox VE < 9 (VE 8 support ends 2026-08-31) | HIGH | Fleet alert + auto-created ticket + admin notification + digest |
| Not reporting — no facts for > 3 days | HIGH | Fleet alert + auto-created ticket + admin notification + digest |
| Updates pending — > 100 packages | MEDIUM | Fleet alert + admin notification + digest (no ticket) |
- Customer fleet — each issue is recorded as an Alert against the client org and device, visible in the Alerts module and on the org/device pages. Alerts auto-resolve when the condition clears (upgraded to VE 9, host reporting again, updates applied).
- Tickets — the HIGH, actionable conditions raise a ticket into the queue so the work is tracked. Pending-updates stays an alert only (it would otherwise churn a ticket daily).
- In-app — admins get a notification per newly-raised issue, linked to the device.
- Email digest — active admins/managers get an at-risk summary weekly (Mondays), plus immediately on any day a new issue appears.
Master switch: Settings → alerts.proxmoxHealthEnabled (on by default).