Releases: kOlapsis/maintenant
Maintenant v1.2.3
Fixes
Endpoint and certificate creation failed with no such column: deleted_at
The standalone certificate quota check ran a SELECT COUNT(*) FROM cert_monitors WHERE source='standalone' AND deleted_at IS NULL query, but cert_monitors has no deleted_at column. Every quota check errored out, causing both HTTP/HTTPS endpoint creation and SSL certificate monitor creation to fail with Failed to create endpoint.
The stray deleted_at filter has been removed. Fixes #19.
Thanks to @samymokhtari for the detailed report and logs.
Upgrading from v1.2.2
docker compose pull && docker compose up -d --force-recreateNo database migrations, no configuration changes required.
Maintenant v1.2.2
Community Edition Quotas
Community Edition quotas are now correctly enforced across all resource types. Heartbeats were already limited, but endpoints, TLS certificates, and status pages were not — this is now fixed:
- Endpoints: max 10
- TLS Certificates: max 5 standalone
- Status Pages: max 1 group, 3 components
The /api/v1/edition API now exposes active quotas and current usage. The frontend displays real-time consumption.
TLS Certificate Alerts
Certificate expiry alerts now use contextual severity (warning / critical) based on how close the expiration date is, instead of a fixed level.
Fixes
- Upgrade links in the frontend now point to the internal
/pro-editionroute instead of an external URL.
Breaking Change: Non-Root Container
The Maintenant container now runs as user nobody (UID 65534) instead of root.
This is an important security hardening that eliminates the privilege escalation vector via the Docker socket.
What changed
| Before (v1.2.1) | Now (v1.2.2) |
|---|---|
Process ran as root inside the container |
Process runs as nobody (65534:65534) |
| Docker socket was directly accessible | Docker socket requires group_add to be readable |
| Read-write filesystem | read_only filesystem with tmpfs for /tmp |
Action required
Check the GID of the docker group on your host and update your compose.yml accordingly:
# Find the docker group GID on your host
getent group docker | cut -d: -f3Then add these directives to your maintenant service:
services:
maintenant:
image: ghcr.io/kolapsis/maintenant:latest
read_only: true
security_opt:
- no-new-privileges:true
group_add:
- "${DOCKER_GID:-983}" # ← docker group GID on your host
tmpfs:
- /tmp:noexec,nosuid,size=64m
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- maintenant-data:/dataThe default GID is 983 (common on Arch/systemd). On Ubuntu/Debian it is often 999 or 998. Check with the command above.
Without a correctly configured group_add, Maintenant will not be able to read the Docker socket and container auto-discovery will not work.
Environment variable
You can set DOCKER_GID in a .env file next to your compose.yml:
DOCKER_GID=999Kubernetes
For Kubernetes deployments, configure runAsUser and runAsGroup in the pod's securityContext:
securityContext:
runAsUser: 65534
runAsGroup: 65534
readOnlyRootFilesystem: true
allowPrivilegeEscalation: falseFull Changelog
Features
- Expose quotas in
/api/v1/editionendpoint - Add endpoint quota for Community Edition (max 10)
- Add certificate quota for Community Edition (max 5 standalone)
- Add status page quotas for Community Edition (1 group, 3 components)
- Wire Enterprise unlimited quotas in app initialization
- Add frontend quota awareness UI for Community Edition
Fixes
- Run container as nobody with hardened security defaults
- Change upgrade links from external URL to internal
/pro-editionroute - Use contextual severity for certificate expiry alerts
Tests
- Add coverage for certificate expiry severity logic
Docs
- Align all compose examples and guides with container hardening
Maintenant v1.2.1
Date: 2026-03-30
Base: v1.2.0
Improvements
Configurable log level
The log level can now be set via the MAINTENANT_LOG_LEVEL environment variable. Accepted values: debug, info, warn, error (case-insensitive). Defaults to info.
environment:
MAINTENANT_LOG_LEVEL: debugKubernetes — runAsNonRoot no longer rejects the pod
The manifests previously specified runAsNonRoot: true without a runAsUser, causing Kubernetes to reject the pod since the image has no USER instruction. The pod securityContext now sets runAsUser: 65534 (nobody), which satisfies the constraint. Fixes #17.
The USER directive has been removed from the Dockerfile — in Docker mode the container needs access to /var/run/docker.sock; non-root is enforced at the pod level in Kubernetes.
Kubernetes manifests — image tag and pull policy
The raw manifests referenced v0.1.0 (which was never published). They now point to latest with imagePullPolicy: Always.
Upgrading from v1.2.0
docker compose pull && docker compose up -d --force-recreateNo database migrations, no configuration changes required.
Maintenant v1.2.0
Date: 2026-03-30
Base: v1.1.2 (a9e6893)
New Features
Docker Swarm Monitoring
Maintenant now auto-discovers and monitors Docker Swarm clusters with no configuration required. When deployed on a manager node, it detects Swarm mode automatically and starts tracking services, tasks, and nodes in real time.
Community Edition — the same "observe without config" experience, extended to Swarm:
- Service discovery — All services enumerated via the Swarm API with mode (replicated/global), image, replica counts (e.g. "3/3 running"), task states, published ports, and attached networks
- Stack grouping — Services deployed with
docker stack deployare automatically grouped by their stack name (com.docker.stack.namespace); override per-service withmaintenant.group - Real-time SSE updates — Service create, update, and remove events propagate to the dashboard within seconds
- Startup reconciliation — Full service and task discovery on startup ensures the dashboard reflects cluster state even after a restart
- Worker node fallback — If deployed on a worker node, Maintenant degrades gracefully to standard Docker container monitoring with a log message
- Manager demotion handling — If the node is demoted from manager to worker at runtime, Maintenant degrades automatically and broadcasts a status update
Enterprise Edition — cluster intelligence, alerting, and a dedicated dashboard:
- Node health overview — All nodes with role, status, availability, engine version, and task count
- Node alerting — Alerts when nodes go down, are drained, or quorum is degraded
- Crash-loop detection — Automatic detection of task failure patterns (3+ failures within 5 minutes), with recovery detection
- Replica health alerting — Alerts when running replicas fall below the desired count
- Rolling update tracking — Real-time progress, stall detection, and rollback alerts
- Dedicated Swarm dashboard — Cluster-wide view with node list, service summary, task distribution, and aggregate health
Labels must be placed in the deploy.labels section of the service definition, not the top-level labels section. All standard maintenant.* labels are supported (group, ignore, alert severity, channels).
See the Swarm documentation and Swarm deployment guide for details.
Kubernetes Dashboard
The Kubernetes section of the UI has been completely reworked. Where the previous release shipped the K8s backend, this release adds the dedicated frontend section with full cluster visibility.
- Workloads view — Deployments, StatefulSets, and DaemonSets grouped by namespace with replica counts, readiness, and rollout status
- Pod detail — Individual pod states, container list, resource usage, restart counts, and log access
- Cluster overview — Node list with roles, status, and resource allocation
- Namespace filtering — The view respects
MAINTENANT_K8S_NAMESPACESandMAINTENANT_K8S_EXCLUDE_NAMESPACES— only visible namespaces appear in the UI
Helm Chart for Kubernetes
A production-ready Helm chart is now included at deploy/helm/maintenant/.
helm install maintenant ./deploy/helm/maintenant \
-n maintenant --create-namespaceThe chart ships with Ingress support (including TLS), configurable resource limits, Enterprise license injection (direct or via existing secret), and sensible defaults. See the Kubernetes guide for the full values reference.
Runtime-Aware Navigation
The sidebar now adapts to the detected runtime. Docker, Swarm, and Kubernetes each surface their own dedicated section — only what is relevant to your environment is shown. Runtime detection happens automatically and the UI updates in real time via SSE if the runtime status changes (e.g. Swarm manager demotion).
Update Tag Filter Labels
Two new Docker labels let you precisely control which tags Maintenant considers as update candidates for a container, closing #14.
| Label | Type | Description |
|---|---|---|
maintenant.update.tag-include |
Go regex | Only tags matching this pattern are considered as update candidates |
maintenant.update.tag-exclude |
Go regex | Tags matching this pattern are excluded from candidates |
Priority rules:
tag-includereplaces the automatic variant filter (e.g.-alpine,-bookwormdetection is bypassed)tag-excludealone preserves the variant filter — only matching tags are removed after- Exclude applies after include — exclude always wins when both are set
- Invalid regex → warning logged, label ignored, default behavior applies
Common patterns:
# Stay on Node 20 alpine — never jump to Node 21
labels:
maintenant.update.tag-include: "^20\\.\\d+\\.\\d+-alpine$"
# Exclude pre-release tags
labels:
maintenant.update.tag-exclude: "(rc|beta|alpha)"
# Pin to Postgres 15.x, no pre-releases
labels:
maintenant.update.tag-include: "^15\\."
maintenant.update.tag-exclude: "(rc|beta|alpha)"These labels have no effect on containers using non-semver channel tags (latest, lts, stable) — those containers use digest-only comparison and bypass the tag list entirely.
Bug Fixes
- Numeric build ID tags excluded from semver candidates — Tags composed entirely of digits (e.g. CI build IDs like
20240315) are no longer treated as semver candidates and no longer generate spurious update suggestions - CrashLoopBackOff alerts fire at startup — Pods already in a crash loop when Maintenant starts now trigger alerts immediately instead of waiting for the next state transition
- Kubernetes ExternalID route matching — Routes that accept Kubernetes ExternalIDs (which include
/) now use wildcard path segments and match correctly - Expired license reported when registry is unreachable — License validation now correctly reports an expired license even when the license server cannot be reached, instead of falling back silently to Community Edition
Upgrading from v1.1.2
docker compose pull && docker compose up -d --force-recreate- Database migrations run automatically on startup
- Swarm CE and Kubernetes features require no schema changes (in-memory state)
- Enterprise Swarm node tracking adds a
swarm_nodestable (migration applied automatically) - No configuration changes required — runtime detection is fully automatic
Maintenant v1.1.2 - Standalone Endpoints & Update Intelligence Fix
Standalone endpoint monitors (discussion #6)
Endpoints can now be created directly from the UI, without requiring Docker/K8s labels. Click "New Endpoint" on the Endpoints page to monitor any HTTP or HTTPS URL or TCP host:port.
- Name, target URL, type (HTTP/TCP), and check interval are configurable
- HTTPS targets offer a "Monitor TLS certificate" checkbox that creates a certificate monitor alongside the endpoint
- Standalone endpoints appear in the same grid as auto-discovered ones, with a delete button in the card footer
- Full API support:
POST /api/v1/endpoints,PUT /api/v1/endpoints/{id},DELETE /api/v1/endpoints/{id}
Digest baseline tracking for non-semver tags (discussion #7)
Images using channel tags (lts, alpine, stable, latest) are no longer incorrectly flagged as having a semver update available. Maintenant now tracks remote digests for these tags and detects actual image rebuilds by comparing against stored baselines, instead of suggesting a switch to the latest semver tag.
UI consistency & ConfirmDialog
- Replaced all native browser
confirm()dialogs with a custom ConfirmDialog component — dark-themed, accessible (role="alertdialog"), keyboard-navigable (Escape to cancel), with destructive action styling - Unified delete button placement across all cards (endpoints, certificates, heartbeats) — always right-aligned in a dedicated actions section
- Applied to all 9 components that had delete/cancel actions: cards, channel manager, silence rules, status page managers, webhooks
PWA cache isolation
- Runtime caches are now versioned per build — each deployment gets unique cache names, preventing stale assets from persisting across updates
sw.js,registerSW.js, andmanifest.webmanifestare served withno-cacheheaders so browsers always fetch the latest service worker- SPA shell (
index.html) also served without caching to ensure immediate pickup of new builds
Maintenant v1.1.1 - Log Viewer Overhaul
This release completely reworks the log viewer, addressing the feedback from #10 and #11.
Core improvements (fixing #11):
- ANSI color support — escape sequences are now properly parsed and rendered with their original colors, no more garbage characters
- Word wrap toggle — long lines wrap by default; toggle off for horizontal scrolling
- Auto-scroll — logs stick to the bottom as new lines arrive, with a "new lines" badge when scrolled up
- Expanded view — full-screen mode (click the expand icon) to use the entire window width instead of the side panel
Search & intelligence:
- Full-text search (Ctrl+K) — live-as-you-type highlighting with match counter and keyboard navigation (Enter / Shift+Enter)
- Regex support — toggle regex mode in the search bar, with visual feedback on invalid patterns
- Log level colorization — colored left-border accents (red for errors, amber for warnings, blue for info, gray for debug) auto-detected from slog, logrus, zap, bracketed, and JSON structured formats
- JSON formatting — JSON log lines get syntax coloring; click to expand/collapse between compact and pretty-printed views
- Timestamp column — parsed timestamps shown as HH:MM:SS with hover tooltip for full timestamp and relative time; auto-hidden when no timestamps are detected
RBAC fix (fixing #10):
- Fixed a crash when viewing logs of containers where all Kubernetes RBAC calls are denied — the viewer now gracefully handles permission errors instead of failing silently with an empty state
Maintenant v1.1.0
Maintenant v1.1.0
New Features
Network Security Insights
Maintenant now inspects container network configurations and flags common misconfigurations:
- Exposed port analysis — detects containers binding directly to
0.0.0.0, database ports exposed without restriction, and host-network mode usage - Dynamic CVE ecosystem resolver — maps container images to their software ecosystem (OS packages, language runtimes, application servers) using OCI manifest inspection with a multi-level fallback chain (labels, manifest config, known image databases)
- Per-container security detail — security insights are accessible directly from the container detail panel
Unified Security Posture Dashboard (Pro)
A new dedicated page provides a single view of infrastructure security health:
- Security posture scoring — each container receives a score based on its network exposure, image update status, and CVE-relevant configuration. A global posture view aggregates scores across the infrastructure
- Global posture score with breakdown by category (network, updates, configuration)
- Per-container risk ranking with drill-down to individual findings
- Severity distribution across all monitored containers
- Risk acknowledgment — dismiss known findings with audit trail
In-Place Entity Navigation
Alerts, dashboard, and security posture pages now open entity details directly in a slide-over panel instead of navigating away. This keeps context visible while inspecting a specific container, endpoint, or certificate.
- Incident feed items link directly to the relevant entity with its detail panel auto-opened
- Deep linking support — entity detail URLs are shareable
Compose-Aware Update Commands
Update and rollback commands now include the correct --project-directory flag, so they work reliably when the compose file lives outside the current working directory.
Bug Fixes
- Stale update records after container upgrade — update records now clear automatically when a container has been upgraded to the latest version, and re-scans correctly update the tracked current tag
- Certificate monitor UNIQUE constraint — certificate monitor creation no longer fails on startup when an inactive monitor already exists for the same host:port pair
- Memory consumer sorting — top consumers are now ranked by absolute memory usage (bytes) instead of percentage of limit, which gave misleading results for containers with memory limits set
- MAINTENANT_ADDR in deployment examples — all docker-compose examples now include the required
MAINTENANT_ADDRenvironment variable
Technical Improvements
Application Architecture
The backend has been restructured for maintainability:
- App container — service wiring extracted from
main.gointointernal/app, reducing the main function to configuration and startup - Dependency injection via Deps structs — all service constructors now accept a typed struct instead of positional parameters, making dependencies explicit and constructor signatures stable as the codebase grows
- Dead code removal — unused
SetEventCallbackcalls and orphaned registration methods cleaned up
HTTP Layer
- Middleware chain extraction — middleware is now composed declaratively instead of being nested in the router constructor
Register*methods folded intoNewRouter— route registration is centralized, removing scattered setup codehttp.Flusherpreservation — the middleware chain now correctly passes through theFlusherinterface, fixing SSE streaming through middleware
Testing
- Unit tests added for heartbeat, resource, status, and five other core service packages
- Tests run with
-raceto catch concurrency issues early
Frontend
ContainerCardredesigned using design system tokens for consistent spacing, typography, and color usage- SMTP notification page shows a clear "not configured" placeholder instead of an empty state
- Page layouts normalized across the application
Build Tooling
Makefileadded withbuild,test, andlinttargets
Upgrading from v1.0.1
- Pull the new image and recreate:
docker compose up -d --force-recreate - Database migrations run automatically (adds compose working directory tracking)
- No configuration changes required
Maintenant v1.0.1
New Features
Host Resource Monitoring (CPU, RAM, Disk)
The dashboard now displays real host metrics (CPU, memory, disk) by reading directly from /proc on the machine, instead of being limited to container stats.
- New
hoststatcollector that parses/proc/stat,/proc/meminfoand mount points for accurate system metrics - API endpoint
/api/v1/resourcesenriched with host data - Dashboard
ResourceStripcomponent displays host CPU, RAM and disk gauges
Required: mount /proc read-only into the container:
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /proc:/host/proc:roMobile-First Dashboard
Dashboard redesigned with a mobile-first approach:
- Responsive layout with adaptive grid (1 / 2 / 3 columns depending on screen size)
AlertList,ContainerDetail,ContainerEventTimelineand header components adapted for small screens- Improved PWA support: SVG icons, updated manifest, apple-touch-icon
Bug Fixes
Exit Codes 137/143 Treated as Graceful Stops
Docker stop sends SIGTERM then SIGKILL (exit 137), and containers handling SIGTERM exit with code 143. Both cases are now classified as "completed" instead of "exited" (error).
- Applied in both real-time event processing (
diehandler) and startup reconciliation (inspectAndMap) - New
containerState.tsutility module centralizing frontend state logic
Container Name Overflow in Cards
Fixed a display bug where long container names would overflow the card instead of being truncated.
Documentation
- Added screenshots to README and feature documentation (dashboard, containers, endpoints, certificates, updates, status page, MCP assistant)
- Added
/proc:/host/proc:rovolume mount to all docker-compose examples (README, installation, labels guide, security, index)
Files Changed
- Backend:
internal/resource/hoststat.go(new),internal/resource/collector.go,internal/resource/service.go,internal/api/v1/resources.go,internal/container/service.go,internal/docker/discovery.go - Frontend:
DashboardPage.vue,ContainerCard.vue,ContainerDetail.vue,AppHeader.vue,AlertList.vue,ResourceStrip.vue,ResourceSummary.vue,containerState.ts(new),resourceApi.ts - Docs:
README.md,docs/index.md,docs/security.md,docs/getting-started/installation.md,docs/guides/docker-labels.md,docs/features/*.md
Upgrading from v1.0.0
- Add the
/proc:/host/proc:rovolume to yourdocker-compose.yml - Recreate the container:
docker compose up -d --force-recreate
Maintenant v1.0.0 — First Light
The first public release of Maintenant, a self-discovering infrastructure monitoring tool. Deploy a single binary, point it at your Docker socket or Kubernetes cluster, and let it do the rest.
What's included
Auto-discovery
- Automatic container detection via Docker and Kubernetes labels
- Real-time event streaming — containers appear, disappear, and update without manual config
- Compose project and service grouping out of the box
Monitoring
- Endpoints — HTTP/TCP checks with configurable intervals and failure thresholds
- Heartbeats — Dead man's switch with per-heartbeat deadlines and grace periods
- TLS Certificates — Expiry tracking with auto-detection from HTTPS endpoint checks
- Resources — CPU, memory, and disk usage per container with threshold alerts
Alerting
- Unified alert engine with severity escalation, recovery detection, and silence windows
- Notification channels: webhook, Discord, SMTP
- Orphan alert pruning on startup
Update intelligence
- OCI registry scanning for available image updates
- Semver-aware comparison across all monitored containers
Public status page
- Per-component status derived from live monitor state
- Real-time updates via SSE
- Aggregate status across all monitors of a given type
Operations
- Single binary with embedded Vue SPA — no separate frontend deployment
- SQLite with WAL mode — no external database required
- MCP server support (stdio and Streamable HTTP)
- PWA-ready frontend with offline support
- Multi-arch Docker image (amd64/arm64)
- Enterprise-ready: AGPLv3 licensed with additionnal Pro/Commercial