Pulsebeat is a self-hosted uptime and health console for the services you care about. Watch HTTP, TCP, ping, and DNS targets from one place: a fast dark, glass-style UI, SSL/TLS insight for HTTPS checks, tags and filters, maintenance windows that silence alerts during planned work, and notification channels (including webhooks) so your team hears about incidents on your terms.
Run it at home, on a VPS, or in Docker — your data stays yours, in a SQLite database you control.
- Dashboard operations hub — Redesigned operational header, clickable status stat cards, stronger filtering, sortable table columns, and URL-synced list state for faster triage.
- Dashboard v1.13.1 polish — Degraded summary card and
filter=degradedURLs; Advanced filters → Paused monitors only (status=paused); eighteen-check Response trend sparklines with en-AU tooltips; status dots, stale when last check exceeds 1.5× interval, uptime good/warn/danger buckets, tag badges, and clearer DNS hostname display in the target column. - Inline actions that keep context — Pause/resume, force-check with inline progress/outcome states, incident deep-linking, and quick settings are all available from each monitor row.
- In-place monitor management — Add monitors in a focused modal (with advanced options) and quick-edit common settings without leaving the dashboard.
- Monitor detail — A persistent status header across Live, History, and Checks, with force-check from the page header and a canonical Checks tab that supports status filters, date-range queries, pagination, CSV export, and incident deep links into History.
- Monitor analytics — History uses a full-width stacked outcomes bar (with always-visible down segments and legend), plain-language incident durations with precise-seconds tooltips, and response-time charts tuned for faster outage triage.
- Dark-mode accessibility polish — Monitor detail table and chart down-state contrast has been refined to improve readability in low-light operational setups.
- SSL and config at a glance — Above-the-fold SSL / TLS health (with details toggle) sits beside a dedicated monitor config card.
- Managed hosts — Define named machines or environments under Settings → Hosts (with icon, colour, IP address, and description), then assign monitors to them for organised fleet management.
- Galaxy View — The Dashboard opens in galaxy mode by default: each host is a planet, its monitors orbit as moons, and sonar-ring pulses use the host's configured colour. Use
?view=tableto switch to the monitor table. Two toggle buttons sit between the stat cards and the view content; your choice persists in the URL and clicking a planet filters the table by that host. - Sidebar navigation — Improved account menu placement and behavior for both desktop and mobile views, with icon-only actions on collapsed desktop rail. Sidebar features glass effects and enhanced visual consistency across all device sizes.
- Alerts — Wire up Telegram, email, Discord, Slack, custom webhooks, and more.
- Maintenance — Schedule windows so checks still run but alerts stay quiet.
- Settings — Tune defaults, retention, SSL alerting, optional container/self-monitoring stats, and About metadata.
Access is password-protected with JWT sessions (httpOnly cookies); the same API can be used with Authorization: Bearer for automation.
The official image serves the web UI and REST API on port 4141 from a single process.
services:
pulsebeat:
image: replace_with_your_image_repo_and_tag
container_name: pulsebeat
restart: unless-stopped
mem_limit: 512m
ports:
- "4141:4141"
volumes:
- ./data:/app/data
environment:
NODE_ENV: production
PULSEBEAT_DATA_DIR: /app/data
PULSEBEAT_JWT_SECRET: `openssl rand -hex 32`
PULSEBEAT_ADMIN_PASSWORD: replace_with_my_password
PULSEBEAT_ADMIN_USER: replace_with_my_user
PULSEBEAT_ALLOWED_ORIGINS: https://pulsebeat.yourdomain.com,http://localhost:4141,http://localhost:5173-
Clone this repository (or use your own compose file pointing at the image).
-
Copy environment defaults:
cp .env.example .env -
Set at least
PULSEBEAT_JWT_SECRET(16+ characters). SetPULSEBEAT_ADMIN_PASSWORDif you want a known initialadminpassword; otherwise the first boot logs a one-off random password. -
Start:
docker compose up --build -d
-
Open http://localhost:4141, sign in, and add your first monitor.
Persistent data lives in ./data on the host by default (pulsebeat.db). The image supports linux/amd64 and linux/arm64 (for example Raspberry Pi).
If you want to keep Docker running and automatically rebuild on source changes:
docker compose up --build -d
docker compose watchdocker compose watch uses the develop.watch rules in docker-compose.yml and will rebuild/recreate the pulsebeat service when client/, server/, or build manifests change.
From the repository root:
npm install
npm run dev- UI (Vite): http://localhost:5173 — proxies
/apito the API (cookies are forwarded). - API: http://localhost:4141
Set PULSEBEAT_JWT_SECRET in .env (≥16 characters) for a stable secret. If you omit it in development, a built-in dev secret is used (not for production).
First run (no users yet): a default account is created:
- Username:
admin(override withPULSEBEAT_ADMIN_USER) - Password:
changemein development ifPULSEBEAT_ADMIN_PASSWORDis unset; in production, if unset, a random password is printed once in the server logs — or setPULSEBEAT_ADMIN_PASSWORDin.envexplicitly.
Production-style local run:
npm run build
npm run startThen open http://localhost:4141 and sign in.
If the browser origin and API origin differ, or you see Content-Security-Policy / connect-src issues, set PULSEBEAT_ALLOWED_ORIGINS to a comma-separated list of full origins (scheme + host, no path), e.g. https://pulsebeat.example.com. That feeds CSP connect-src and credentialed CORS for /api. If another layer injects a stricter CSP, adjust it there — Pulsebeat cannot override headers added in front of the app.
- Canonical changelog:
CHANGELOG.mdat the repo root. - Copies are synced to
client/public/andserver/when you runnpm run dev,npm run build, ornpm run sync-changelog. - For releases, bump
versionin the rootpackage.json,client/package.json, andserver/package.jsontogether, then add a new section toCHANGELOG.md.
See LICENSE.
If you find Aura useful, consider buying me a coffee.

