The headline of this release is that maintenant no longer needs a container runtime to start. The Docker / Kubernetes socket becomes an observable dependency rather than a startup gate: the app always boots, serves the UI and API, and surfaces a missing runtime as a degraded state that recovers on its own.
This release also fixes a long-standing retention bug that left archived containers piling up forever.
Degraded runtime startup
Previously, maintenant exited at startup if the Docker or Kubernetes socket was unreachable. That made the tool unusable for two common situations: monitoring only endpoints / SSL / heartbeats with no local runtime, and surviving a daemon restart or a host deploy without crashing.
The runtime connection is now non-blocking and non-fatal. The app starts in every case and treats "no runtime" as a first-class state.
How it behaves
- Bounded connect attempt. A new
TryConnect(ctx)(~3s budget) probes the runtime at startup ? DockerPing, KubernetesServerVersionunder a context timeout. On failure the app logs a warning and continues; Swarm detection is guarded behindIsConnected(). - Auto-recovery. A background supervisor loop keeps trying to connect. When the runtime comes back, container monitoring (reconcile + event stream) is wired exactly once per connection cycle ? no duplicate watchers, no manual restart.
- Daemon loss detection. If the event stream closes (the daemon goes away mid-run), the runtime is marked disconnected and a
runtime.availability_changedSSE event is broadcast so connected clients react in real time. - Last-known data stays visible. Container read endpoints (list / detail / transitions) keep serving the last persisted state and add
"stale": truewhen the runtime is disconnected, so the UI can label the data instead of going blank. - Live actions fail cleanly. Endpoints that require a live runtime (e.g. the log stream) return
503 {"error":"container monitoring unavailable"}instead of panicking. - No stats spam. The resource collector skips
StatsSnapshotticks while disconnected; host-stat collection continues unaffected.
API & health
GET /api/v1/health now reports the runtime state:
{
"runtime": { "name": "docker", "connected": false }
}Container read payloads carry "stale": true while the runtime is down.
UI
A new RuntimeDegradedBanner (semantic CSS variables only, light + dark) appears on the Containers and Dashboard pages while the runtime is unavailable, and disappears automatically when it recovers ? driven by the runtime.availability_changed SSE event via the runtime store. Endpoint, Certificate, and Heartbeat surfaces are unaffected and show no banner, since those monitors never needed a runtime.
This also enables a deliberate workflow: pause container monitoring during a deployment by stopping the daemon, without maintenant crash-looping ? monitoring resumes on its own once the runtime is back.
Fixes
- Retention purge unblocked (#25). The retention loop could fail with
FOREIGN KEY constraint failedwhen deleting an archived container that still had surviving children (state transitions, resource snapshots, or a resource alert config ? the latter is never purged). The three child tables lackedON DELETE CASCADE, so archived rows accumulated indefinitely. Migration21_containers_cascade_deleterebuildsstate_transitions,resource_snapshots, andresource_alert_configswithON DELETE CASCADEoncontainer_id, so an archived container and its history are now dropped atomically.
Internals & CI
- OCI standard labels added to the
Dockerfilefor better registry metadata. LICENSE_PUBLIC_KEYmoved to a repository variable (not a secret) in the Docker build workflow. The key is public by nature, so it stays inspectable in build logs instead of being masked.
Upgrade notes
- Nothing to configure for degraded mode ? it is the default behavior as of v1.2.14. Deployments that only monitor endpoints / SSL / heartbeats can now run with no Docker or Kubernetes socket mounted at all.
- Migration
21_containers_cascade_deleteruns automatically at startup. It rebuilds three tables; on large histories this is a one-time operation at first boot. Adown.sqlis provided (rebuilds the tables without the cascade) should you need to roll back to v1.2.13. - No new environment variables.
Documentation
- Updated: Containers (new Degraded Mode section: auto-recovery, last-known data, 503 on live actions, real-time SSE banner), Configuration.