zattera

module
v0.1.0-alpha.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 14, 2026 License: Apache-2.0

README

⛵ Zattera

The single-binary PaaS. Your servers, the Vercel experience.

Zattera — Italian for "raft". It runs on Raft.

zattera.dev · Docs · Quickstart

Status License Go Dependencies


Turn any pool of machines — bare metal, VPS, multi-cloud, the server under your desk — into a Heroku/Vercel-grade platform. One Go binary that is the CLI, the control plane, the scheduler, the proxy, the cert manager, and the registry. The only thing your servers need is Docker.

# on your first server
curl -fsSL https://get.zattera.dev | sh

# on every other machine, anywhere in the world
curl -fsSL https://get.zattera.dev | sh -s -- --join zattera.example.com --token <JOIN_TOKEN>

# on your laptop
zattera deploy --prod
✓ Built api (nixpacks, 34s)
✓ Released v42 → production (red/green, 2 replicas healthy)
● https://api.example.com

Why Zattera

Every alternative makes you choose: a web panel bolted on Docker with no real orchestration (Coolify, Dokploy), a bare CLI that leaves scheduling and state to you (Kamal), or the full cloud experience if you operate Kubernetes first (Kubero, Cozystack). Zattera takes the untaken quadrant: real multi-server orchestration with zero platform dependencies.

  • No Kubernetes. No etcd, no CNI/CSI/Ingress zoo, no YAML sprawl.
  • No external database. State lives in embedded Raft — the platform that runs your Postgres doesn't die when its Postgres dies. It doesn't have one.
  • No web-stack panel on your servers. Workers run an agent measured in tens of MB, not a 2GB dashboard.
  • No bundled nginx/Traefik/certbot. Proxy and ACME live in-process. No config generation, no version skew, no "cert renewed but proxy didn't reload".
  • No vendor anything. Builds, images, logs, metrics — all on your metal. Works air-gapped.

Features

  • Nodes anywhere — WireGuard mesh + gossip: multi-region, multi-cloud, NAT'd home servers, all first-class. Starts at one node; grow with a single --join, drain and remove nodes freely.
  • Deploy anything — Nixpacks auto-detection or Dockerfile, built on your own builders, stored in the embedded registry.
  • Vercel-style flowzattera deploy --prod, GitHub push-to-deploy, staging/production/preview environments, env vars & secrets, custom domains + automatic Let's Encrypt.
  • Red/green releases — new version fully healthy before traffic switches; instant rollback.
  • Scale — replica autoscaling, load balancing across nodes, scale-to-zero with wake-on-request, serverless concurrency mode.
  • Internal DNS — services talk cross-node via db.production.myproject.internal over the encrypted mesh; staging never sees production.
  • Stateful apps — pinned volumes for Postgres/Redis/…, browsable from the CLI, snapshotted to S3.
  • Disaster recovery — full platform restore (state + volumes + images) onto fresh infrastructure with one command.
  • Operate it — logs, metrics, alerts, jobs & cron, zattera attach/top/fs/port-forward, audit log, RBAC, API-first (the CLI is a pure API client).
  • Coming later — node autoprovisioning: Zattera buys Hetzner/DO/AWS machines when the pool is full and destroys them when idle, with budget caps.

What Zattera does

Status note: Pre-alpha. The spec is complete and core foundations exist (Raft, protos, scheduler, mesh, registry), but M1 (deploy → HTTPS → rollback end-to-end) is not finished yet. Most items below are designed/planned, not all shipped today.

Platform model
  • Single Go binary — CLI, control plane, worker agent, proxy, and registry in one binary
  • Docker only — no Postgres, Redis, etcd, nginx, or certbot on hosts
  • Embedded Raft state — no external control-plane database
  • One-line install & join — workers join with --join + token
  • Single node → cluster — fully functional on one machine; grow with --join, drain/remove nodes
Deploy & build
  • Nixpacks + Dockerfile builds via BuildKit
  • Pre-built image deploys
  • Embedded OCI registry — no Docker Hub required
  • Git push-to-deploy — GitHub webhook/App, branch → environment mapping
  • Environments — staging, production, preview-*
  • Red/green deploys — traffic switches only after health checks pass
  • Instant rollback — previous release kept warm (~10 min)
  • Config as codezattera.toml + CLI/API
Multi-server orchestration
  • Own scheduler — bin-packing, spread, node labels/constraints
  • True multi-server pooling — not independent per-server management
  • WireGuard mesh — cross-region, multi-cloud, NAT/home servers as first-class
  • HA control plane — 3–5 node Raft quorum
  • Node drain/remove — graceful migration for stateless workloads
  • Autoscaling — CPU/RAM/RPS-driven replica scaling
  • Scale-to-zero — idle timeout → 0 replicas; wake on request (M3)
  • Serverless mode — concurrency-based scaling (M3)
Networking & traffic
  • Embedded L7/L4 proxy — HTTP/2, WebSocket, TCP passthrough
  • Load balancing — P2C, health checks, optional sticky sessions
  • TLS / ACME — embedded Let's Encrypt; HTTP-01 in M1–M3
  • Internal DNSservice.env.project.internal across nodes over the mesh
  • Any node as ingress — traffic can enter anywhere and route over the mesh
Stateful & data
  • Volumes — pinned to nodes for Postgres, Redis, etc.
  • Volume CLI — browse, cp, snapshot
  • S3 snapshots — incremental, content-addressed
  • Full disaster recovery — one-command restore: state + volumes + images (M2)
  • Honest data HA — snapshots + app-level replication; no fake sync replication
Operations
  • Logs — tail, stream, retention; zattera logs -f
  • Metrics — per-app/node; historical TSDB (M2)
  • Alerts — webhook/Slack/email (M3)
  • Jobs & cron — one-shot jobs + scheduled cron (M2)
  • Remote debug — attach, top, fs, port-forward over API tunnel
  • RBAC — org → project → environment roles
  • Audit log — mutating API calls recorded
  • API-first — CLI is a pure API client; everything scriptable
  • State export/apply — GitOps-lite cluster config export
Coming later
  • SSO/OIDC (M4)
  • Wildcard certs via DNS-01 (M4)
  • Node autoprovisioning — Hetzner, then DO/AWS (M5)
  • External log sinks, Prometheus endpoint (M4)

What Zattera deliberately doesn't do

Zattera's edge is not a longer feature list — it's focus on the deploy-and-run path and refusing what makes alternatives heavy or fragile.

Doesn't do Who typically does Why Zattera skips it
Run Kubernetes Kubero, Cozystack, Devtron No etcd/CNI/CSI/Ingress zoo, no YAML sprawl
Multi-container pods / sidecars Kubernetes One container per service instance
Service mesh / network policies Istio, Linkerd, K8s Complexity far exceeds typical app-deploy needs
Operators / CRDs / plugins K8s ecosystem No extension sprawl
Docker Swarm orchestration Dokploy, CapRover Weak for cross-region/NAT; maintenance mode
General-purpose orchestrator Nomad, K8s App platform, not a generic scheduler
Web GUI on servers Coolify, Dokploy, CapRover CLI + API first; no 2GB panel on every host
280+ one-click app templates Coolify, CapRover Maintenance treadmill; docs/recipes instead
Separate Traefik/Nginx/certbot Coolify, Dokploy, CapRover Proxy + ACME in-process
External DB for the platform Coolify (Postgres+Redis) Control plane shouldn't die when its DB dies
Distributed volume replication Longhorn, Ceph Honest RPO via snapshots, not fake HA
Vendor-hosted builds/images Vercel, Railway, Fly Builds and images stay on your metal

See What we deliberately don't do in the full specification.

How Zattera compares

Capability Zattera Dokploy Kubernetes Coolify Kamal
Real multi-server scheduling ✅ Own scheduler ⚠️ Docker Swarm ✅ Native ❌ Independent servers ⚠️ Manual per-host
NAT / home servers ✅ WireGuard mesh ❌ SSH-only ❌ SSH-only
Control-plane footprint ✅ One binary Panel + Swarm Full cluster ~2GB panel + DB Client-only CLI
Scale-to-zero / serverless ✅ (M3) ⚠️ Via add-ons
Red/green + instant rollback Rolling Rollouts Rolling
Web admin UI ❌ CLI/API Many
One-click app catalog Helm charts
K8s ecosystem (CRDs, mesh, CSI)
Full DR from S3 ✅ (M2) Partial Velero (add-on) Partial Git config
Requires K8s expertise

Pick Zattera if you want Vercel/Heroku-style deploys on your own servers, multi-region/home-lab workers without K8s, and red/green + scale-to-zero + DR as first-class features.

Pick Dokploy/Coolify if you want a web UI today, one-click templates, and are fine with a heavier control-plane stack.

Pick Kubernetes if you need pods, sidecars, CRDs, service mesh, CSI storage, and have platform-engineering capacity.

Pick Kamal if you want minimal explicit deploys to known hosts and will manage scaling and state yourself.

Read the full comparison in the specification.

How it works

 CLI ──HTTPS──▶ Control plane (1–5 nodes: API · Raft · Scheduler · Builder · ACME)
                      │ mTLS over WireGuard mesh
        ┌─────────────┴─────────────┐
   Worker node                 Worker node
   agent · proxy · docker      agent · proxy · docker
   (Hetzner, eu)               (home server, NAT)

Desired state is declared, replicated via Raft, and continuously reconciled. Kill a node: stateless replicas reschedule in seconds. Export the whole platform as YAML with zattera state export. Read the full specification.

Status

⚠️ Pre-alpha — spec stage. The specification is complete; implementation is starting with the M1 milestone (single control node, builds, red/green deploys, proxy + ACME, CLI, GitHub integration). Star the repo to follow along, open a Discussion to influence the design.

Non-goals

Multi-container pods, service mesh, plugins/CRDs, template catalogs, Windows containers, being a general-purpose orchestrator. The subtraction is the product — see What we deliberately don't do.

Contributing

Design discussions happen in Issues/Discussions; architecture decisions are recorded as ADRs. Dev setup in CONTRIBUTING.md.

License

Apache-2.0

Directories

Path Synopsis
api
gen/zattera/v1
Package zatterav1 is a reverse proxy.
Package zatterav1 is a reverse proxy.
cmd
zattera command
zattera is the single binary: CLI, control-plane node and worker node.
zattera is the single binary: CLI, control-plane node and worker node.
internal
appconfig
Package appconfig parses the per-app zattera.toml (spec §4) into the proto shapes ApplyAppConfig consumes, and computes the deterministic config hash that identifies a release's effective configuration.
Package appconfig parses the per-app zattera.toml (spec §4) into the proto shapes ApplyAppConfig consumes, and computes the deterministic config hash that identifies a release's effective configuration.
cli
Package cli implements every user-facing command.
Package cli implements every user-facing command.
cli/cliconfig
Package cliconfig manages the CLI-side configuration (~/.config/zattera/config.toml): named contexts pointing at clusters, with tokens.
Package cliconfig manages the CLI-side configuration (~/.config/zattera/config.toml): named contexts pointing at clusters, with tokens.
cli/ui
Package ui centralizes CLI output: lipgloss styles, success/error lines in the Vercel-style format, tables, and a --json mode that suppresses all decoration.
Package ui centralizes CLI output: lipgloss styles, success/error lines in the Vercel-style format, tables, and a --json mode that suppresses all decoration.
commands
Package commands assembles the cobra command tree.
Package commands assembles the cobra command tree.
config
Package config loads and validates the zatterad server configuration.
Package config loads and validates the zatterad server configuration.
daemon
Package daemon is the node runtime: control plane and/or worker, selected by config roles.
Package daemon is the node runtime: control plane and/or worker, selected by config roles.
daemon/agent
Package agent is the node-side runtime that keeps a node in sync with the control plane.
Package agent is the node-side runtime that keeps a node in sync with the control plane.
daemon/api
Package api hosts the public control-plane API.
Package api hosts the public control-plane API.
daemon/builder
Package builder builds container images from source using a managed buildkitd (spec §3.4).
Package builder builds container images from source using a managed buildkitd (spec §3.4).
daemon/ca
Package ca implements the embedded cluster certificate authority.
Package ca implements the embedded cluster certificate authority.
daemon/github
Package github implements push-to-deploy: a webhook endpoint that turns GitHub push events into builds, and GitHub App authentication for cloning private repos and posting commit statuses (spec F9, T-37).
Package github implements push-to-deploy: a webhook endpoint that turns GitHub push events into builds, and GitHub App authentication for cloning private repos and posting commit statuses (spec F9, T-37).
daemon/intdns
Package intdns is the per-node internal DNS resolver (F26).
Package intdns is the per-node internal DNS resolver (F26).
daemon/livestate
Package livestate holds the leader's in-memory view of connected nodes: presence, last heartbeat time and the most recent live sample.
Package livestate holds the leader's in-memory view of connected nodes: presence, last heartbeat time and the most recent live sample.
daemon/logstore
Package logstore defines the per-node log storage contract (spec §3.10).
Package logstore defines the per-node log storage contract (spec §3.10).
daemon/mesh
Package mesh owns the WireGuard overlay (ADR-0003).
Package mesh owns the WireGuard overlay (ADR-0003).
daemon/nodeinfo
Package nodeinfo detects a node's static capacity (CPU / memory / disk) for registration in state.
Package nodeinfo detects a node's static capacity (CPU / memory / disk) for registration in state.
daemon/proxy
Package proxy hosts the embedded L7/L4 proxy (tasks T-41..T-48).
Package proxy hosts the embedded L7/L4 proxy (tasks T-41..T-48).
daemon/raftstore
Package raftstore wires hashicorp/raft to the in-memory state store (ADR-0004).
Package raftstore wires hashicorp/raft to the in-memory state store (ADR-0004).
daemon/registry
Package registry implements Zattera's embedded OCI image registry (spec §3.5).
Package registry implements Zattera's embedded OCI image registry (spec §3.5).
daemon/runtime
docker.go is the ONLY file permitted to import the Docker SDK (spec rule 3).
docker.go is the ONLY file permitted to import the Docker SDK (spec rule 3).
daemon/scheduler
Package scheduler runs on the leader and reconciles desired replica counts into Assignments: it decides WHAT should run WHERE, writing only desired state (agents converge it, T-15).
Package scheduler runs on the leader and reconciles desired replica counts into Assignments: it decides WHAT should run WHERE, writing only desired state (agents converge it, T-15).
daemon/secrets
Package secrets implements envelope encryption for cluster secrets (spec §3.13, design §2.10):
Package secrets implements envelope encryption for cluster secrets (spec §3.13, design §2.10):
daemon/tlsmgr
Package tlsmgr manages TLS certificates for the ingress: ACME issuance via certmagic backed by the raft KV (cluster-wide, one issuer serialized by a distributed lock), and a dev mode that mints self-signed certs from the cluster CA on demand (T-44).
Package tlsmgr manages TLS certificates for the ingress: ACME issuance via certmagic backed by the raft KV (cluster-wide, one issuer serialized by a distributed lock), and a dev mode that mints self-signed certs from the cluster CA on demand (T-44).
daemon/tsdb
Package tsdb defines the embedded time-series store contract (spec §3.10): per-series ring buffers, 15s raw resolution for 24h + 5m downsampled for 30d.
Package tsdb defines the embedded time-series store contract (spec §3.10): per-series ring buffers, 15s raw resolution for 24h + 5m downsampled for 30d.
pkgutil/clock
Package clock abstracts time for testability.
Package clock abstracts time for testability.
pkgutil/ids
Package ids generates the ULID identifiers used for every first-class object.
Package ids generates the ULID identifiers used for every first-class object.
pkgutil/version
Package version carries the build version, stamped via -ldflags.
Package version carries the build version, stamped via -ldflags.
state
Package state holds the full replicated cluster state in memory (ADR-0004).
Package state holds the full replicated cluster state in memory (ADR-0004).
testutil/fakeruntime
Package fakeruntime is an in-memory ContainerRuntime for unit and simcluster tests.
Package fakeruntime is an in-memory ContainerRuntime for unit and simcluster tests.
testutil/freeport
Package freeport hands out free TCP ports for tests.
Package freeport hands out free TCP ports for tests.
testutil/simcluster
Package simcluster runs an in-process multi-node Zattera control plane for unit and chaos tests: real hashicorp/raft with in-memory transports, real FSM/state, fake container runtime, fake clock.
Package simcluster runs an in-process multi-node Zattera control plane for unit and chaos tests: real hashicorp/raft with in-memory transports, real FSM/state, fake container runtime, fake clock.
pkg
apiclient
Package apiclient is the public Go client for the Zattera API.
Package apiclient is the public Go client for the Zattera API.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL