Skip to content

kOlapsis/maintenant

Repository files navigation

maintenant — Unified monitoring

maintenant

Monitor everything. Manage nothing.
Drop a single container. Your entire stack is monitored in seconds.

Release Docker License Pro — €29/mo, 14-day trial

Documentation  •  Quick Start  •  Features  •  Pricing  •  Configuration  •  API


Keep maintenant alive — go Pro for €29/mo

Built in the open by one developer in Bordeaux, France — no VC, no tracking, no dark patterns.
If maintenant replaces 3 SaaS tools in your stack, a Pro subscription pays for itself on day one.


Start 14-day free trial →  ·  Sponsor on GitHub  ·  Star the repo

Why maintenant?

Most self-hosters juggle 3-5 tools to monitor their stack: one for containers, one for uptime, one for certs, one for metrics, and yet another for a status page. maintenant replaces all of them.

maintenant Uptime Kuma Portainer Dozzle
Container auto-discovery Yes No Yes Yes
HTTP/TCP endpoint checks Yes Yes No No
Cron/heartbeat monitoring Yes Yes No No
SSL certificate tracking Yes Yes No No
CPU/memory/network metrics Yes No Limited No
Image update detection Yes No Yes No
Network security insights Yes No No No
Public status page Yes Yes No No
Alerting (webhook, Discord) Yes Yes Limited No
Kubernetes native Yes No Yes No
Single binary, zero deps Yes Node.js Docker API Docker API

One container. One dashboard. Everything monitored.


Screenshots

Dashboard
Dashboard — Uptime, response times, resources, unified monitors
Containers
Container auto-discovery
Endpoints
Endpoint monitoring
Certificates
TLS certificate tracking
Updates
Update intelligence
Status Page — All OK
Status page — All operational
Status Page — Degraded
Status page — Degraded state

Quick Start

Docker (30 seconds)

# docker-compose.yml
services:
  maintenant:
    image: ghcr.io/kolapsis/maintenant:latest
    ports:
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /proc:/host/proc:ro
      - maintenant-data:/data
    environment:
      MAINTENANT_ADDR: "0.0.0.0:8080"
      MAINTENANT_DB: "/data/maintenant.db"
    restart: unless-stopped

volumes:
  maintenant-data:
docker compose up -d

Open http://localhost:8080 — your containers are already there. No configuration needed.

Kubernetes

kubectl apply -f deploy/kubernetes/

maintenant auto-detects the in-cluster API. Read-only RBAC, namespace filtering, workload-level monitoring out of the box.

For detailed setup instructions, advanced configuration, and label reference, see the full documentation.


Features

Container Monitoring

Zero-config auto-discovery for Docker and Kubernetes. Every container is tracked the moment it starts — state changes, health checks, restart loops, log streaming with stdout/stderr demux. Compose projects are auto-grouped. Kubernetes workloads (Deployments, DaemonSets, StatefulSets) are first-class citizens.

Endpoint Monitoring

Define HTTP or TCP checks directly as Docker labels — no config files, no UI clicks. maintenant picks them up automatically when a container starts. Response times, uptime history, 90-day sparklines, configurable failure/recovery thresholds.

labels:
  maintenant.endpoint.http: "https://api:3000/health"
  maintenant.endpoint.interval: "15s"
  maintenant.endpoint.failure-threshold: "3"

Heartbeat & Cron Monitoring

Create a monitor, get a unique URL, add one curl to your cron job. maintenant tracks start/finish times, durations, exit codes, and alerts you when a job misses its deadline.

# One-liner for any cron job
curl -fsS -o /dev/null https://now.example.com/ping/{uuid}/$?

Community includes up to 5 heartbeats. Pro lifts the cap for unlimited jobs.

SSL/TLS Certificate Monitoring

Automatic detection from your HTTPS endpoints, plus standalone monitors for any domain. Alerts at 30, 14, 7, 3, and 1 day before expiry. Full chain validation.

Resource Metrics

Real-time CPU, memory, network I/O, and disk I/O per container. Historical charts from 1 hour to 30 days (Pro). Per-container alert thresholds with debounce to avoid noise. Top consumers view for instant triage.

Network Security Insights

Automatic detection of dangerous network configurations across your containers. Flags ports binding to 0.0.0.0, exposed database ports, host-network mode, privileged containers, and Kubernetes-specific risks (NodePort, LoadBalancer without NetworkPolicy). Each container image is mapped to its software ecosystem via OCI manifest inspection for CVE-relevant context.

Update Intelligence

Knows when your images have updates available. Scans OCI registries, compares digests. Compose-aware update and rollback commands with the correct --project-directory flag. Stop running docker pull blindly.

Alert Engine

Unified alerts across all monitoring sources. Webhook and Discord channels included. Silence rules for planned maintenance. Exponential backoff retry on delivery.

Pro adds Slack, Microsoft Teams, and Email channels, plus escalation chains and maintenance windows.

Public Status Page

Give your users a clean, real-time status page. Component groups, live SSE updates, severity aggregation across all monitors.

Pro adds incident timelines and subscriber notifications (email + webhook) — turn outages into trust-building moments.

MCP Server

Built-in Model Context Protocol server. Query your infrastructure, read logs, and check alert status from any MCP-compatible AI assistant. Supports both stdio and Streamable HTTP transports with full OAuth2 authentication for remote clients (Claude web, Claude mobile, Claude Desktop).


Configuration

Environment Variables

Variable Default Description
MAINTENANT_ADDR 127.0.0.1:8080 HTTP bind address
MAINTENANT_DB ./maintenant.db SQLite database path
MAINTENANT_BASE_URL http://localhost:8080 Base URL (used for heartbeat ping URLs)
MAINTENANT_ORGANISATION_NAME Maintenant Organisation name on the status page
MAINTENANT_CORS_ORIGINS same-origin CORS allowed origins (comma-separated)
MAINTENANT_RUNTIME auto-detect Force docker or kubernetes
MAINTENANT_MAX_BODY_SIZE 1048576 Max request body size in bytes (1 MB)
MAINTENANT_UPDATE_INTERVAL 24h Update intelligence scan interval
MAINTENANT_LICENSE_KEY Pro license key (enables Pro features)
MAINTENANT_MCP false Enable MCP server (Streamable HTTP on /mcp)
MAINTENANT_MCP_CLIENT_ID OAuth2 client ID for MCP authentication
MAINTENANT_MCP_CLIENT_SECRET OAuth2 client secret for MCP authentication
MAINTENANT_K8S_NAMESPACES all Namespace allowlist (comma-separated)
MAINTENANT_K8S_EXCLUDE_NAMESPACES none Namespace blocklist
MAINTENANT_DISABLE_TELEMETRY unset (telemetry on) Set to 1/true/yes to disable telemetry

Full configuration reference in the documentation.

Docker Labels Reference

Container settings
labels:
  maintenant.ignore: "true"                    # Exclude from monitoring
  maintenant.group: "backend"                  # Custom group name
  maintenant.alert.severity: "critical"        # critical | warning | info
  maintenant.alert.restart_threshold: "5"      # Restart loop threshold
  maintenant.alert.channels: "ops-webhook"     # Route to specific channels
Endpoint monitoring
labels:
  # Simple — one endpoint per container
  maintenant.endpoint.http: "https://app:8443/health"
  maintenant.endpoint.tcp: "db:5432"

  # Indexed — multiple endpoints per container
  maintenant.endpoint.0.http: "https://app:8443/health"
  maintenant.endpoint.1.tcp: "redis:6379"

  # Tuning
  maintenant.endpoint.interval: "30s"
  maintenant.endpoint.timeout: "10s"
  maintenant.endpoint.http.method: "POST"
  maintenant.endpoint.http.expected-status: "200,201"
  maintenant.endpoint.http.tls-verify: "false"
  maintenant.endpoint.http.headers: '{"Authorization":"Bearer tok"}'
  maintenant.endpoint.failure-threshold: "3"
  maintenant.endpoint.recovery-threshold: "2"
TLS certificate monitoring
labels:
  maintenant.tls.certificates: "example.com:443,api.example.com:443"
Full stack example
services:
  maintenant:
    image: ghcr.io/kolapsis/maintenant:latest
    ports:
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /proc:/host/proc:ro
      - maintenant-data:/data
    environment:
      MAINTENANT_ADDR: "0.0.0.0:8080"
      MAINTENANT_DB: "/data/maintenant.db"

  api:
    image: myapp:latest
    labels:
      maintenant.group: "production"
      maintenant.endpoint.http: "http://api:3000/health"
      maintenant.endpoint.interval: "15s"
      maintenant.alert.severity: "critical"
      maintenant.alert.channels: "ops-webhook"

  postgres:
    image: postgres:16
    labels:
      maintenant.endpoint.tcp: "postgres:5432"
      maintenant.alert.severity: "critical"

  redis:
    image: redis:7-alpine
    labels:
      maintenant.endpoint.tcp: "redis:6379"

volumes:
  maintenant-data:

Telemetry

maintenant sends an anonymous, opt-out usage snapshot once an hour to https://metrics.kolapsis.com. No hostnames, IPs, container names, endpoint URLs, certificates, webhook targets, status-page component names, license keys, or operator-supplied free-form strings of any kind are transmitted.

What is collected

Each snapshot contains the following fields and nothing else (full wire format: specs/015-shm-telemetry/contracts/telemetry-payload.md):

Application fields (this product owns these):

  • editioncommunity or pro
  • containers_total — count of auto-discovered containers
  • endpoints_total — count of configured HTTP/TCP endpoints
  • heartbeats_total — count of configured heartbeat monitors
  • certificates_total — count of TLS certificate monitors
  • webhooks_total — count of configured webhooks
  • status_components_total — count of status-page components

Runtime context (collected automatically by the SHM SDK):

  • sys_os, sys_arch, sys_cpu_cores, sys_go_version, sys_mode (docker / kubernetes / standalone)
  • app_mem_alloc_mb, app_goroutines, app_uptime_h
  • An installation identifier generated by the SDK on first run and reused thereafter

How to disable it

Set MAINTENANT_DISABLE_TELEMETRY to a truthy value before the process starts:

# Docker
docker run -e MAINTENANT_DISABLE_TELEMETRY=1 ghcr.io/kolapsis/maintenant:latest

# Kubernetes
env:
  - name: MAINTENANT_DISABLE_TELEMETRY
    value: "1"

# systemd / shell
export MAINTENANT_DISABLE_TELEMETRY=1
./maintenant

Truthy values (case-insensitive, whitespace-trimmed): 1, t, true, y, yes, on. Anything else, including empty or unset, leaves telemetry enabled.

When disabled, exactly one log line is emitted at startup and nothing else:

INFO  telemetry disabled  reason=opt-out

No background goroutine, no DNS lookup of metrics.kolapsis.com, no outbound packets toward it.

Persistent install identity

The SDK persists its identity to /data/shm/shm_identity.json on first run. Mount a persistent volume on /data/shm so the same installation isn't counted as new on every restart.

The reference Docker Compose template above already mounts /data as a volume — /data/shm is a subpath, so it's covered by default. For Kubernetes:

apiVersion: apps/v1
kind: StatefulSet
spec:
  template:
    spec:
      containers:
        - name: maintenant
          volumeMounts:
            - name: shm-data
              mountPath: /data/shm
  volumeClaimTemplates:
    - metadata:
        name: shm-data
      spec:
        accessModes: [ReadWriteOnce]
        resources:
          requests:
            storage: 100Mi

Without the volume, every restart is counted as a fresh install. The privacy impact is zero (the identity is opaque), but our fleet stats will be distorted — please keep the volume.

When /data/shm is unwritable (read-only mount, permission error), telemetry disables itself silently with a single WARN line:

WARN  telemetry disabled  reason=datadir-unwritable  datadir=/data/shm  error=...

We deliberately don't fall back to an in-memory identity — that would inflate fleet-wide install counts.


Security Model

maintenant does not include built-in authentication — by design.

Like Dozzle, Prometheus, and most self-hosted monitoring tools, maintenant is designed to sit behind your existing reverse proxy + auth middleware. No need to manage yet another set of user accounts.

Internet  ->  Reverse Proxy (Traefik / Caddy / nginx)
          ->  Auth (Authelia / Authentik / OAuth2 Proxy)
          ->  maintenant
Example: Traefik + Authelia
services:
  maintenant:
    image: ghcr.io/kolapsis/maintenant:latest
    labels:
      traefik.enable: "true"
      traefik.http.routers.maintenant.rule: "Host(`now.example.com`)"
      traefik.http.routers.maintenant.middlewares: "authelia@docker"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /proc:/host/proc:ro
      - maintenant-data:/data
    environment:
      MAINTENANT_ADDR: "0.0.0.0:8080"
      MAINTENANT_DB: "/data/maintenant.db"
      MAINTENANT_BASE_URL: "https://now.example.com"

Note: /ping/{uuid} (heartbeat pings) and /status/ (public status page) are meant to be publicly accessible. Configure your proxy rules accordingly.


Alert Sources

Source Events Default Severity
Container restart_loop, health_unhealthy Warning
Endpoint consecutive_failure Critical
Heartbeat deadline_missed Critical
Certificate expiring, expired, chain_invalid Critical
Resource cpu_threshold, memory_threshold Warning
Update available Info

Deliver to Discord or any HTTP webhook. Slack, Teams, and email available with maintenant Pro.


API

Full REST API under /api/v1/ for automation and integration.

Endpoint reference
Resource Endpoints
Containers GET /containers GET /containers/{id} GET /containers/{id}/transitions GET /containers/{id}/logs
Endpoints GET /endpoints GET /endpoints/{id} GET /endpoints/{id}/checks GET /endpoints/{id}/uptime/daily
Heartbeats GET POST /heartbeats GET PUT DELETE /heartbeats/{id} POST /heartbeats/{id}/pause|resume
Certificates GET POST /certificates GET PUT DELETE /certificates/{id}
Resources GET /containers/{id}/resources/current|history GET /resources/summary|top
Alerts GET /alerts GET /alerts/active GET POST /channels GET POST /silence
Webhooks GET POST /webhooks POST /webhooks/{id}/test
Status Page GET POST /status/groups|components|incidents|maintenance
Updates GET /updates POST /updates/scan
Security GET /security/insights GET /security/summary GET /security/insights/{id}
Events GET /containers/events (SSE stream)
Health GET /health

Architecture

┌──────────────────────────────────────────────────────┐
│                  Single Go Binary                    │
│                                                      │
│   ┌────────────────────────────────────────────┐     │
│   │  Vue 3 + TypeScript + Tailwind (embed.FS)  │     │
│   │  Real-time SSE  ·  uPlot charts  ·  PWA    │     │
│   └────────────────────────────────────────────┘     │
│                         |                            │
│   ┌────────────────────────────────────────────┐     │
│   │           REST API v1 + SSE Broker         │     │
│   └────────────────────────────────────────────┘     │
│          |                          |                │
│   ┌─────────────┐  ┌──────────────────────┐         │
│   │   Docker     │  │     Kubernetes       │         │
│   │   Runtime    │  │     Runtime          │         │
│   └─────────────┘  └──────────────────────┘         │
│          |                          |                │
│   ┌────────────────────────────────────────────┐     │
│   │  Containers · Endpoints · Heartbeats ·     │     │
│   │  Certificates · Resources · Alerts ·       │     │
│   │  Updates · Security · Status Page ·        │     │
│   │  Webhooks                                  │     │
│   └────────────────────────────────────────────┘     │
│                         |                            │
│   ┌────────────────────────────────────────────┐     │
│   │     SQLite  (WAL · single-writer · zero    │     │
│   │              external dependencies)        │     │
│   └────────────────────────────────────────────┘     │
└──────────────────────────────────────────────────────┘
  • Single binary — Frontend embedded via embed.FS. One file to deploy.
  • Zero dependencies — SQLite is the only database. No Redis, no Postgres, no message queue.
  • Real-time — SSE pushes every state change to the browser instantly.
  • Read-only — maintenant never touches your containers. Observe only.
  • Label-driven — Configure monitoring through Docker labels. No YAML to maintain.
  • ~17 MB RAM — Lightweight enough to run on any VPS or Raspberry Pi.

Pricing

Community Edition is free forever. Pro keeps the project alive.
If you ship real software, €29/mo is less than two hours of debugging the outage you didn't see coming.
And 100% of revenue funds full-time development — no investors to pay back, no salespeople to feed.

Community

Free · AGPL-3.0 · self-hosted forever

  • Container auto-discovery (Docker + Kubernetes)
  • HTTP / TCP endpoint monitoring
  • Heartbeat & cron monitoring (up to 5)
  • TLS certificate tracking
  • Resource metrics (CPU, RAM, net, disk)
  • Network security insights
  • Update intelligence (digest scan)
  • Alert engine + webhook + Discord
  • Public status page
  • REST API + SSE + MCP server
  • PWA support

Everything a solo self-hoster needs.

Pro  Recommended · 14-day free trial

€29/month · or €290/year (save 2 months)

Everything in Community, plus:

  • Unlimited heartbeats
  • Slack, Microsoft Teams, Email channels
  • Alert escalation & routing — page the right person, not a dead channel
  • Maintenance windows — silence cleanly during deploys
  • Unified security posture dashboard
  • CVE enrichment + risk scoring per container
  • Incident management with public timeline
  • Subscriber notifications (email, webhook)
  • Priority email support

Start free trial →

Why upgrade to Pro?

  • Sleep through the night. Escalation chains page the on-call engineer, then the backup, then the lead — instead of dying silently in a muted Discord.
  • Prioritize the vulnerabilities that matter. CVE enrichment and per-container risk scoring surface what's critical in your environment — not a generic feed.
  • Turn outages into trust. Public incident timelines and subscriber notifications keep your users informed automatically.
  • Get direct answers. Priority email support, straight to the developer who wrote it.
  • Fund independent software. maintenant is built in Bordeaux, France — by one developer, with no VC, no tracking, no dark patterns. Your subscription is the roadmap.

Pro — Unified Security Posture
Pro — Unified security posture with CVE enrichment & risk scoring

Flexible billing — your choice of processor

Pick the processor that fits where you are:

Region Processor Methods
Global Stripe Credit / debit card
European Union Mollie Card, SEPA Direct Debit, iDEAL, Bancontact, and more
  • 14-day free trial — plenty of time to evaluate against a real stack
  • Cancel anytime from your dashboard
  • VAT-compliant invoices issued automatically
  • Self-hosted means self-hosted — your monitoring data never leaves your infrastructure

"Why should I pay for open-source?"

Fair question. Here's the honest answer:

Is the Community Edition really everything I need?

Yes. Community is not crippleware — it runs production infrastructure every day. Pro exists for teams that need escalation routing, CVE intelligence, and premium channels. If you don't need those, stay on Community, and consider sponsoring instead.

If I don't pay, does the project die?

maintenant is AGPL-3.0 and will always be free. But one developer can only sustain this full-time if users pay. Every Pro subscription is a direct vote for "keep shipping" — no investors to please, no enterprise pivot, no acquisition exit.

Can I self-host Pro? Does my data leave my infra?

Yes, self-host Pro exactly like Community — it's the same binary. License validation is stateless and offline-tolerant. Your monitoring data never touches our servers. Ever.

Is there an Enterprise plan for larger teams?

Yes — for teams needing SSO, audit logs, custom SLAs, or on-prem support contracts. Email hello@kolapsis.com.

Activate Pro

Grab a key from maintenant.dev/#pricing, set it in your environment, restart — done.

MAINTENANT_LICENSE_KEY=your-license-key

Start 14-day free trial — €29/mo

14-day free trial · cancel anytime · VAT-compliant invoices


Support the project

maintenant is built independently in Bordeaux, France. No VC, no tracking, no telemetry, no data collection, no acquisition exit. The only way this keeps going is if users who benefit from it give back. Here's how, ranked by impact:

1. Go Pro

€29/mo · 14-day trial

The single most impactful way to support the project. Unlocks advanced features AND funds development.

Start trial →

2. Sponsor

Any amount · one-off or monthly

Don't need Pro? Sponsor on GitHub. Every sponsor gets credited in the Backers wall below.

Sponsor →

3. Spread the word

Free · 10 seconds

Star the repo, share on HN / Lobsters / Reddit / LinkedIn. Discoverability is oxygen for indie projects.

Star repo →

Backers

Every Pro subscriber and GitHub sponsor keeps this project independent. Thank you.

GitHub Sponsors

Want your company logo here? Become a corporate sponsor — visibility for you, runway for the project.


Contributing

Code contributions are welcome. Please open an issue first to discuss bigger changes. Small fixes, typos, docs — just send the PR.

For other ways to contribute (bug reports, feature ideas, feedback), see Support the project.


License

Copyright 2025-2026 Benjamin Touchard / kOlapsis — Bordeaux, France

Licensed under the GNU Affero General Public License v3.0 (AGPL-3.0) or a commercial license.


Built with care in Bordeaux, France — if maintenant saves you an outage, buy the developer a coffee (or a year of runway).