MIT-licensed · No Docker required

Self-hosted uptime monitor
built for small teams.

One Express + EJS app, SQLite (or MySQL), zero build step. Monitor HTTP, TCP, ICMP, DNS, TLS certificates, domain WHOIS / RDAP expiry, and passive heartbeats. Alert through 10 channels. Share monitors with per-monitor ACLs. A lightweight alternative to Uptime Kuma, Healthchecks.io, Gatus, Statping, and Better Stack.

MIT license Node.js 20+ SQLite · MySQL ~150 MB RAM
Self-hosted uptime monitor dashboard with monitor cards and dark mode
10
notification channels
7
monitor types
3
roles + per-monitor ACL
1
process · no Docker required

Everything a self-hosted team monitor needs

Probe anything you can reach, alert anywhere you operate, share with anyone on the team.

Cloudflare-aware probing

Detects Cloudflare challenges, records them as inconclusive instead of DOWN, adapts back-off, rotates realistic browser user-agents. The feature no other open-source uptime monitor ships out of the box.

7 monitor types

HTTP / HTTPS with regex, JSON-path, body-string, and status-code assertions. TCP, ICMP ping, DNS records, TLS cert expiry, domain WHOIS / RDAP expiry, and passive heartbeats (Healthchecks.io-style with start / success / fail pings and cron schedules).

10 notification channels

Discord, Slack, Telegram, Ntfy.sh, Gotify, Pushover, Mattermost, Microsoft Teams, SMTP email, generic webhook. Per-event message templates with placeholders and one-click reset-to-default.

Multi-user with per-monitor ACLs

Flat admin / editor / viewer roles layered with per-monitor view / manage grants. Argon2id password hashing, per-user TOTP 2FA, personal API tokens — all backed by an env super-admin break-glass account.

Public status page + RSS

/status route (token-gated optional) with 90-day daily uptime bars, ordered monitor groups, per-monitor display-name overrides, last-24h MTTR, and an Atom feed at /status.rss.

REST API + Prometheus

Token-authenticated /api/v1/* with read / write scopes — every endpoint ACL-filtered through the token owner. Built-in /metrics Prometheus exporter for Grafana, also ACL-aware.

Tags, bulk actions, live polling

Coloured tag chips, multi-select bulk toolbar (pause / resume / delete / add-tag / remove-tag), server-side pagination, full-text search, and 5-second live polling of just the visible cards.

Hardened auth

Per-user TOTP 2FA (RFC 6238) with 10 single-use recovery codes, in-memory rate-limit & lockout (5/15 min IP + 10/30 min username), full audit log per actor, and argon2id password hashing.

JSON backup / restore

Export all or a selected subset of monitors, channels, and SMTP settings to a portable JSON file. Restore on another instance with a configurable conflict strategy (skip / replace / rename).

Things no other open-source uptime monitor ships

Honest list. Uptime is a mature space — but these are real, falsifiable differences that solve real on-call pain.

01 Cloudflare-aware probing

Detects Cloudflare challenges via status, cf-mitigated header, and body markers. Marks them as inconclusive so a JS challenge never tanks your uptime % or fires a false-positive alert. Adaptive exponential back-off, rotated browser UAs, optional per-monitor HEAD-first "Cloudflare mode".

02 during_maintenance flag on incidents

Competitors silently suppress incidents during maintenance windows. We open the incident and flag it — so you can count "real" outages separately from ones you caused.

03 Mute, distinct from Pause

Keep the probes running and the history flowing, but suppress channel dispatches. Pause stops everything. Most monitors only have pause.

04 Per-token ACL filtering on API + metrics

API tokens inherit the creator's monitor visibility. The Prometheus /metrics exporter respects that too. Most exporters are flat admin-or-nothing.

05 Env super-admin + DB users side-by-side

.env credentials stay as a permanent break-glass account, always admin, with its own TOTP secret. DB users have their own. You can never lock yourself out.

06 Single-process, Docker-optional, SQLite default

Clone, npm install, npm start. That's the prerequisite list. Docker is available if you want it; nothing about the project assumes it.

07 Domain WHOIS / RDAP expiry as a first-class monitor

Catch a forgotten registrar renewal before the domain falls off the internet. The probe queries RDAP first via the IANA bootstrap registry (structured JSON), falls back to WHOIS over TCP/43 with multi-pattern parsing, stores expires_at / registrar / EPP status, and fires domain_expiring at 30/14/7/3/1/0-day bands — no nagging. Returns unknown for redacted TLDs instead of false-flagging DOWN. Uptime Kuma, Gatus, Statping, and Healthchecks all skip this.

Screenshots

Clean, dark-by-default UI. Vanilla JS — no Bootstrap JS bundle, no SPA.

Self-hosted uptime monitor dashboard with monitor cards and dark mode
Live dashboard — compact monitor cards, 5s polling, full-text search.
Monitor detail page with response-time chart, uptime stats, and incidents
Monitor detail — 24h / 7d / 30d charts, P95, incident timeline.
Per-monitor sharing grants with view / manage permissions
Per-monitor sharing — owners hand out view or manage grants.
Notification channels: Discord, Slack, Telegram, Ntfy, Gotify, Pushover, Mattermost, Teams, email, webhook
10 notification channels, attach any number per monitor.
Notification message templates with placeholder palette
Customisable per-event templates with one-click placeholder insertion.
New monitor form with assertions, headers, tags
Monitor form — status / regex / JSON-path / body assertions.
Advanced HTTP monitor options: auth, body, redirects, TLS verify
Advanced probe options — auth, body, redirects, skip-TLS-verify.
Public status page with 90-day uptime bars
Public status page — 90-day bars, grouped monitors, RSS feed.
Admin users and roles management
Users & roles admin — argon2id passwords, per-user 2FA.
Per-user, per-monitor access control grants: none, view, manage
Per-monitor ACL grants — bulk none / view / manage.
Personal account page: profile, password, 2FA, recovery codes, API tokens
My account — profile, password, 2FA, recovery codes, API tokens.
Audit log with action filter dropdown and JSON metadata
Audit log — every action, actor, IP, target, JSON meta.
Backup and restore configuration JSON import / export
Backup & restore — selective JSON export with conflict strategy.
Uptime monitor dashboard filters
Filters — by state, type, Cloudflare mode, and tag.
Bulk pause, resume, delete, tag actions
Bulk actions toolbar — pause / resume / delete / tag, sticky.

Compared to other uptime monitors

Picked carefully. We don't try to out-feature Uptime Kuma; we make a different trade-off.

Uptime this Uptime Kuma Healthchecks.io Gatus Statping-ng Better Stack
License MIT MIT BSD-3 Apache-2Apache-2Proprietary
Self-hosted Yes Yes Yes Yes Yes No (SaaS)
Runs without Docker Yes (1 process) Yes Yes Yes Yes
HTTP / TCP / Ping / DNS / Cert All five Most HTTP only (passive) MostHTTP / TCPAll five
Domain WHOIS / RDAP expiry Dedicated type (RDAP→WHOIS)NoNo No No Basic
Heartbeats with cron + body capture Yes Basic Best in class No No Yes
Cloudflare-aware probing Yes No No No No
Notification channels 10 90+ 30+ Via shoutrrr1320+
Public status page + RSS Yes Yes No Yes Yes Yes
Multi-user with per-monitor ACLs Yes Coming Teams only No Limited Yes
REST API + Prometheus exporter Both (ACL-filtered)LimitedAPI onlyRead-onlyAPI onlyAPI only
Audit log per actor Yes No No No No Yes
Login rate-limit + lockout Yes No Yes No No Yes
Dark mode by default Yes Yes Yes No No Yes
Footprint ~150 MB · 1 process~100 MB~200 MB~30 MB~80 MB

Compared as of May 2026 against publicly documented features. PRs welcome if anything's out of date.

Quick start

Three minutes from git clone to a live dashboard.

1 Clone & install

git clone https://github.com/codewizdevs/uptime.git
cd uptime
npm install
cp .env.example .env

2 Edit .env

SESSION_SECRET=$(openssl rand -hex 48)
ADMIN_USER=admin
ADMIN_PASS=<something strong>
DB_DRIVER=sqlite    # or mysql

3 Start it

npm start
# or for production
pm2 start src/server.js --name uptime
pm2 save

Open http://localhost:3000 and sign in. The schema auto-applies on first boot — no migration step. Need more? See the PM2 + nginx and Docker guides on GitHub.

Stack

Boring on purpose. Easy to read, easy to fork, easy to deploy.

RuntimeNode.js 20+
ServerExpress 4 + EJS
HTTP clientundici (HTTP/2, brotli)
Databasebetter-sqlite3 or mysql2
Sessionsexpress-session
Passwordsargon2 (argon2id)
Mailnodemailer
FrontendTabler CSS + vanilla JS
ChartsChart.js
Logspino + rolling file
Process mgrPM2 (optional)
ContainerDocker / compose (optional)

Built & maintained by CodeWiz

CodeWiz is a full-stack development agency specializing in custom web development, AI/ML integration, DevOps, and modern web technologies. We build, ship, and operate self-hosted infrastructure for small teams and bootstrapped products — and we open-source the parts we'd want to use ourselves.

Need this deployed for you, a custom integration, or a private fork with company-specific channels and SSO? Get in touch.

Contact

Web Dev AI / ML DevOps Node.js Laravel React