Credential model
| Credential | Lifetime and tenant behavior | Use |
|---|---|---|
| Administrator session | Short-lived signed access cookie plus rotating opaque refresh token; tenant selected from memberships | Interactive UI and administrative API |
| Tenant API key | Revocable, optionally expiring, permanently pinned to one tenant | Automation and integrations |
| Push token | Monitor-specific capability URL | Passive push heartbeat only |
| Location credential | Private-location identity constrained by NATS authorization | Remote worker queue access |
Administrator access tokens default to a short lifetime (15 minutes in the standard configuration), while refresh tokens default to 30 days and rotate on use. A rotated refresh token stays valid for a 60-second reuse window so concurrent refreshes from parallel requests or multiple tabs do not end the session. Disabled users are checked against database state on authenticated requests.
Platform and tenant roles
| Role | Scope | Capabilities |
|---|---|---|
Platform superadmin | Installation | User administration, any tenant context, and all tenant operations |
Platform member | Installation | Only tenants granted through membership |
Tenant admin | One tenant | All tenant operations, including API keys, tenant settings, and audit access |
Tenant editor | One tenant | Normal monitoring mutations but not API-key, tenant-setting, or audit administration |
Tenant viewer | One tenant | Reads plus approved compute-only diagnostics |
Viewer and read-key compute-only POST routes include monitor test, import preview, dependency suggestions, mesh probe, and AI connection test. Persisted operations such as Run now, channel test, acknowledgement, or configuration updates require write authorization.
AI training labels are writes, not diagnostics: confirming or correcting an incident analysis or an alert triage and accepting or dismissing a dependency suggestion need an editor, admin, superadmin, or write API key, and viewers and read keys get HTTP 403. Only tenant admins and superadmins, signed in, can export labels; every API key is refused, write scope included. The same holds for SIP test-call monitors, which place real calls: creating, changing, pausing, running, testing or importing one needs a signed-in tenant admin or superadmin, and editors and API keys get HTTP 403.
Bootstrap and manage users
On an empty installation, the public bootstrap status and first-user endpoints allow exactly the initial account to be created. That first active account is a superadministrator. OIDC just-in-time login can also initialize the first superadministrator on an empty installation, and an operator with database access can create or recover one at any time with `go run ./cmd/admin`.
| User variable | Validation and behavior |
|---|---|
username | 3–64 characters; letters, numbers, ., _, and - |
email | Optional, used for OIDC linking and SSO-only users |
password | 12–128 characters when local login is enabled |
platform_role | superadmin or member |
memberships | Tenant IDs paired with admin, editor, or viewer; patch replacement is authoritative |
auth_method | Indicates local, OIDC/SSO-only, or linked authentication behavior |
A user with email and no password can be provisioned as SSO-only. Superadministrator-only user routes create, list, update, and delete accounts. Safeguards prevent deleting the current user or leaving the installation without an administrator.
Tenant context
An administrator session can select a tenant using X-Tenant-ID; a tenant_id query fallback is supported by the authentication context where applicable. The server verifies membership unless the user is a superadministrator.
API keys ignore arbitrary tenant selection and remain pinned to their creation tenant. The tenant-list endpoint is for administrator sessions and returns only allowed tenant context. Public tenant create/update/delete management is not exposed through the normal product API.
API keys
| Variable | Meaning |
|---|---|
name | Operator-facing key purpose |
scope | read or write; defaults to write when omitted in the current API |
expires_at | Optional future expiration time |
key | Full secret returned only in the creation response |
key_prefix | Non-secret SHA-256-derived identifier returned in list responses to correlate keys; not a fragment of the secret |
last_used_at | Usage timestamp, updated with write throttling |
created_by / created_at | Creation audit metadata |
revoked | Whether the key can no longer authenticate |
curl -H 'Authorization: Bearer pk_<secret>' \
https://monitoring.example.com/api/v1/monitors- Create the key as a tenant administrator and choose the minimum scope.
- Copy the full key from the one-time creation response into a secret manager.
- Use
key_prefixto identify the key record later; it is a derived identifier, not a recognizable fragment of the secret, and list responses never reveal the full key. - Set an expiration and rotate before it, rather than keeping indefinite integration credentials.
- Revoke the key when a client is retired or the secret may have leaked.
last_used_at is intentionally not updated on every request; writes are throttled to roughly five-minute granularity. Use it for coarse inventory, not per-request forensics.
OpenID Connect
Probara supports one platform identity provider using the authorization-code flow with PKCE. Signed state cookies and nonce validation protect the browser redirect. Provider discovery is loaded lazily as the login flow needs it.
- OIDC identities are bound by the stable
(issuer, subject)pair. - A verified email can link to an explicitly SSO-only account.
- An unverified email is not trusted for account linking.
- A subject already bound to another account is refused.
- When just-in-time provisioning is enabled, new users receive the configured default platform/tenant membership rather than arbitrary claims-based privilege — unless OIDC group mappings exist, in which case mapped roles replace the JIT defaults.
- On an empty installation, the first successful JIT login becomes the initial superadministrator.
OIDC group mappings
Superadmins can map identity-provider groups to roles under Settings → Access → OIDC group mappings (or via /api/v1/oidc-group-mappings). A mapping targets either one tenant with a role (admin, editor, viewer) or the platform (grants superadmin). Groups are read from the ID-token claim named by `OIDC_GROUPS_CLAIM`; request the groups scope via OIDC_SCOPES so the provider sends it.
- Zero mappings means the feature is off: JIT defaults apply and roles stay manually managed. Deleting all mappings restores that behavior immediately.
- With any mappings present, the identity provider is the source of truth for SSO users: platform role and tenant memberships are re-derived from the user's groups on every login, overwriting manual edits.
- A user in several groups mapping to the same tenant gets the highest role (
admin>editor>viewer). Group names match case-sensitively. - A user in no mapped groups syncs to a member with no tenant memberships — deliberately no fallback to the JIT default, which would silently re-grant revoked access.
- The sync never demotes the last active superadmin; the demotion is skipped and flagged in the audit log (
skipped_last_superadmin_demotion). - Password-based accounts are never touched by group sync.
- Applied changes are recorded as
auth.oidc_role_syncaudit events with the full membership diff, the matched groups, and every group the token presented (received_groups) — the place to look when a name doesn't match. - Groups presented in verified ID tokens at successful logins are catalogued and offered as suggestions in the mapping editor (with click-to-prefill chips for groups that have no mapping yet). OIDC has no API to enumerate an IdP's groups, so the catalog only knows groups someone has already logged in with.
- Mappings accept an optional display label (click a row's group cell to edit). Matching always uses the raw claim value — essential with Azure AD, whose groups claim carries object IDs (GUIDs), not names: label the GUID rows so the table stays readable.
Tenant settings
| Setting | Constraint and effect |
|---|---|
data_retention_days | 0 keeps mesh history indefinitely; otherwise 30–3,650 days. Raw check results are always capped at 30 days |
dashboard_group_tags | Up to 50 non-empty unique tags, each up to 64 characters, used to curate service-summary groups |
Retention applies to mesh history and raw agent metric samples. Raw check results are kept 30 days regardless of this setting, and uptime/latency history beyond that comes from rollups kept 400 days. Audit retention is configured separately at platform level. Dashboard group tags change presentation only; they do not create monitor groups or notification rollup.
Workspace local AI settings
| Field | Meaning |
|---|---|
enabled | Writable; enable dependency suggestions, asynchronous incident analysis and alert triage for the workspace |
installation_enabled | Installation-level availability switch; overrides workspace enablement |
available / model | Read-only local-service readiness and model identity. Each API process caches the result for about 30 seconds, failures included, so a just-fixed service can read as unavailable until the cache expires. |
message | One of four fixed readiness strings (disabled, not configured correctly, unreachable, not ready); details are only in the API logs |
auto_triage_enabled | Writable, default false; triage new alerts automatically. Takes effect only while enabled is also on. With it off, alerts are not triaged at all, so SLA report outages land in Not triaged |
triage_delay_seconds | Writable, default 60, 0–3600; how long an alert must stay open before it is triaged. The wait is never shorter than two check intervals of the alert's monitor (that part capped at one hour), so 0 still waits for them |
triage_cooldown_seconds | Writable, default 900, 0–86400; skip an alert's triage when its monitor already has a ready triage completed within this time. 0 turns the cooldown off |
triage_max_per_hour | Writable, default 60, 1–600; triages claimed per rolling hour in this workspace, skipped ones not counted |
triage_notifications_enabled | Writable, default false; send suspected causes once to each channel already paged for an alert (not PagerDuty or Opsgenie). Takes effect only while enabled and auto_triage_enabled are also on, and only for triages completed after it was turned on |
Settings → AI controls the workspace switch and tests the installation-owned CPU service. Absent workspace settings default enabled, with auto-triage off and the triage defaults above; existing enable and disable switches are preserved. Settings updates are partial: any of the six writable fields, at least one, and an omitted field keeps its stored value. Out-of-range numbers and legacy provider fields return a validation error. Editors, admins, superadmins and write API keys can change these settings; viewers see them read-only. The Automatic alert triage block (Triage new alerts automatically, Send suspected causes to alert channels, Wait before triage (s), Cooldown per monitor (s), Max triages per hour) is locked while local AI is disabled for the installation or the workspace switch is off, and Send suspected causes to alert channels also while auto-triage is off. The API still accepts auto_triage_enabled and triage_notifications_enabled with AI or triage off; no alert is triaged, and no follow-up sent, until every switch they depend on is on. The connection test accepts an empty object, cannot accept destinations or credentials, always probes afresh and refreshes the readiness cache of the API replica that serves it.
Tenant admins also see Training labels under Settings → AI. Export labels downloads every label in the workspace as JSONL training rows (POST /api/v1/ai-labels/export, which also accepts a since/until window and subject types). A row carries evidence counters, catalogue answers and provenance, with no monitor names or IDs (see AI training labels). Labelling and export never call the model, so they work while local AI is disabled.
Model decisions are advisory and explanations cite bounded monitoring evidence. No configuration secrets, bodies, screenshots or arbitrary error text are sent to the model. Suggested edges and troubleshooting actions require operator review. Controlled scenarios do not establish real-world accuracy.
Audit log
Tenant administrators and platform superadministrators can review audit events for mutations and important authentication/authorization paths. Records include actor type, identifier and label, action, resource, outcome, HTTP status, IP address, user agent, structured details, and timestamp.
| Filter | Behavior |
|---|---|
action | Exact action name; discover available actions from the actions endpoint |
outcome | success, failure, or denied |
actor_id | Filter by actor identifier |
from / to | RFC 3339 time bounds |
page / page_size | Paginated results |
sort / dir | Order by occurred_at (the default, newest first), action, resource (type, then ID) or outcome, asc or desc; ties read newest first. Any other value is HTTP 400 |
AI labels record as incident.label (resource incident/{id}), alert.label (alert triage, resource alert/{id}), monitor.label (dependency suggestions), and ai-label.export; AI settings changes record as ai-setting.update. A viewer's refused label attempt is recorded as denied.
Bulk alert triage (POST /alerts/bulk/acknowledge and /resolve) records one alert.acknowledge or alert.resolve event per requested alert (resource alert/{id}), shaped like the single action's, with details.bulk: true. An alert the batch skipped records as failure (HTTP 404, as the single action would answer) with details.reason. These per-alert events are written before the response, so they are not subject to the recorder's buffer, and they replace the usual request-level event; a refused or invalid bulk request (403, 400) records one request-level event as any other write does.
Kubernetes discovery writes record named events: discovery-integration.create, .update, .delete and .rotate-token (resource discovery-integration/{id}; .update carries details.added and details.removed, the namespaces actually added or removed, plus details.name_changed and details.location_changed, and an edit that changes nothing records no event), discovery-link.create and .delete (resource discovery-service/{id}, details.monitor_id), and discovery.approve, filed under the monitor the approval created (resource monitor/{id}, with details.discovered_service_id and details.suggestion_key); a repeated approval that only returns the already linked monitor (created: false) writes nothing and records no event. As with bulk triage, these replace the request-level event on success, and a refused or failed discovery write records one request-level event.
Audit writes are best-effort asynchronous operational records, not a transactional ledger. The platform AUDIT_RETENTION_DAYS setting defaults to 365 days; 0 keeps records indefinitely.
Import monitors
Monitor imports support JSON, YAML, and CSV with format autodetection. JSON/YAML can contain an array, a single object, common wrappers such as items, monitors, or data, a versioned portable YAML bundle, and an Uptime Kuma backup export. YAML also recognizes common source wrappers such as services, endpoints, and checks.
Two source schemas are recognized and translated automatically, so the field-mapping step is already complete when preview reports them: the portable bundle (portable_monitor_export) and an Uptime Kuma export (uptime_kuma_export). Everything else goes through field mapping.
- Upload the source to import preview.
- Review detected field/type mappings, normalization, warnings, and row errors.
- Correct ambiguous group members and unsupported types.
- Execute the import and retain the per-row created/skipped/error report.
- Open created monitors and test credentials, location assignments, notification routing, and dependencies before enabling broad alerting.
Mapped/simple import currently specializes in HTTP, ping, DNS, gRPC, and groups. Defaults include a 60-second interval, 30-second timeout, and enabled state when omitted. Duplicate name+type combinations are matched case-insensitively and skipped.
Migrating from Uptime Kuma
Upload an Uptime Kuma backup export and the importer translates monitor types, assertions, tags, retry tolerance, and group nesting on its own. Uptime Kuma 1.x writes that file from Settings → Backup → Export. Version 2.0 removed the backup button and Uptime Kuma has never had a REST API, so scripts/kuma-export in this repository logs into a running instance over its socket.io API and writes the same file: go run ./scripts/kuma-export -url https://kuma.internal -user admin (password from -pass or $KUMA_PASSWORD, plus -totp when two-factor is enabled).
Translated types: http, keyword (a body assertion, inverted for invert-keyword), and json-query (a JSON path assertion) become HTTP monitors; port becomes TCP; ping and dns map directly; push becomes a push monitor; grpc-keyword becomes a gRPC health probe; postgres, mysql, mongodb, and redis map to their database monitors; and group becomes a group, with Uptime Kuma's parent links inverted into membership so nesting survives.
Accepted status codes become explicit status ranges, redirect limits and TLS verification carry over on HTTPS monitors, and Uptime Kuma's certificate-expiry notification becomes tls_min_days_valid, which raises a dedicated TLS-expiry alert rather than failing the check — the same notify-only behavior. Retry counts land in consecutive_failures_threshold, clamped to 1-10.
Monitors with no faithful equivalent are listed as not imported rather than approximated: docker, sqlserver, steam, gamedig, mqtt, kafka-producer, radius, snmp, tailscale-ping, manual, smtp, real-browser, and rabbitmq — Uptime Kuma polls the RabbitMQ management HTTP API while this platform performs an AMQP handshake, so recreate those by hand. Unsupported DNS record types and port monitors without a port are reported the same way.
Export monitors
The monitor export endpoint produces a versioned YAML bundle with monitor configuration, tags, retry thresholds, and group membership names. Compatibility data can include legacy alert-policy names, but policy management is retired. Export only produces this portable bundle — there is no Uptime Kuma-direction export.
Administration checklist
- Keep at least two controlled superadministrator recovery paths.
- Grant tenant
editororviewerby default and reserveadminfor governance tasks. - Issue integration-specific, expiring API keys with the minimum scope.
- Test OIDC login and local/recovery login after every proxy, issuer, or public-origin change.
- Review audit events, inactive users, stale API keys, and tenant memberships on a schedule.
- Define both telemetry and audit retention intentionally.
- Treat AI hypotheses as advisory and protect the installation-owned local-service token.
- Always preview monitor imports and test imported monitors before relying on them for production alerts.