Skip to main content

Install z4j.

Three deployment paths, one platform. Whether you run a homelab Raspberry Pi or a production Kubernetes cluster, the z4j feature set ships in every tier.

Lightest

Pure Python (pip)

One pip install. No Docker. No container runtime.

Best for

Solo developers, homelab, local dev, bare-metal servers, CI

Homelab Solo developer
Default

z4j

One container. Bundled SQLite. Zero required env vars.

Best for

Homelab, small teams, evaluation, proof-of-concept

Homelab Small team Evaluation
Production

z4j + Postgres

Two services. Same image. Horizontal-scale ready.

Best for

Medium and larger businesses, regulated environments, compliance-sensitive teams

Small business Medium business Enterprise
Side by side

Compare the three paths

Capability Pure Python (pip)z4jz4j + Postgres
Container runtime required None (pure Python) Docker Docker + Postgres
Database SQLite SQLite (persisted volume) PostgreSQL 17+
Services to run 1 process 1 container 2 containers
Agent count ~10 ~50 1000+
Events per minute ~1k ~5k 300k+
Horizontal scaling
Full-text search
Range-partitioned events
Auto-migrations
Auto-generated secrets
Compliance-friendly (Postgres)
Lightest

Pure Python (pip)

One pip install. No Docker. No container runtime.

Install command

bash
# Install the brain (dashboard and backend bundled, SQLite by default)
pip install z4j-brain

# Boot with an admin account. Auto-runs migrations, generates secrets.
z4j-brain serve \
  --admin-email you@example.com \
  --admin-password change-me

What runs

1

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.

Requirements

  • Python 3.13 or newer
  • No Docker, no Redis, no broker required
  • Writes to ~/.z4j/z4j.db (SQLite)
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
Database
SQLite (auto-created at ~/.z4j/z4j.db)
Scale envelope
Up to ~10 agents, ~1k events/minute, single-host deployment
Default

z4j

One container. Bundled SQLite. Zero required env vars.

Install command

bash
# The default. One file. docker compose up.
# No secrets to set, no Postgres, no broker. It just works.
docker compose up -d

# Tail logs for the first-boot admin setup URL.
docker compose logs -f z4j-brain

# Or skip the interactive setup with env vars in .env:
#   Z4J_BOOTSTRAP_ADMIN_EMAIL=you@example.com
#   Z4J_BOOTSTRAP_ADMIN_PASSWORD=change-me

What runs

1

z4j-brain

z4jdev/z4j:latest

One image. Bundles the FastAPI backend, the React dashboard, and the SQLite driver. Auto-generates secrets on first boot, persists them to the z4j_data volume, auto-runs migrations. Exposes port 7700.

Requirements

  • Docker 20.10 or newer
  • Port 7700 bound to localhost by default (reverse-proxy for public access)
  • Persistent volume for SQLite database and persisted secrets
Use this when
  • First-time evaluation: clone the repo, docker compose up, done
  • Internal tools for a team of 2 to 20 developers
  • Homelab Docker Compose stacks (Synology, Unraid, TrueNAS)
  • Customer demos and sales engineering POCs
  • Single-instance production where ops simplicity wins over scale
Database
SQLite, stored in the z4j_data named volume
Scale envelope
Up to ~50 agents, ~5k events/minute, single container deployment
Production

z4j + Postgres

Two services. Same image. Horizontal-scale ready.

Install command

bash
# Two services. The z4j-brain image is the SAME one from the default
# compose file; it auto-switches to Postgres because Z4J_DATABASE_URL
# is set. No separate image, no custom build.

# Set your secrets in .env first:
#   POSTGRES_PASSWORD=<long random>
#   Z4J_SECRET=<openssl rand -hex 48>
#   Z4J_SESSION_SECRET=<openssl rand -hex 48>
#   Z4J_PUBLIC_URL=https://z4j.yourdomain.com
#   Z4J_ALLOWED_HOSTS=["z4j.yourdomain.com"]

docker compose -f docker-compose.postgres.yml up -d --build

# First-boot admin URL is in the brain logs.
docker compose -f docker-compose.postgres.yml logs -f z4j-brain

What runs

1

z4j-brain

z4jdev/z4j:latest

Same image as the default. Bundles backend plus dashboard. Connects to external Postgres via Z4J_DATABASE_URL.

2

z4j-postgres

postgres:18-trixie

Your primary datastore. Holds events, tasks, schedules, users, HMAC-chained audit log, and partitioned event history.

Requirements

  • Docker Compose v2+ or Kubernetes
  • PostgreSQL 17 or newer (18+ recommended for 3x I/O improvements)
  • Reverse proxy with TLS (Caddy, nginx, Traefik) or cloud load balancer
  • Secrets management (env, Vault, Sealed Secrets, etc.)
Use this when
  • Self-hosted production deployments with audit requirements
  • Central Postgres with point-in-time recovery already in place
  • Teams with dedicated infrastructure or platform engineering
  • Compliance regimes (SOC 2, HIPAA, ISO 27001) that require Postgres
  • Kubernetes stacks with a Helm chart on the roadmap
Database
PostgreSQL 17+ (18.3+ recommended)
Scale envelope
1000+ agents, 5000+ events/second, multiple brain replicas behind a load balancer
HTTPS setup

Reverse proxy, your choice.

z4j does not bundle a reverse proxy. Pick the TLS pattern that matches your existing infra.

Next step

Install the agent in your app

After the brain is running, drop the agent package into your Django, Flask, or FastAPI app. One pip install plus three environment variables.

Pick your engine

Every tier supports every engine

Install one or more engine adapters alongside your framework. Every deployment tier supports all six.

Architecture FAQ

One image, one clear story.

Answers to the common confusions about z4j's container layout.

Is the frontend a separate container?

No. The brain image bundles the FastAPI backend and the compiled React dashboard together. The backend serves the dashboard as static HTML, CSS, and JS from the same process. There is no second container for the UI.

Is there a separate image for each tier?

No. Both Docker tiers use the same z4jdev/z4j image. The runtime picks SQLite or Postgres based on the Z4J_DATABASE_URL environment variable.

Then what are the image tags for?

Tags pin versions, not modes. Use :latest for the most recent release, :1.0.0 to pin a specific version, and :edge for pre-releases.

How many services for z4j + Postgres?

Two. z4j-brain runs the backend and dashboard from one image. z4j-postgres runs Postgres. No separate frontend.

Does the brain need Redis or RabbitMQ?

No. The brain communicates with your agents over a direct WebSocket. Your task queue engine uses whatever broker it already uses (Redis, RabbitMQ, SQS). The brain observes, it does not re-broker.

Can I migrate from SQLite to Postgres later?

Yes. Point Z4J_DATABASE_URL at your Postgres instance and restart. The same image reconnects, runs migrations, and picks up your users, audit chain, and schedules.

Still picking a tier?

Solo developer or homelab: start with pip. Team of 2-20: default z4j compose. Anyone with existing Postgres or compliance needs: z4j + Postgres.