Documentation Index
Fetch the complete documentation index at: https://docs.kindling.systems/llms.txt
Use this file to discover all available pages before exploring further.
Production Setup
The common public shape for Kindling is a Linux host running the control plane with public edge-facing hostnames.Core Pieces
- a Linux host with the required Kindling toolchain
- PostgreSQL configured for Kindling state and logical replication
- public DNS records for API, dashboard, and any workload hostnames
- firewall and host permissions aligned with the chosen runtime
Recommended Production Shape
Start with one of these supported shapes:- All-in-one single server: one Linux host runs API, edge, worker, WAL listener, reconcilers, and PostgreSQL.
- Single control plane + remote workers: one Linux host runs API, edge, PostgreSQL, WAL listener, and reconcilers; additional Linux hosts run worker-only
kindling serveprocesses against the same database cluster.
docs/high-availability.md).
Important First-Boot Inputs
public_base_url- optional
dashboard_public_host - optional service and preview base domains
- optional
advertise_hostfor browser-openable runtime URLs
kindling serve flags on first boot.
What Production Means In Practice
Production self-hosting is not only “the server starts.” It also means:- TLS can be issued for the public hosts you expose
- the dashboard build points at the correct API origin
- the host can actually expose runtime URLs or edge-routed traffic
- the runtime and networking permissions on the machine match the chosen deploy path
Multi-Server Bootstrap
This is the recommended sequence for a control-plane-plus-workers cluster. Canonical topology boundaries: repodocs/high-availability.md and docs/private-networking.md.
1. Prepare the database tier
- Create or identify the PostgreSQL cluster that will hold Kindling state.
- Put PgBouncer or another private SQL entry point in front of PostgreSQL on your private network.
- Make sure every Kindling host can reach that same private host:port.
- Write the same DSN to
/etc/kindling/postgres.dsnon every host. - If
/etc/kindling/postgres.dsnpoints at PgBouncer, also write the same direct-primary DSN to/etc/kindling/postgres.replication.dsnon every host for the WAL listener.
localhost, 127.0.0.1, or a public PostgreSQL listener.
Example direct replication DSN shape when pooling:
2. Prepare the control-plane host
- Install host dependencies (
make install-depsorcontrib/install-host-deps.sh --allas appropriate). - Build or deploy the
kindlingbinary. - Run
sudo bash contrib/setup-kindling-prod.sh. - Edit
/etc/kindling/kindling.envwith:KINDLING_HOMEKINDLING_ADVERTISE_HOSTKINDLING_PUBLIC_URL- optional
KINDLING_DASHBOARD_HOST KINDLING_ACME_EMAIL
- Keep
/etc/kindling/postgres.dsnpresent before first start. - If you use PgBouncer, keep
/etc/kindling/postgres.replication.dsnpresent before first start too.
3. Start the first node
Bring up the control-plane services:- run migrations
- create or load
~/.kindling/server-id - register itself in the
serverstable - seed initial cluster/server settings from the serve flags and env-backed wrapper
4. Validate the first node
Verify:- the API is reachable at
public_base_url - the dashboard can load against the intended API origin
GET /api/metareturns successfully- the first server appears in
GET /api/servers server-idexists on disk and remains stable across restarts
5. Join a worker node
For each additional worker host:- install dependencies and deploy the same
kindlingbinary - provision the same
/etc/kindling/postgres.dsn - if pooling, provision the same
/etc/kindling/postgres.replication.dsn - run
sudo bash contrib/setup-kindling-prod.sh - edit
/etc/kindling/kindling.env- set
KINDLING_ADVERTISE_HOSTto that host’s reachable address - keep
KINDLING_PUBLIC_URLpointed at the shared control-plane API origin - Without WireGuard mesh: set
KINDLING_INTERNAL_IPto this host’s stable private IPv4 (required when other servers already exist in the cluster) - With WireGuard mesh (Linux): set
KINDLING_WG_MESH=1,KINDLING_WG_ENDPOINTto this host’s UDPip:port, and on joiners set the coordination-server variables (see below)
- set
- start the worker component:
- loopback
internal_ip(or, without mesh, omittingKINDLING_INTERNAL_IPwhen the cluster already has other servers) - a loopback / localhost PostgreSQL DSN
WireGuard mesh (Linux, optional)
WhenKINDLING_WG_MESH=1 on Linux edge/worker processes, Kindling:
- allocates a deterministic 10.64.x.x overlay address per
server-id - stores WireGuard metadata on
servers(wireguard_ip,wireguard_public_key,wireguard_endpoint) - configures
wg0, syncs peers from PostgreSQL on an interval, and setsservers.internal_ipto the overlay address for that process
docs/private-networking.md for the full contract):
| Variable | Role |
|---|---|
KINDLING_WG_MESH=1 | Enable automation |
KINDLING_WG_ENDPOINT | This node’s UDP endpoint (host:port) as seen by peers |
KINDLING_WG_LISTEN_PORT | Optional; default 51820 |
KINDLING_WG_PRIVATE_KEY | Optional override (base64); else file ~/.kindling/wg-private-key, else Kindling generates a per-node local key |
KINDLING_COORDINATION_SERVER_WG_IP | Joiners only — coordination peer overlay IP |
KINDLING_COORDINATION_SERVER_ENDPOINT | Joiners only — coordination peer UDP endpoint |
KINDLING_COORDINATION_SERVER_PUBKEY | Joiners only — coordination peer WireGuard public key |
vm_ip:port from Postgres. With mesh enabled, peers advertise each server’s VM ip_range as WireGuard AllowedIPs, so the control-plane host can route to remote VM addresses over wg0 when those IPs sit in the peer’s allocated range. If you disable mesh, you must provide your own routing or port publishing between edge and workers.
6. Validate the joined worker
After joining, verify:- the new server appears in
GET /api/servers - the worker reports healthy component metadata
- deployments can place workloads onto the joined worker
- the control plane can still reach workloads running there
- if using Cloud Hypervisor across multiple workers,
KINDLING_CH_SHARED_ROOTFS_DIRis consistent with your shared-storage design
Operator Checklist
Before calling the cluster healthy:- every host uses the same
/etc/kindling/postgres.dsn - the DSN points at a shared private database entry point
- if pooling, every host uses the same
/etc/kindling/postgres.replication.dsnand it points at a replication-capable PostgreSQL host - every host has a stable
server-idat~/.kindling/server-id(noKINDLING_SERVER_IDenv — obsolete) - without mesh: every joining worker has
KINDLING_INTERNAL_IPset to a non-loopback private address - with mesh: every participating host has
KINDLING_WG_MESH=1,KINDLING_WG_ENDPOINT, and joiners have coordination-server env vars until the mesh converges - no multi-server worker advertises
127.0.0.1,0.0.0.0, orlocalhostas its internal address - the control plane can proxy to workloads on joined workers
- DNS, TLS, and dashboard API origin all match the public hostnames you configured
Documentation map
Strategic product architecture (including supported topology narrative) may live in your team’s Kindling vault asSpec.md. Operator runbooks in this repository are what you follow for day-one setup and validation:
docs/high-availability.md— supported topologies, PostgreSQL HA, multi-server bootstrap.docs/private-networking.md— private DSN pattern, WireGuard mesh contract (PEP-287), edge → workload routing.docs/control-plane-backup-and-dr.md— control-plane vs workload backup scope, recovery ordering.- Control-plane backup and DR — summary and links for operators.
- Backup and restore — procedures (Postgres / volumes / validation).
- Operations runbook — install, upgrade, backup, drain, audit checklist index.