zattera

module
v0.1.0-alpha.8 Latest Latest
Warning

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

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

README

⛵ Zattera

Your servers. One binary. A full PaaS.

Turn any pool of machines into your own Heroku — in the time it takes to brew a coffee.

Zattera is Italian for "raft". Fitting: it floats on Raft consensus.

zattera.dev · Docs · Quickstart

Status License Go Dependencies


You have machines: a bare-metal box, a couple of VPSes, maybe the server humming under your desk. What you don't have is a weekend to spend wiring together Kubernetes, Traefik, certbot, a registry, and a Postgres just to deploy your app.

Zattera is one Go binary that is the CLI, the control plane, the scheduler, the proxy, the cert manager, and the registry. Your servers need Docker. That's it. That's the whole dependency list.

From zero to deployed in four commands

# 1. On your first server — start the cluster
#    Asks for a domain (e.g. mycluster.example.com), prints your login + join commands
curl -fsSL https://get.zattera.dev | sh
sudo zattera cluster init

# 2. On every other machine, anywhere in the world — join it
#    (the previous command prints this line for you)
curl -fsSL https://get.zattera.dev | sh && sudo zattera cluster join <control-ip>:8443 --token <JOIN_TOKEN>

# 3. From your laptop — log in and take the helm
zt login --server https://<control-ip>:8443 --ca-pin <FINGERPRINT> --token <ADMIN_TOKEN> --context prod

# 4. cd into your app (any Nixpacks / Dockerfile app) and ship it
zt deploy --prod
✓ Built api (nixpacks, 34s)
✓ Released v42 → production (red/green, 2 replicas healthy)
● https://api.yourcustomdomain.com
  https://api-prod.mycluster.example.com

No YAML. No panel to install. No cloud account. Your metal, your platform.

Why Zattera exists

Every self-hosting tool today forces a trade-off:

  • Web panels on Docker (Coolify, Dokploy) — friendly, but no real multi-server orchestration underneath.
  • Bare deploy CLIs (Kamal) — minimal, but scheduling, state, and failover are your problem.
  • "Just run Kubernetes first" (Kubero, Cozystack) — the full cloud experience, if you staff a platform team.

Zattera takes the quadrant nobody claimed: real multi-server orchestration with zero platform dependencies.

That means a long list of things you'll never install, configure, or debug at 3 AM:

  • 🚫 No Kubernetes. No etcd, no CNI/CSI/Ingress zoo, no YAML sprawl. Setting up your infrastructure shouldn't require five Kubernetes DevOps engineers.
  • 🚫 No Docker Swarm. No orchestrator in maintenance mode holding your production together.
  • 🚫 No external database. State lives in embedded Raft, replicated across nodes. The control plane can't die because "its database died".
  • 🚫 No web-stack panel on your servers. Workers run an agent measured in tens of MB — not a 2 GB dashboard per host.
  • 🚫 No bundled nginx/Traefik/certbot. Proxying, load balancing, and Let's Encrypt certificates live in-process. No config generation, no version skew, no "cert renewed but the proxy didn't reload".
  • 🚫 No vendor anything. Builds, images, logs, metrics — all on your metal. Works air-gapped. Leaves with you.

What you get

  • 🌍 Nodes anywhere — WireGuard mesh + gossip make multi-region, multi-cloud, and NAT'd home servers first-class citizens. Start with one node; grow with a single --join; drain and remove freely.
  • 📦 Deploy anything — Nixpacks auto-detection or your Dockerfile, built on your own builders, stored in the embedded registry. No Docker Hub required.
  • Vercel-style flowzattera deploy --prod, GitHub push-to-deploy, staging/production/preview environments, env vars & secrets, custom domains with automatic Let's Encrypt.
  • 🔄 Red/green releases — the new version must be fully healthy before traffic switches. Rollback is instant; the previous release stays warm.
  • 📈 Scale — replica autoscaling, cross-node load balancing, 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 — volumes pinned to nodes for Postgres/Redis/…, browsable from the CLI, snapshotted to S3.
  • 🛟 Disaster recovery — restore the whole platform (state + volumes + images) onto fresh infrastructure with one command.
  • 🔧 Real operations — logs, metrics, alerts, jobs & cron, zattera attach/top/fs/port-forward, audit log, RBAC. API-first: the CLI is a pure API client, so everything is scriptable.
  • 🔮 Coming later — node autoprovisioning: Zattera buys Hetzner/DO/AWS machines when the pool is full and destroys them when idle, with budget caps.

The full picture

Status note: Pre-alpha. Zattera.dev is an ambitious PoC/experiment — the base structure is largely "vibe-coded", though architectural choices and most tests are made and verified manually by the maintainer. We're looking for early adopters and alpha testers.

🏗️ 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

The subtraction is the product. Every row below is a deliberate "no":

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 2 GB 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

How it 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 ~2 GB 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 and 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 the platform-engineering capacity to run it.

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

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)

You declare desired state; Raft replicates it; the scheduler continuously reconciles reality against it. Kill a node and stateless replicas reschedule in seconds. Want the whole platform as code? zattera state export gives you the cluster as YAML.

Non-goals

Multi-container pods, service mesh, plugins/CRDs, template catalogs, Windows containers, being a general-purpose orchestrator. See What we deliberately don't do.

Contributing

Design discussions happen in Issues/Discussions; architecture decisions are recorded as ADRs. Dev setup lives 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.
cloud/provider
Package provider is a production cloud-infrastructure client: it spins, inspects, and destroys VMs on a real provider (Hetzner today; others later).
Package provider is a production cloud-infrastructure client: it spins, inspects, and destroys VMs on a real provider (Hetzner today; others later).
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/archive
Package archive gives audit entries and events durability beyond their in-state rings (T-92).
Package archive gives audit entries and events durability beyond their in-state rings (T-92).
daemon/backup
Package backup implements full-platform disaster recovery (spec §3.11, T-66): a leader backs up the raft state, the cluster CA material and the sealed data key to the same S3 object store the volume snapshots use; `zatterad restore` rebuilds a fresh single-node cluster from the latest backup.
Package backup implements full-platform disaster recovery (spec §3.11, T-66): a leader backs up the raft state, the cluster CA material and the sealed data key to the same S3 object store the volume snapshots use; `zatterad restore` rebuilds a fresh single-node cluster from the latest backup.
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/leaderrunner
Package leaderrunner factors the "run this loop only while we hold raft leadership" boilerplate shared by every leader-gated control-plane loop (scheduler, orchestrator, dispatcher, janitors).
Package leaderrunner factors the "run this loop only while we hold raft leadership" boilerplate shared by every leader-gated control-plane loop (scheduler, orchestrator, dispatcher, janitors).
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/mesh/meshsock
Package meshsock is the custom wireguard-go conn.Bind (ADR-0003 Phase C/D): one UDP socket multiplexes WireGuard transport packets and disco probe frames, a per-peer path state machine upgrades hub-routed peers to direct or hole-punched UDP paths, and (Phase D) falls back to a TCP relay when no UDP path works.
Package meshsock is the custom wireguard-go conn.Bind (ADR-0003 Phase C/D): one UDP socket multiplexes WireGuard transport packets and disco probe frames, a per-peer path state machine upgrades hub-routed peers to direct or hole-punched UDP paths, and (Phase D) falls back to a TCP relay when no UDP path works.
daemon/mesh/relay
Package relay is the Phase D DERP-lite fallback (ADR-0003): every control node runs an mTLS TCP relay; a meshsock node with no working UDP path frames its already-encrypted WireGuard packets as (dst node, payload) and the relay forwards them to the destination's connection.
Package relay is the Phase D DERP-lite fallback (ADR-0003): every control node runs an mTLS TCP relay; a meshsock node with no working UDP path frames its already-encrypted WireGuard packets as (dst node, payload) and the relay forwards them to the destination's connection.
daemon/nodehealth
Package nodehealth holds the pure node-liveness decision types shared by the gossip failure detector (internal/daemon/mesh) and the liveness monitor (internal/daemon/api).
Package nodehealth holds the pure node-liveness decision types shared by the gossip failure detector (internal/daemon/mesh) and the liveness monitor (internal/daemon/api).
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/notify
Package notify is the alert engine (T-74): the leader evaluates AlertRules against metrics (TSDB/livestate) and cluster events, and delivers firing and resolved notifications to NotificationChannels (webhook, Slack, email) with per-rule dedupe.
Package notify is the alert engine (T-74): the leader evaluates AlertRules against metrics (TSDB/livestate) and cluster events, and delivers firing and resolved notifications to NotificationChannels (webhook, Slack, email) with per-rule dedupe.
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.
daemon/upgrade
Package upgrade resolves release artifacts for a rolling cluster upgrade (T-95).
Package upgrade resolves release artifacts for a rolling cluster upgrade (T-95).
daemon/volumes
Package volumes implements the content-addressed snapshot engine (spec §3.11): a deterministic tar of a volume's host path is content-defined-chunked (FastCDC), each chunk is deduplicated by sha256, compressed (zstd), encrypted (AES-GCM), and stored as an object; a per-snapshot manifest lists the ordered chunk hashes.
Package volumes implements the content-addressed snapshot engine (spec §3.11): a deterministic tar of a volume's host path is content-defined-chunked (FastCDC), each chunk is deduplicated by sha256, compressed (zstd), encrypted (AES-GCM), and stored as an object; a per-snapshot manifest lists the ordered chunk hashes.
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/platform
Package platform normalizes and matches OCI platform strings ("linux/amd64").
Package platform normalizes and matches OCI platform strings ("linux/amd64").
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