Vigilant Vole
Latest release on GitHub

Know the moment something goes down.

Vigilant Vole is a lightweight, self-hosted uptime monitor written in Rust. Status pages, smart alerts and remote agents, in the spirit of Uptime Kuma.

One ~20 MB image. SQLite. Runs anywhere Docker does.

MIT licensedBuilt in RustLight and dark

The Vigilant Vole dashboard: 10 monitors with live status, 24-hour heartbeat bars, uptime and response times, and counters for up, down, pending and maintenance.

Watch everything you run.

Thirty kinds of checks, alerts that don’t cry wolf, and status pages your users will actually read, from one small container.

Thirty ways to check

HTTP(S) with status codes, headers, auth and proxies, plus keyword and JSONPath checks. TCP ports, ping, DNS with nine record types and your own resolver, push heartbeats for cron jobs, Docker containers, WebSockets, domain expiry over RDAP, NTP, Steam game servers, Minecraft (Java and Bedrock), Satisfactory, FiveM/RedM and Mumble servers, and groups.

Services, too: PostgreSQL, MySQL/MariaDB, SQL Server, MongoDB, Redis, MQTT, Kafka, RabbitMQ, gRPC health checks and keyword calls (any unary method, from a .proto or server reflection), SMTP, RADIUS, SNMP (v1, v2c and v3) and TLS handshakes, plus Tailscale pings through the host’s tailscaled. HTTP checks can sign in with basic auth, OAuth2 client credentials or a client certificate.

And real browsers: a headless Chromium next to it (browserless or chromedp/headless-shell) loads the page with its scripts, looks for text or a CSS selector, can fail on JavaScript errors, and keeps a screenshot of the last failure. The browser is its own container, so this one stays small.

TLS certificates and domain registrations warn you before they expire. Tags, groups and maintenance windows keep a hundred monitors as calm as ten.

All monitor types

Alerts that don’t cry wolf

A failing check retries on its own interval before anyone hears about it. Alerts fire on settled changes only, recovery messages say how long it was down, and flapping monitors are called out instead of flooding your phone.

Send reminders every few failed checks while it stays down, and escalate to a second channel, say PagerDuty, after a set number of minutes. Upside-down mode flips any check.

How notifications work

Status pages people actually read

Public pages with sections, 90-day uptime bars, response times, incidents written in Markdown (pinned, with history) and scheduled maintenance. Light, dark or automatic, custom CSS, and your own domain.

Every page is also JSON for embedding, and SVG badges put status, uptime, response time or certificate expiry in a README.

Status pages and badges

Confirm outages from somewhere else

Run the same binary in agent mode on another network, in another country. Agents pick up the monitors you mark, run them, and report back to your server.

Turn on outage confirmation and a local failure only becomes down, and only alerts, when the agents agree. A flaky uplink at home no longer pages you at 3 a.m.

Remote agents guide

Label a container, get a monitor

Mount the Docker socket, or a read-only socket proxy, switch on discovery, and add vigilant.* labels. Vigilant Vole creates the monitor and pauses it when the container goes away.

Monitors you made by hand are never touched.

Docker discovery reference
services:
  payments:
    image: ghcr.io/acme/payments:latest
    labels:
      vigilant.enable: "true"
      vigilant.name: "Payments API"
      vigilant.type: "http"        # default: docker (running + healthy)
      vigilant.target: "http://payments:8080/health"
      vigilant.interval: "30"
      vigilant.group: "Production"
      vigilant.tags: "prod,team:payments"
      vigilant.notify: "Ops Discord"

24 notification providers, plus Apprise for 90 more.

Each channel has a Send test button. Mark one as default and new monitors get it automatically.

  • Discord
  • Slack
  • Microsoft Teams
  • Google Chat
  • Mattermost
  • Rocket.Chat
  • Matrix
  • Webex
  • Feishu/Lark
  • DingTalk
  • Telegram
  • Signal
  • SMS via Twilio
  • ntfy
  • Pushover
  • Gotify
  • Pushbullet
  • Bark
  • Email (SMTP)
  • PagerDuty
  • Opsgenie
  • Webhook
  • Home Assistant
  • Apprise

Built to be operated.

An API for everything, your whole setup in git, and an easy way over from Uptime Kuma.

  • REST API

    Full CRUD for monitors, status pages, incidents, maintenance and settings. A browsable reference in the app, and an OpenAPI 3.1 document.

    API docs
  • Config as code

    Export the whole setup as one YAML or JSON file, keep it in git, and apply it back with a dry-run plan first. Merge, replace, or apply on every start.

    Config schema
  • Move from Uptime Kuma

    Upload kuma.db (1.23 or 2.x) or a JSON backup. Monitors, groups, tags, notifications, status pages and maintenance come across, and push tokens are kept.

    Migration guide
  • Prometheus and Grafana

    A /metrics endpoint with Kuma-compatible metric names, so the Grafana dashboards you already have keep working.

    Metrics reference
  • Roles, 2FA and API tokens

    Admin, editor and viewer roles, TOTP with recovery codes, and expiring read or write tokens. Argon2 passwords and a strict Content-Security-Policy.

    Security notes
  • Backup and restore

    Download a consistent database snapshot while monitoring keeps running, and restore one on the next start. Upgrades take a snapshot first.

    Backups

Small enough to forget about.

One static Rust binary serves server-rendered HTML. No Node.js, no external database, no OpenSSL. Everything it keeps lives in one folder.

  • Docker image ~20MB Compressed, about 61 MB on disk
  • Binary ~32MB Static, with everything compiled in
  • Memory at idle A fewMB Kuma typically uses 100 MB or more
  • To back up 1folder SQLite, session key and backups in /data

Take a closer look.

Calm in light and dark, live over Server-Sent Events, and just as at home on a phone.

Monitor detail for Website: up, uptime tiles from 24 hours to one year, a 24-hour response-time chart, a 90-day uptime bar, recent events and the TLS certificate with 67 days left.
Monitor detail. Uptime from a day to a year, response times, 90 days of history, events and the certificate.
The dashboard on a phone: monitor counters, filter chips and the monitor list, with a tab bar at the bottom.
On your phone. The whole app works on a small screen and installs as a PWA.

Public status pages

An overall banner, incidents, sections and 90-day uptime bars, on its own URL or your own domain. This one is in the light theme.

Set up a status page
A public status page in the light theme: a yellow Partial outage banner, an incident about delayed payment confirmations, and Website and API sections with 90-day uptime bars.

Vigilant Vole and Uptime Kuma.

Uptime Kuma is an excellent, mature project with a big community, and Vigilant Vole borrows a lot of its ideas. Here’s an honest comparison with Kuma 1.23 and 2.0.

Feature comparison between Vigilant Vole and Uptime Kuma
Feature Vigilant Vole Uptime Kuma
Footprint
RuntimeOne static Rust binary, server-rendered HTML (Askama + htmx)Node.js + Vue SPA
Docker image~20 MB compressed (~70 MB on disk)Hundreds of MB
Idle memoryA few MBTypically 100 MB+
DatabaseSQLite (bundled)SQLite, or MariaDB/MySQL in 2.0
Monitoring
HTTP(S), keyword, JSON query, TCP, ping, DNS, push, Docker, Steam, groups, WebSocketYesYes
Domain expiry (RDAP), NTP monitorsYesNo NTP; domain expiry varies by version
Database monitors: PostgreSQL, MySQL/MariaDB, Redis, SQL Server, MongoDBYesYes
MQTT, Kafka, RabbitMQ, gRPC health checks, RADIUS, SNMP v1/v2c, SMTP, TLS handshakeYesYes, except a TLS-handshake type
gRPC keyword callsYes, from a .proto or server reflection; metadata is sentYes, with a pasted .proto
Game serversYes, a curated set: Valve/Source games, Minecraft Java and Bedrock, Satisfactory, FiveM/RedM, MumbleYes, about 360 games via GameDig
SNMPv3Yes, every security level: MD5, SHA-1, SHA-2 authentication; DES, AES-128/192/256 privacyYes, noAuthNoPriv only
Tailscale pingYes, through the host’s mounted tailscaled socketYes, via the tailscale CLI (not in the Docker image)
Real-browser (headless Chrome) monitorYes, via a remote browser (CDP)Yes
HTTP authBasic, OAuth2 client credentials, mTLSBasic, NTLM, mTLS, OAuth2 client credentials
Alerting
Notification providers24 native + Apprise (90+ services)90+ native
Reminders (resend while down)YesYes
Escalation channels after N minutesYesNo
Flap detectionYesNo
Multi-location checks, outage confirmationRemote agentsNo
Status pages
Status pages, custom domains, badgesYesYes
Status page logo upload, analytics, password protectionYes, with built-in cookie-free analyticsLogo and analytics; no password protection
IncidentsMultiple per page, pinned, historyOne active incident per page
Maintenance windowsManual, once, daily, weeklyAlso cron, day-of-month, every N days
Running it
Multiple users with rolesAdmin, editor, viewerSingle user
2FA (TOTP)Yes, with recovery codesYes
REST APIFull CRUD + OpenAPINo (socket.io; API keys for metrics only)
Config as code, GitOpsYAML/JSON, dry-run, merge or replaceNo
Docker label auto-discoveryBuilt inNo (third-party AutoKuma)
Prometheus metricsKuma-compatible names + moreYes
Long-range uptime after retentionDaily rollupsAggregate tables in 2.0
Import from the other oneReads kuma.db–
Interface languages26, incl. right-to-left (ar, he, fa) and CJK (ja, ko, zh)About 50 languages
Built-in Cloudflare TunnelNoYes

When Kuma is the better fit If you need a language outside our 26, or real-browser checks without running a separate browser container, Uptime Kuma is the better choice today. Already on Kuma? The importer brings your setup across.

Up in a minute.

Pull the image, map a port and a folder, and open http://localhost:3001. A one-time setup wizard creates your admin account.

Finish setup right away Until the first admin exists, anyone who can reach the page can create one. Set VV_SETUP_TOKEN to require a secret in the setup link.

Docker

docker run -d --name vigilant-vole --restart unless-stopped \
  -p 3001:3001 \
  -v "$PWD/data:/data" \
  --cap-add NET_RAW \
  ghcr.io/ferdinand99/vigilant-vole:latest

Docker Compose

services:
  vigilant-vole:
    image: ghcr.io/ferdinand99/vigilant-vole:latest
    container_name: vigilant-vole
    restart: unless-stopped
    ports:
      - "3001:3001"
    volumes:
      - ./data:/data
    cap_add:
      - NET_RAW # raw ICMP fallback for ping monitors

Save it as docker-compose.yml and run docker compose up -d. The full file has commented extras: the Docker socket, a config file and a remote agent.

Unraid

Search for Vigilant-Vole in Community Applications. The template sets the port, the appdata path and PUID/PGID for you. Manual setup

Linux (systemd)

bash -c "$(curl -fsSL https://raw.githubusercontent.com/Ferdinand99/Vigilant-Vole/main/deploy/install.sh)"

No Docker needed: a static binary for x86_64 or aarch64, checksum-verified and run as a sandboxed systemd service on Debian, Ubuntu and friends. It asks whether to set up the server or a remote agent for another server. Add -- update to update. Linux guide

Proxmox VE

export COMMUNITY_SCRIPTS_URL=https://raw.githubusercontent.com/Ferdinand99/Vigilant-Vole/main/deploy/proxmox
bash -c "$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/ct/vigilant-vole.sh")"

Run it in the Proxmox VE shell. It creates an unprivileged Debian 13 container with Vigilant Vole inside, community-scripts style: the server, or a small remote agent container. Run update in the container to update.