Operations and incident platform¶
Status: target architecture; Stages 0–5 implemented per operations platform migration. Stages 6–8 remain.
Executive assessment¶
The repository already has a useful observability plane on infra-services:
- Prometheus evaluates infrastructure and application alerts.
- Alertmanager groups and routes
notify=pagealerts to Discord, allowlisted service/severity/alert-name combinations to the incident adapter, and critical patching alerts to ntfy. Unmatched alerts reachblackhole. - Grafana provisions dashboards from Git and uses Prometheus and Loki.
- Loki and Alloy retain 30 days of logs from
infra-servicesand runner hosts. - Inventory generates node-exporter targets.
- GitHub Actions and Ansible provide guarded runner maintenance and diagnostics.
- Traefik and Authentik protect human-facing monitoring interfaces.
- SOPS-backed renderers keep runtime secrets out of Git.
The principal gap is operational state. Alertmanager tracks delivery, grouping, silences, and currently active alerts, but it is not an incident record system. Discord and ntfy messages do not provide durable acknowledgement, assignment, timelines, or review data.
The existing components remain authoritative in their current domains. OneUptime Community Edition adds incident state and workflow history; it does not replace Prometheus, Alertmanager, Grafana, Loki, or the remediation control plane.
Current gaps¶
Stages 0–5 of the operations platform migration are accepted (adapter live; domain rollout through monitoring-platform as of 2026-08-01). Remaining program gaps:
- Approval-gated runner remediation is not yet connected to OneUptime timelines (Stage 6).
- OneUptime lifecycle notifications have not cut over from dual-write/pilot to production destinations (Stage 7).
- The independent host heartbeat uses Healthchecks.io + ntfy outside Prom/AM (monitoring dead-man). It measures host/timer/outbound-network liveness, not monitoring-plane health; a healthy host can keep pinging with both monitoring processes stopped. Prometheus self-health rules require a working evaluation and delivery path to notify.
continue: trueevaluates later sibling routes, not universal failover. Discord requiresnotify=page; ntfy requires criticalservice=os-patching. Allowlisted runnernotify=ticketalerts depend on the adapter without a direct Discord fallback. OneUptime is not yet the sole lifecycle notifier.- Alert noise, frequency, duration, and flapping summaries still need a decision-oriented closeout dashboard pass.
Decision¶
Use OneUptime Community Edition as the incident and response layer.
OneUptime was selected over Keep Community Edition because OneUptime is actively maintained and uniformly Apache-2.0 licensed. Keep remains functionally capable, but its open-source edition is community-maintained after the Elastic acquisition, the repository mixes MIT and commercial code, and released configuration-as-code support has material gaps.
OneUptime is deployed only after capacity and restore gates pass. Version
11.7.3 is the researched baseline; deployment pins the exact application and
dependency versions or digests.
Responsibilities and state ownership¶
| Concern | Owner | Durable state |
|---|---|---|
| Metrics and alert series | Prometheus | Prometheus TSDB, 30-day baseline |
| Logs and log alert source data | Loki | Loki TSDB, 30-day baseline |
| Alert evaluation | Prometheus and Loki ruler | Version-controlled rules |
| Grouping, inhibition, routing, silences | Alertmanager | Alertmanager state volume |
| Incident status, acknowledgement, assignment | OneUptime | PostgreSQL |
| Incident and remediation timeline | OneUptime | PostgreSQL |
| Dashboards and investigation | Grafana | Provisioned JSON plus Grafana DB |
| Direct emergency notification | Alertmanager | Receiver configuration in Git |
| Incident lifecycle notification | OneUptime | Workflows plus provider secrets |
| Remediation execution | GitHub Actions and Ansible | GitHub run logs and artifacts |
| Infrastructure inventory | Inventory YAML | Git |
Prometheus remains the sole source of truth for whether a metric alert is firing. A OneUptime acknowledgement does not silence or resolve an Alertmanager alert. Silence creation is a separate, explicitly permissioned action.
Data flow¶
flowchart LR
Sources[Exporters, applications, checks] --> Prometheus
Prometheus --> Alertmanager
LokiRuler[Loki ruler] --> Alertmanager
Alertmanager -->|matching page or critical patching route| DirectNotify[Discord and ntfy]
Alertmanager -->|allowlisted adapter routes| OneUptime[OneUptime incidents]
Prometheus --> Grafana
Loki --> Grafana
OneUptime --> Investigation[Grafana, Loki, and runbooks]
OneUptime --> LifecycleNotify[Lifecycle notifications]
OneUptime --> GitHubActions[Approved GitHub Actions]
GitHubActions --> Ansible[Bounded Ansible actions]
GitHubActions --> OneUptime
Alertmanager forwards only explicitly allowlisted service/severity/alert-name
combinations to the adapter. send_resolved: true requests recovery delivery.
Direct Discord and ntfy receivers do not depend on OneUptime for already-matching
alerts, but they still depend on Alertmanager and their providers. Receiver
selection is not proof of delivery. See the
current receiver matrix
and rollback boundary: removing
an adapter route leaves incident-only tickets without notifications unless a
fallback is separately reviewed or the owner accepts a bounded loss window.
Incident identity and lifecycle¶
Each Alertmanager alert keeps its native fingerprint as the alert identity. Repeated firing events update the same alert record.
Incidents use a versioned deterministic correlation key derived from the alert contract. The default dimensions are:
The domain dimension is explicit, for example:
runner_groupfor runner-capacity incidents;storage_poolfor storage incidents;backup_targetfor backup incidents;instanceorhostfor host-scoped availability incidents;repositoryandworkflowfor repository automation incidents.
Alertmanager groupKey is retained for traceability but is not the only
long-term incident identifier because routing configuration can change it.
An incident closes only after every attached alert fingerprint is resolved. Partial group recovery updates the timeline and leaves the incident open.
Authentication boundaries¶
Human access¶
oneuptime.infra.realemail.app is LAN/VPN only. Browser pages pass through the
local Traefik instance and authentik@file. /api and /identity use a
higher-priority router with no Authentik middleware; OneUptime's own credentials
authorize those calls, which is what the On-Call app requires. Community
Edition on this stack does not use OIDC, so browser users still complete
Authentik and then OneUptime login. A direct backend-network request must not
bypass OneUptime authorization.
Machine access¶
Alertmanager and GitHub Actions use separate, least-privilege application tokens. Machine routes are exact paths with rate limits and source restrictions; they are not covered by a broad Authentik bypass.
OneUptime receives none of the following:
- Docker socket access;
- privileged mode;
- host filesystem mounts;
- the SOPS age key;
- patch-controller or operator SSH keys;
- runner registration or operator GitHub App credentials;
- arbitrary command execution.
Network boundaries¶
The OneUptime stack has a private application network for the application,
PostgreSQL, Redis, ClickHouse, and its ingress proxy. Only the ingress proxy
joins the external traefik network.
Alertmanager delivery prefers a private, explicitly shared ingestion network. If a machine route is required through Traefik, it is limited to the exact webhook path and protected by both a OneUptime token and edge controls.
No OneUptime container publishes a host port. Adding OneUptime does not add a WAN port forward or Cloudflare Tunnel.
Storage and capacity¶
OneUptime's supported Compose deployment requires PostgreSQL, Redis, and
ClickHouse even when duplicate telemetry ingestion is disabled. The current
infra-services allocation of 4 vCPU, 16 GiB RAM, and 100 GiB disk is therefore
not sufficient.
Before deployment:
- Measure live VM, hypervisor RAM, and thin-pool headroom.
- Agree the final allocation with the owner.
- Resize VM 123 and its guest filesystem in a maintenance window.
- Update inventory only after reality changes.
- Verify at least 20 percent disk free and sufficient idle memory.
The planning target is approximately 12 vCPU, 32 GiB RAM, and 200–400 GiB disk. The final disk allocation must account for current thin-pool headroom and OneUptime's actual incident-only growth.
Backup requirements¶
OneUptime is tier 1 once it becomes the incident record:
- PostgreSQL logical backup for incidents, users, workflows, and timelines;
- ClickHouse-consistent backup even while telemetry ingestion is disabled;
- SOPS-protected preservation of
ENCRYPTION_SECRETand service credentials; - exact Compose configuration and image digests in Git;
- off-host restic copy and an isolated restore drill.
Redis is cache and queue state and is restored empty.
Prometheus and Loki remain retention-bounded tier-2 telemetry unless a later owner decision promotes their history. Alertmanager state is included in monitoring recovery so active silences survive a host loss.
Failure modes¶
| Failure | Detection | Degraded behavior |
|---|---|---|
| OneUptime unavailable | Readiness probe and container alerts, where configured | Only matching page/critical-patching routes retain direct destinations; incident-only tickets have no direct fallback |
| PostgreSQL unavailable | Readiness and database health checks | No incident mutations; only matching direct routes remain independent |
| Redis or workers unavailable | Queue and workflow health checks | Incidents may persist but workflows pause |
| ClickHouse unavailable | Analytics database health check | OneUptime readiness may fail; telemetry remains in Prometheus/Loki |
| Alertmanager unavailable | Prometheus may observe scrape failure, but notification through the failed Alertmanager can be lost | Host heartbeat can remain healthy; OneUptime cannot compensate for lost routing |
| Prometheus unavailable | Independent monitoring-chain watchdog acceptance remains pending; host heartbeat is insufficient | Metric alerts cannot evaluate; host heartbeat can keep pinging |
| Authentik unavailable | External SSO probe | Human UI is unavailable; machine ingress remains independent |
| GitHub Actions unavailable | Workflow dispatch and queue alerts | Investigation continues; remediation is manual |
| Notification provider failure | Delivery canary and workflow status | Incident console remains authoritative |
An end-to-end monitoring watchdog must terminate outside the Prometheus/Alertmanager failure domain and separately prove evaluation and delivery loss detection. The existing independent host heartbeat is not that watchdog. Critical severity alone does not imply an independent delivery path: some critical alerts intentionally remain tickets. Changing that policy requires owner review.
Upgrade and rollback strategy¶
OneUptime releases frequently and applies database migrations at startup.
Upgrade:
- Review release and security notes.
- Test the exact target version against a restored dataset.
- Take and verify PostgreSQL and ClickHouse backups.
- Pull pinned images and record digests.
- Stop ingress and application workers.
- Start the new application and allow migrations to finish.
- Test readiness, login, incident history, firing/resolved correlation, links, and notification/remediation workflows.
Rollback restores the previous PostgreSQL and ClickHouse backups and the prior exact images together. Reverting an image tag without restoring migrated data is not a rollback.
Implementation sequence¶
- Land this architecture and the alert contract.
- Add semantic CI and correct existing rule defects.
- Validate and resize
infra-services. - Deploy OneUptime as an authenticated shadow stack.
- Prove backup and restore before alert ingestion.
- Implement the GitHub runner correlation adapter after the native workflow concurrency gate failed.
- Roll out alert domains and operational dashboards incrementally.
- Connect approval-gated runner remediation.
- Migrate lifecycle notifications and add platform self-monitoring.
See operations platform migration for gates and rollback points.
Known risks and deferred work¶
- Community Edition requires a second local login behind Authentik because OIDC is an enterprise feature.
- The five-service incident-only deployment omits OneUptime's probe and AI containers and must be retested on every upgrade.
- Native workflow find/create behavior failed duplicate safety on 2026-07-31: two concurrent deliveries created two incidents for one correlation key. The workflow remains disabled. The race-safe incident adapter replaced it and now accepts allowlisted production alerts.
- The monitoring host runs several stateful services. Capacity is a hard gate, not a documentation exercise.
- Synology, UPS, and external probes need additional exporters before their domains can be represented completely.