Pip (SQLite)
LightestFor Solo developers, homelab, local dev, bare-metal servers, CI
Pure Python. No container runtime required.
What runs: 1 process
z4j ships one image for the brain. Backend and dashboard are bundled. There is no separate frontend container.
One Python process
z4j-brain serves the FastAPI API, the WebSocket agent gateway, and the React dashboard from a single process. SQLite lives on local disk.
Get running in minutes
# Install the brain + umbrella (dashboard, backend, SQLite, all bundled)
pip install z4j
# Start it. First boot auto-mints HMAC secrets, runs migrations, and prints
# a one-time setup URL to stderr. Open the URL to create the first admin.
# z4j auto-detects the server's hostname, FQDN, and LAN IPs - so you can
# reach the dashboard via any of them out of the box.
z4j serve
# Then open http://<your-server>:7700 in your browser.
# Adding a public domain (e.g. tasks.example.com pointed via reverse proxy):
z4j allowed-hosts add tasks.example.com # persisted to ~/.z4j/allowed-hosts
z4j allowed-hosts list # show what's whitelisted
z4j allowed-hosts remove old-host.example # idempotent
# Restart z4j serve to pick up changes.
# Useful CLI commands (z4j and z4j-brain are aliases - same entry point):
z4j check # config + DB + migrations at head
z4j status # version, DB URL, user/project/agent counts
z4j createsuperuser # provision an admin without the setup URL
z4j changepassword # reset a user password
z4j migrate upgrade head # run alembic migrations explicitly
z4j audit verify # verify the HMAC-chained audit log
z4j reset-setup # mint a fresh setup URL (e.g. expired token)
After the brain is running, open http://localhost:7700 and sign in.
Confirm everything is wired up
Each framework adapter ships a `doctor` command that probes brain reachability, TLS, WebSocket upgrade, and the on-disk buffer path. Run it as the same user the service runs under.
Django
python manage.py z4j_doctor Flask
python -m z4j_flask doctor FastAPI
python -m z4j_fastapi doctor Bare / Celery / RQ / etc.
python -m z4j_bare doctor
Exits 0 on all-green, 1 on any failure. Add --no-websocket to skip the WS round-trip, --json for scripts. Catches the common www-data-can't-write-$HOME startup failure (the agent now auto-relocates the buffer to $TMPDIR/z4j-{uid} and logs a single WARNING). See service-user deployments.
Reach the brain via any name you want
The brain validates the HTTP `Host:` header on every request to defend against cache-poisoning. Auto-detect handles the common cases; the `z4j allowed-hosts` CLI handles the rest.
What's auto-allowed (no config)
localhost,127.0.0.1,[::1]- The system hostname + FQDN (incl. Tailscale's
<host>.<tailnet>.ts.net) - Every LAN IP bound on the host (covers
192.168.x.x, Docker bridges, Tailscale)
Adding a custom domain (one-time, persisted)
For a public DNS name (reverse proxy, Cloudflare Tunnel, internal LB), persist it once via the CLI:
z4j allowed-hosts add tasks.example.com
z4j allowed-hosts list # show current set
z4j allowed-hosts remove old.example # idempotent
z4j allowed-hosts path # ~/.z4j/allowed-hosts
# Restart `z4j serve` to pick up the change. Precedence (highest first)
Z4J_ALLOWED_HOSTSenv - pins the list, replaces auto-detect--allowed-hostCLI flag - additive, repeatable~/.z4j/allowed-hostsfile - persistent, additive- Auto-detect - localhost + hostname + FQDN + LAN IPs
Security
Rejected requests get a generic 400 in production mode (no internal hostname leakage). Dev mode shows a verbose response with the rejected host and a fix command. Operators always get the verbose detail in the server log via request_id correlation.
Requirements
- Python 3.11 or newer
- No Docker, no Redis, no broker required
- Writes to ~/.z4j/z4j.db (SQLite)
SQLite (auto-created at ~/.z4j/z4j.db)
Up to ~10 agents, ~1k events/minute, single-host deployment
Is this the right tier for you?
Use this when
- Running z4j on a Raspberry Pi or homelab NUC
- Evaluating z4j locally before committing to a container
- CI jobs that need a task dashboard ephemerally
- Air-gapped Python environments where Docker is not permitted
Not ideal when
- Multiple concurrent admins (SQLite is single-writer)
- High event throughput (>1k events/minute sustained)
- Teams with heterogeneous hosts and OS versions
Capabilities in this tier
- All 6 engines supported
- All 3 framework adapters
- Full dashboard UI
- RBAC and audit log
- HMAC wire protocol
- Multi-writer scale-out
- Horizontal brain replicas
How to move up a tier
Switch to z4j (Docker) or z4j + Postgres by graduating to the Docker compose presets. Your data, users, and schedules all migrate over.
Works with every engine and framework
Framework adapters
Django
Django AppConfig integration, zero boilerplate.
Learn more
Flask
Flask extension pattern. One line to install.
Learn more
FastAPI
Lifespan-hook integration for async stacks.
Learn moreEngine adapters
Celery
The industry standard, covered end-to-end.
Learn more
RQ
Lightweight Redis queue, fully instrumented.
Learn more
Dramatiq
Middleware-driven Dramatiq observability.
Learn more
Huey
Lightweight Redis/SQLite queue, first-class.
Learn more
arq
Async Redis queue for FastAPI-era Python.
Learn more
taskiq
Broker-agnostic async task framework.
Learn moreCompare with
Ready to run z4j with Pip (SQLite)?
Copy the install command above, run it, and open the dashboard on port 7700.