Self-hosted · multi-tenant · MSP-ready

Monitoring that reaches everywhere,
owned entirely by you.

Project Pulse is a self-hosted, multi-tenant infrastructure & network monitoring platform in the spirit of PRTG and CheckMK — remote probes, host agents, auto-discovery, and SLA-driven alerting, built for MSPs and homelabs alike.

🚧 Not public yet. Pulse is in active development — the public release and source repository will be announced later. Watch this space. ✨
✨ Public release — announced soon Explore the features

What it is

One console for every site, tenant, and device

Pulse watches servers, network gear, and services across many customers and locations from a single pane of glass. Probes sit inside each network and dial home over an encrypted, outbound-only channel — nothing needs to be exposed to the internet. Metrics stream to a fast time-series store, and an SLA-aware engine turns problems into the right alert, to the right person, at the right time.

Core
API · web UI · alert engine
Probes
outbound gRPC over mTLS
Agents
host self-metrics
Metrics
VictoriaMetrics TSDB
ASP.NET Core 10 React 18 + TypeScript EF Core · SQL Server & PostgreSQL gRPC + mTLS internal CA VictoriaMetrics .NET self-contained probes Argon2id · TOTP 2FA
832
commits
~216k
lines of code
112
sensor types
5,488
automated tests

Designed & built in pair-programming with Claude. Counted on 25 August 2026 — lines of code is hand-written C#/TypeScript across 1,106 files, excluding generated database migrations; tests are xUnit facts plus theory cases.

Status

What's built vs. what's coming

Pulse is under active, fast-moving development. Everything in the left column runs today; the right column is what's queued next. Honest and up to date.

Implemented

  • Multi-tenant from day one. Per-tenant isolation enforced at the query layer; MSP customer → department → zone hierarchy. An "All customers" estate view spans every client in one dashboard, monitoring list and alert list — reads and writes, with an explicit owning-customer picker so nothing lands on the wrong invoice.
  • Outbound-only probes. .NET 10 self-contained agents dial Core over gRPC/mTLS via an internal CA; SQLite offline buffer replays after outages. Certs auto-renew and probes self-update from Core — no inbound download.
  • Host agents. Cross-platform CPU / memory / disk / uptime self-metrics with auto-provisioned devices.
  • 112 sensor types. Ping, TCP, HTTP(S)/JSON, TLS-cert expiry, DNS, scripts (PowerShell & Bash); a full SNMP family (v1 / v2c / v3 USM); WMI (service, CPU, memory, disk, perf-counter, event log) and SSH for agentless Windows & Linux; virtualization — Proxmox VE, VMware and Hyper-V (hosts, guests, clusters, datastores, replication); containers — Docker and Kubernetes; databases, mail round-trip (SMTP/IMAP/POP3), file / folder / FTP / SMB, a syslog receiver, and FortiGate & OPNsense packs. All with typed, per-sensor settings forms. The disk family also ships a roll-upsnmp-disk, ssh-disk and wmi-disk grade every volume as channels of one sensor, under a shared channel cap so a roll-up cannot truncate silently.
  • Containers, past "is it running". A Docker container is graded on CPU as a true delta, memory against its own limit with page cache excluded, network and block I/O, PIDs, uptime, its healthcheck verdict and its restart count — so a container that is up but pinned at 100%, OOM-restarting and failing its own healthcheck no longer reads green. Beside it: image freshness, volumes, Swarm services, Compose stacks, registry reachability and the daemon's event stream, one sensor per concern so thresholds and alert routing stay separate.
  • Hardware health. Broken RAM / fan / PSU / voltage / temperature via Redfish/BMC (iDRAC / iLO / XCC, out-of-band, any OS), and physical-disk SMART health over SSH (smartctl) or Windows (Storage) for hosts without a BMC.
  • The gear under the rack, too. UPS via the standard RFC 1628 UPS-MIB — one sensor for APC, Eaton, Vertiv, Riello and most others rather than a vendor tree — plus PDU load judged against the breaker's rating, two-sided environmental sensors (a room that is too cold is also a fault), FC switches, Synology NAS and NetApp ONTAP with zero spares graded rather than only failed disks. (Newest family: written to the published MIBs and vendor APIs and unit-tested against captured responses — not yet run against real UPS or SAN hardware.)
  • PRTG-style channels & computed sensors. Per-channel display, scaling, decimals, colours, spike filter, and upper/lower warning & error limits that drive sensor state through the retry gate — plus Sensor Factory formulas and business-process rollups computed from other sensors.
  • Network auto-discovery & topology maps. CheckMK-style subnet sweep + port fingerprint, suggested sensors, one-click approve, scheduled re-scans with optional unattended auto-add, and deep SNMP/WMI fingerprinting. Pulse also logs into switches and routers over SNMP (CDP/LLDP, ARP and interface tables) to auto-draw the network map and overlay what it monitors. Adding a sensor asks the device rather than asking you — pick the disk, interface, service, datastore or container from a list the probe just read off the target, instead of typing an identifier and finding out it was wrong at the first reading.
  • SLA-driven alerting. SLA tiers, multi-level dependency suppression, retry gating, an N-rung escalation ladder whose acknowledgements expire rather than muting an alert for ever, and Email / SMS / Webhook / Slack / Teams / Discord / Telegram / PagerDuty / Syslog (RFC 5424) / Graylog GELF / browser push channels with state & threshold triggers, inheritable notification templates, and per-recipient delivery reports.
  • One unreachable host, one alert. A device's ping is automatically the parent of that device's other sensors, so a dead host pages once instead of forty times — nothing to configure, and nothing written to your existing dependency tree. A multi-homed device suppresses only when both pings are down; a device with no ping suppresses nothing; an explicitly chosen parent still wins. The sensor page says why it is muted, which ping is muting it, and which level decided. Suppressed time is recorded as paused rather than down, so availability figures move the first month you enable it — deliberately, and said out loud.
  • Alerting that survives its own transport failing. Ordered groups of SMTP servers and SMS gateways with automatic failover, judged by a circuit breaker on real send results — not a port check. An accepted SMS that never reports delivery counts against its gateway, and a failover is announced on a different transport, because "email is down" sent by email is the one message that never arrives.
  • "Unusual" detection. Per-sensor baselines by hour-of-day, so a value that is normal at 09:00 and alarming at 03:00 is treated as such — with an inheritable tolerance you can override per device or per sensor.
  • AI-assisted root cause, and an in-app assistant. Bring-your-own LLM (OpenAI / Azure OpenAI / Anthropic / Gemini / local Ollama) explains why a sensor failed from correlated context, remembers confirmed fixes per sensor type, and answers follow-up questions in the same thread. A grounded assistant answers questions about your own estate through your own permissions. Opt-in per tenant, redacted, default off, with a per-tenant token budget.
  • Time-series metrics. Readings stream to VictoriaMetrics; per-sensor history graphs, and estate-wide trends aggregated across every customer with the per-customer breakdown beside the total.
  • Serious auth. Argon2id hashing, mandatory TOTP 2FA, breached-password checks (HIBP), login rate-limiting, permission-based RBAC.
  • Directory sign-in, multi-tenant. Entra ID with a directory per customer and one for the MSP, matched on the token's own directory id rather than an e-mail domain — authorization-code flow with PKCE, accounts matched or provisioned per directory, and the local break-glass administrator deliberately excluded. Active Directory over LDAPS signs people in too, and in both cases directory groups decide the Pulse role — matched on group id or name, so joining a group is the whole onboarding step.
  • Operations UI. Dashboard, monitoring tree, alerts, sensor detail, network map, reports, customers, users, audit log, a built-in knowledge base, a NOC wallboard, and an "Advanced" expander on every tunable. The dashboard is arranged per user; Ctrl-K opens a command palette over every setting, tab and named object, and the two hundred-odd tunables are searchable by name, key or description. White-label branding and your own logo.
  • System-information inventory. Per-device hardware/OS inventory — CPU/RAM, BIOS/serial, IP addresses & MACs, disks, installed software — collected via agent / WMI / SSH / SNMP, PRTG-style. Plus traceroute from the probe, stored and diffed so a changed path is visible.
  • Cross-customer device moves. Relocate a device (and its history) to another customer with automatic probe re-assignment.
  • Installers for both platforms. A self-elevating Windows wizard, and a one-command Linux Core installer — system account, layout, systemd unit, starter config and TLS in one go, with an --upgrade that keeps the environment you added rather than overwriting it. Services run least-privilege by default. Dual DB providers, DevCert / PFX / Let's Encrypt TLS. Probe and load-balancer appliance images build from source on Ubuntu 26.04 LTS.
  • A cluster you can perform maintenance on. Multi-node Core with leader election, so scheduled work runs exactly once — and an admin page that shows the roster, each node's build, who leads, where every probe is attached, and the cluster-wide faults no single node can see (split builds, a pending schema, an unshared key ring). Drain a node rather than stopping it and hoping: readiness drops at once, leadership is released, probes and each zone's runner lease move to the peer — four real drains in the lab, not one probe offline. Apply a pending database migration from the page, under a lease so two operators get one migration and one clear refusal. The front door keeps answering while the schema is behind, so the button that repairs it is reachable at the only address anyone dials.
  • A certificate lifecycle you can finish. Rotating a private CA is where most self-hosted deployments get stuck. Pulse rotates its own as a supervised operation — issue a standby, distribute it to every probe, wait for each one to confirm, activate only then; if a single probe cannot confirm, the standby is deleted and nothing changed. Old roots retire one at a time with rollback, a probe or agent can be re-keyed on demand instead of waiting out a 397-day certificate, and what a locked-down appliance trusts is changed over the connection it already holds — no SSH. Each probe's page states its real trust position (anchored, pinned, or a bundle that only looks valid), and a trust file Pulse can read but openssl cannot is reported and then repaired in place. The web front door takes its certificate from the same CA, renewed 30 days out, with the private key never leaving the balancer.
  • Audit & settings. Append-only audit trail of config changes; a settings registry so nothing is hardcoded, overridable per customer. English + Danish.
  • Production-ready deploy. Single process serving the UI + API over one TLS origin, its own HTTP→HTTPS redirect and HSTS, and a break-glass CLI recovery command — no reverse proxy required. Pulse monitors itself under a reserved customer of its own.
  • Central credentials & device management. Encrypted credentials set once on a customer and inherited down to departments, zones & devices (sensors authenticate automatically); a Devices tab, device detail/edit, and typed custom fields.
  • Auto-remediation, carefully. Attempt the fix, not just the report — from a fixed catalogue of typed actions compiled into the probe and bound to a sensor type. Core's message carries no parameter at all: it names a sensor and an action, and the probe derives the target from that sensor's own configuration, so a compromised Core cannot name a service to restart. Suggest / Ask / Auto per scope, behind guard rails — attempts per day, consecutive failures, a blast-radius limit that refuses to act during an infrastructure event, business hours in the customer's own time zone, and maintenance windows. Every refusal is recorded with the rail that caused it. The AI may only select from the catalogue and explain why; it can never author an action.
  • Per-customer onboarding scripts. Generated Windows and Linux scripts that open exactly one customer's estate to monitoring — derived from the sensors that customer actually has, so no Windows sensors means no WinRM rule and no service account. That customer's real probe addresses, only the ports their sensor types need, least-privilege accounts, an idempotent matching undo, and a drift view that separates "the firewall is now blocking something" from "something is still open that nothing uses".
  • Incident resolutions as memory. Record what the technician actually did when a sensor recovers, and retrieve it the next time the same thing fails the same way — so the third engineer to meet a problem doesn't start where the first did.
  • Installer generation & appliances. Downloadable per-OS probe installers, and a ready-to-run appliance image that Core keeps patched — including operator-initiated LTS release upgrades — with a fleet-health view, staged rollouts, a fleet-wide update pause and rollback. Installers check the host's prerequisites before they touch anything, and a self-update refuses rather than swapping a build the host cannot run.
  • Maintenance windows & RMM patch awareness. Scheduled suppression (one-off or recurring) at any level — customer, site, zone, device or sensor. Alerts mute during planned work while metrics keep recording. NinjaOne and Automox integrations read the patch schedule and suppress devices while they are being updated.
  • Agents answer a probe’s questions from inside the host. Not the same sensor types — the same information. A service, event log, performance counter, application pool or disk’s SMART health checked locally, with no credential, no WinRM listener and no network hop, which removes most of what makes agentless Windows monitoring fragile. The family deliberately carries no HTTP or TCP check: an agent on every host that Core could aim at an arbitrary address would be a network prober under another name.
  • The front door is monitored, not assumed. The load balancer installs from an appliance image or onto a server you already have, and is then registered and watched like anything else — its certificate checked by opening the socket, and how many backends are still behind it read from HAProxy’s own stats by the agent on the box. A front end that still answers while the last backend is gone is the outage that looks like uptime, and that is the one this closes. Maintenance and drain are not graded as faults, because a rolling upgrade puts each node into one by design.
  • NetBox, both directions. Import the inventory somebody already maintains — devices, sites, roles, platforms and addresses — on a schedule that is allowed to refuse rather than half-apply, and that recognises its own previous run instead of duplicating it. Then write back what only monitoring knows: devices, switch ports and the cables discovery found. Pulse’s own placeholders are never laundered into NetBox as facts, and provenance is recorded so you can tell which system asserted what.
  • Upgrades you can undo. Pulse backs up its own database on a schedule and refuses an upgrade that has no recent backup. Release artifacts are signed and the signature is verified on the machine about to run them; Core fetches and checks its own release, and a one-click upgrade crosses the privilege boundary without an SSH session — with rollback, on Windows and Linux both. The Core appliance ships as one image that boots on BIOS and on UEFI.
  • Pulse ships its own logs. Core’s diagnostic log goes to syslog or Graylog alongside the alert channels, so the monitoring system lands in the same place you already read everything else — rather than being the one box whose logs live only on its own disk.

In the pipeline

  • Flow monitoring. NetFlow / sFlow / IPFIX collection with top-talker and top-protocol breakdowns — the last big PRTG sensor family Pulse doesn’t cover.
  • Cloud & vendor packs. Azure, Microsoft 365 and AWS service health alongside the on-premise catalogue. Ranked by what they cost you to onboard rather than by what they cost us to build: Meraki is one API key, while Azure wants an RBAC assignment per subscription and AWS an IAM principal per account and region — a support conversation before a single channel appears.
  • Geo maps. Sites plotted on a world map, beside the floor-plan canvas that already ships. Held deliberately, and not for effort: a site carries no coordinates yet, and where the tiles come from is a real decision — a hosted provider means every wallboard in every customer makes third-party requests from an on-premise monitoring system, which is exactly what an air-gapped install cannot have.
  • Public read-only map links. A map is visible to signed-in users of its customer today. An unauthenticated token URL for a reception screen needs a decision about what a leaked link exposes before it needs any code.
  • A native mobile app. Browser push already ships end to end — VAPID, subscriptions, a real notification channel kind. A native app is not started.
Built in the open, AI-assisted. Pulse is proudly "vibe-coded" — designed and implemented rapidly in pair-programming sessions with Anthropic's Claude (Opus). The architecture is deliberate and reviewed; the velocity is the fun part. Expect rapid iteration, honest status, and a real feature set rather than a slide deck.

Principles

Why build another monitoring tool?

Yours, end to end

Self-hosted with no phone-home. Probes are outbound-only; nothing about your network is exposed.

Made for MSPs

True multi-tenancy: customers, departments, zones, and per-tenant roles — one deployment, many clients.

Discovers for you

Point it at a subnet and it finds hosts, fingerprints them, and suggests the right sensors.

Database freedom

First-class SQL Server and PostgreSQL. No provider lock-in, ever.

Fast metrics

Time-series in VictoriaMetrics — never bloating your relational database.

Alerts that make sense

SLA tiers, dependency suppression, and escalation so you're paged for causes, not symptoms.

Source & public release — announced later ✨