Getting Started

Get the Zentinel Control Plane running locally and deploy your first configuration bundle.

Prerequisites

Docker Compose (recommended): Only Docker required — all dependencies included.

Standalone / production deployment: If you have your own PostgreSQL and S3, see the standalone Docker and bare-metal options.

Local development:

  • Elixir 1.16+ and Erlang/OTP 26+ (managed via mise)
  • Docker — for MinIO (bundle storage)
  • zentinel CLI binary — for configuration validation

Docker Compose

Start the full stack with one command:

git clone https://github.com/zentinelproxy/zentinel-control-plane.git
cd zentinel-control-plane
docker compose up

This starts:

ServicePortPurpose
Control Plane4000Web UI and API
PostgreSQL 175432Database
MinIO9000 (API), 9001 (console)Bundle storage

The control plane automatically runs database migrations and seeds the database on first startup.

Open http://localhost:4000 to access the web UI.

MinIO console at http://localhost:9001 (credentials: minioadmin / minioadmin).

To tear down (including data):

docker compose down -v

Local Development

For hot-reloading and SQLite (no external databases):

git clone https://github.com/zentinelproxy/zentinel-control-plane.git
cd zentinel-control-plane

mise install          # Install Elixir/Erlang
mise run setup        # Fetch deps, create DB, migrate, seed
mise run dev          # Start dev server at localhost:4000

Default Credentials

On first startup, a default admin account is created:

FieldValue
Emailadmin@localhost
Passwordchangeme123456
Roleadmin

Important: Change these credentials immediately in any non-development environment.

Creating Your Own User

Via the web UI: Navigate to /register.

Via the console:

# Local development
mise run console

# Docker
docker compose exec app bin/zentinel_cp eval '
  ZentinelCp.Accounts.register_user(%{
    email: "[email protected]",
    password: "your-secure-password-here"
  })
'

Password requirements: minimum 12 characters, maximum 72 characters. Hashed with Argon2.

User Roles

RolePermissions
adminFull org control — manage members, projects, signing keys, API keys
operatorManage projects, bundles, rollouts, services, nodes
readerRead-only access to all resources

Roles are per-organization. A user can hold different roles in different orgs.

First Steps

1. Create an Organization

Navigate to Organizations > New Organization. Enter a name — a URL-safe slug is generated automatically. Organizations are the top-level tenant boundary.

2. Create a Project

From the org dashboard, click New Project. Projects group related proxy configurations, nodes, bundles, and rollouts.

3. Configure Services

Navigate to Services > New Service. Define a route path and upstream:

  • Name: e.g., “API Backend”
  • Route Path: e.g., /api/*
  • Upstream URL: e.g., http://api.internal:8080

4. Compile a Bundle

Navigate to Bundles > New Bundle. Enter KDL configuration or generate from your services. Compilation runs in the background — the bundle transitions from compiling to compiled when ready.

Or via the API:

curl -X POST http://localhost:4000/api/v1/projects/my-project/bundles \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"config_source": "route \"/api/*\" {\n  upstream \"http://api:8080\"\n}"}'

5. Register a Node

Register a Zentinel proxy instance:

curl -X POST http://localhost:4000/api/v1/projects/my-project/nodes/register \
  -H "Content-Type: application/json" \
  -d '{"name": "proxy-1", "labels": {"env": "dev"}}'

Store the returned node_key — it is shown only once. See the Proxy Registration guide for the full walkthrough on connecting proxies, configuring JWT auth, and deploying bundles.

6. Deploy with a Rollout

Navigate to Rollouts > New Rollout. Select the compiled bundle, choose a strategy (rolling, canary, blue-green, all-at-once), configure health gates, and start.

Environment Variables

Key variables for Docker deployment:

VariableDefaultPurpose
DATABASE_URLecto://zentinel:zentinel@postgres:5432/zentinel_cpPostgreSQL connection
SECRET_KEY_BASESet in composePhoenix secret key
S3_ENDPOINThttp://minio:9000MinIO endpoint
S3_BUCKETzentinel-bundlesBundle storage bucket
PORT4000HTTP listen port

See Configuration for the full list of environment variables.