Self-Hosting
Run your own Pulsync server. Devices speak the same protocol either way — they can’t tell hosted from self-hosted.
The self-hosted server is fully self-contained: SQLite for storage and an in-process MQTT broker, so there’s no external database or broker to set up. It gives you device enrollment, telemetry, commands, remote config, OTA firmware hosting, a local dashboard, and mDNS discovery (pulsync.local).
Requirements
- Node.js 20+
- Build tools for the native
better-sqlite3module (Xcode Command Line Tools on macOS,build-essentialon Debian/Ubuntu). Prebuilt binaries cover most setups, so you usually won’t need to compile anything.
Run with Node
git clone https://github.com/Pulsync/pulsync-server.git
cd pulsync-server
npm install
npm start That’s it — SQLite + embedded MQTT, no external services. Open the dashboard at http://localhost:3456/. On the LAN the server also advertises itself as pulsync.local, so devices can find it by name.
Run with Docker (optional)
Docker isn’t required, but a Compose file is included if you prefer a containerized deploy:
git clone https://github.com/Pulsync/pulsync-server.git
cd pulsync-server
docker compose up Same single self-contained service (SQLite + embedded MQTT), exposing HTTP on 3456 and MQTT on 1883, with volumes for the database and firmware.
Point a device at it
Pulsync.setServer("pulsync.local:3456"); // by mDNS name (recommended)
Pulsync.setServer("http://192.168.1.50:3456"); // by IP Or set nothing — the library auto-discovers a local server on the LAN. See Connectivity.
Configuration
Everything is optional and set via environment variables (see .env.example):
| Variable | Default | Purpose |
|---|---|---|
PORT | 3456 | HTTP port (dashboard + device API) |
MQTT_PORT | 1883 | Embedded MQTT broker port |
DATABASE_URL | (unset → SQLite) | Set a postgresql:// URL to use Postgres instead |
ADMIN_PASSWORD | (empty → open) | Password gate for the dashboard + management routes |
JWT_SECRET | (random per run) | Signs admin sessions; set a stable value to persist them |
Security notes
ADMIN_PASSWORDgates the dashboard and management routes. It’s open by default, which is fine on a trusted LAN — set it if the dashboard is reachable beyond your network. Device-facing routes stay open; devices authenticate with their own token.JWT_SECRETsigns admin session cookies. Leave it unset and a random key is used (sessions reset on restart); set a long random value (openssl rand -hex 32) to keep sessions stable.- The dashboard runs over plain HTTP for LAN use. Put it behind a TLS reverse proxy if you expose it publicly.