Pulsy
Self-hosting

Run Pulsy on your own infrastructure

Pulsy is a small Docker stack: Postgres, a Node server that also runs the check scheduler, and nginx serving the built SPA. Bring it up with four commands, point it at your domain, and every capability is on — no licence key, no tiers, no phone-home.

What you need

Modest. Pulsy runs comfortably on the smallest VPS most providers sell.

  • A Linux host with Docker and the Compose plugin installed.
  • About 1 GB of RAM and a little disk for Postgres — check history is the only thing that grows.
  • A domain name, and a TLS-terminating reverse proxy in front for production.
  • Outbound network access, so the checker can reach the endpoints you monitor.

Quickstart

From a clean host to a running instance.

# 1. Clone the repository and create your environment file
git clone https://github.com/SelmiAbderrahim/pulsy.org.git pulsy && cd pulsy
cp .env.example .env

# 2. Generate the two required secrets and paste them into .env
openssl rand -base64 32   # -> ENCRYPTION_KEY
openssl rand -base64 32   # -> BETTER_AUTH_SECRET

# 3. Start the full stack (postgres + server + web)
#    The server applies the database schema on startup.
make start

# 4. Seed a demo user and two example monitors
make seed

Open http://localhost:3000 and sign in with the seeded demo account. Tail logs with `make logs`; stop everything with `make stop`. The server applies the database schema on startup, so there is no separate migration step for a fresh install.

Environment variables

All configuration lives in a single root `.env`, copied from `.env.example`.

Environment variables
VariableRequirementPurpose
ENCRYPTION_KEYRequiredAES-256-GCM key protecting email-provider credentials at rest. Generate with `openssl rand -base64 32`.
BETTER_AUTH_SECRETRequiredSigns session cookies. Generate the same way, and keep it distinct from the encryption key.
PUBLIC_SERVER_URLRequiredThe public address of the API server. Used for links and callbacks.
PUBLIC_WEB_URLRequiredThe public address of the web app. Also the canonical origin for SEO and status pages.
BETTER_AUTH_URLRequiredThe origin better-auth issues and validates sessions against.
RESEND_API_KEYOptionalSet it, with `EMAIL_FROM`, to actually send verification and password-reset mail. Left unset, the server logs email metadata only and omits bodies, because they can contain reset tokens.

Rotating ENCRYPTION_KEY makes any already-encrypted provider secrets unrecoverable. Set it once, back it up, and treat it like a database password.

What actually runs

Three containers on one host. No queue, no external services, nothing to sign up for.

  • pulsy-postgres

    The datastore. Monitors, check logs, incidents, and status-page configuration all live here — this is the only container holding state, so it is the only one you need to back up.

  • pulsy-server

    The tRPC API, the better-auth handler, and the node-schedule check scheduler. The scheduler runs inside this process, so monitors are checked for exactly as long as this container is up.

  • pulsy-web

    The built React SPA served by nginx, which proxies /api/* to the server so the browser stays same-origin and session cookies just work.

Day two

Upgrading

Pull and restart. The server runs an idempotent schema push on startup, so a version bump does not need a manual migration step. Read the changelog first if you are skipping several releases.

git pull
make start   # rebuilds the images and re-applies the schema

Backups

Postgres holds everything that matters. Dump it on whatever schedule your check history is worth, and store the dump off the host — alongside your ENCRYPTION_KEY, without which encrypted provider secrets in that dump cannot be read.

docker compose -f docker/docker-compose.yml --env-file .env \
  exec postgres pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB" > pulsy-backup.sql

Frequently asked questions

Is self-hosted Pulsy limited compared to Pulsy Cloud?
No. The self-hosted build has no tiers, no feature flags gating capabilities, and no monitor limit. Every notification channel, status pages with custom domains, TLS-expiry alerting, incident tracking, and the full API are all on. Pulsy Cloud runs the same code; what you pay for there is that someone else operates it.
Do I need a licence key or an account to self-host?
No. There is no key, no activation, and no phone-home. Clone, configure, and run — the software never contacts pulsy.org.
How much does it cost to run?
Whatever your host costs. Pulsy itself is free forever under AGPL-3.0. The stack fits on a small VPS; the only thing that grows over time is Postgres, and check-log retention is configurable.
Can I move from Pulsy Cloud to self-hosted later, or the other way?
Yes, in both directions. It is the same software, so nothing is stranded by the move. Cloud data is exportable at any time.
Where do checks run from when I self-host?
From wherever you deploy Pulsy. That is an advantage for monitoring internal or firewalled endpoints a hosted service cannot reach, and a limitation if you want multi-region vantage points — for that, deploy more than one instance.

Start monitoring in minutes

Fully-managed uptime monitoring — every channel, status pages, and TLS-expiry alerts included. Start free.