github kOlapsis/maintenant v1.8.1
Reliability and security release

5 hours ago

A reliability and hardening release. Agents connect again on Personal and Pro, alerts resolve when their condition clears, the status page delivers its emails, and every deployment path starts as documented. The documentation was reviewed page by page against the code.

Agents and multi-host

  • Agents connect to a 1.8.0 server again. The agent gRPC listener did not start on Personal and Pro; it does now.
  • An agent revoked or deleted on the server re-enrolls with a fresh token, or stops with a clear message instead of retrying forever.
  • Agents start on a host without Docker or Kubernetes, report host metrics and the OS, and attach to the runtime as soon as it answers. Runtime changes (a host joining or leaving a Swarm) are reported to the server.
  • Events replayed from the spool after an outage feed history only: they no longer change a container's live state or raise alerts.
  • Agents honour the maintenant.endpoint.interval and timeout labels of each endpoint.
  • MAINTENANT_CA_CERT now applies to every outbound TLS connection: the agent's gRPC client, webhooks and channels, SMTP, the licence server, and registries. Agents can use a private PKI.

Deployment

  • The Docker image starts as a non-root user (runAsUser, dropped capabilities), prepares a bind-mounted /data itself, and defaults MAINTENANT_DB to /data/maintenant.db.
  • Kubernetes manifests and the Helm chart (1.3.0) carry their namespace and the full read-only RBAC the runtime needs, including nodes, jobs and metrics.
  • The generated Kubernetes agent manifest is a single-replica Deployment with a persistent volume: one agent per cluster, one host slot.
  • install.sh restarts the service after an upgrade, keeps the keys it does not manage in the env file, supports offline installs (--binary, --sha256sums) and custom data paths.

Alerting

  • Escalation levels fire at their configured delay from the start of the alert, and an acknowledgment reaches every channel that was notified.
  • REST, MCP and the posture page share one acknowledgment path. An acknowledged alert no longer restarts an escalation when its severity rises: the channels get a single severity-change notice.
  • Every certificate alert (expired, chain_invalid, hostname_mismatch, ocsp_revoked), CPU and memory alerts, and Swarm alerts resolve when their condition clears, including after a restart.
  • Kubernetes alerts (replica_health, crash_loop, node_condition) are raised for the cluster the server runs in.
  • Notifications for the same alert and channel are delivered in order; a recovery never arrives before its alert.
  • Retention only purges alerts that are no longer active.

Status page

  • Subscriber emails (confirmation, incidents, maintenance) are sent through the MAINTENANT_SMTP_* settings already used by the email channel. Subscribing again gives the same answer whatever the address, so the list of subscribers cannot be probed.
  • Hidden components never appear on a public surface: page, API, events, feed or emails.
  • Incident and maintenance inputs are validated, deleting a running maintenance window closes it cleanly, and a manual status override is restored when a window ends.

Runtimes

  • A lost Docker daemon or Kubernetes API switches the server to degraded mode, shows the runtime banner, and reconnects on its own.
  • With a kubeconfig whose cluster does not answer, detection falls back to Docker. Set MAINTENANT_RUNTIME=kubernetes to wait for the cluster instead.
  • Swarm deploy.labels are read (including Traefik and Caddy labels), tasks are grouped by stack, crash loops are counted from task failures across all nodes, and manager and worker counts are reported.

Update intelligence

  • Official Docker Hub images (nginx, redis:latest) are scanned; locally built images are skipped.
  • Floating tags are compared with the digest that is actually running: an update stays listed until the container runs the new image.
  • Rollback commands target the previous image, Swarm services get docker service update --image, and maintenant.update.* labels apply to agents and Kubernetes workloads.
  • Behind a Docker socket proxy, enable IMAGES=1 so local builds and exact digests are detected.

Monitoring

  • Daily uptime is kept for a year in rollups and works on PostgreSQL. Heartbeat uptime is weighted by time and excludes paused periods.
  • maintenant.ignore silences a container everywhere: alerts, endpoints and certificates from its labels, security insights.
  • Kubernetes Services of type LoadBalancer and NodePort produce security insights.
  • Network rates are real bytes per second, and agent containers appear in live resource views.

Security

  • Cross-origin writes to /api are refused with 403 CROSS_ORIGIN_REFUSED. List trusted origins in MAINTENANT_CORS_ORIGINS; * no longer allows writes.
  • MCP OAuth redirects are rebuilt from the allowlist or a loopback host, and /mcp works behind a reverse proxy on the same host. A client secret shorter than 32 characters logs a warning.
  • Status page SVG assets are parsed in full and refused if they carry active content.
  • The runtime image picks up Alpine security updates at build time.

Changes to be aware of

  • Removed: the filter_tags trigger and escalation filter, the maintenant.alert.channels label, and the per-entity routing capability. Trigger scopes route an entity's alerts to chosen channels.
  • The status page SMTP form and GET/PUT /api/v1/status/smtp are gone; configure MAINTENANT_SMTP_*. POST /api/v1/status/smtp/test sends a test email.
  • An invalid MAINTENANT_MAX_BODY_SIZE or MAINTENANT_SECURITY_SCORE_THRESHOLD, or a gRPC certificate without its key, now stops startup with a message naming the setting.

Upgrading

Migrations 35 to 39 run at startup on SQLite and PostgreSQL.

  • Kubernetes: re-apply the manifests or run helm upgrade to get the new RBAC. For an agent deployed from an earlier manifest, delete the old DaemonSet and apply a freshly generated manifest.
  • Native install: re-run the install script; it restarts the service on the new binary.

The full documentation is at docs.maintenant.dev.

Don't miss a new maintenant release

NewReleases is sending notifications on new releases.