KOWAN Docs

DocsReference

Architecture

How Kowan works: the server, the agents and their edge and direct connections, where data is stored, what runs in the background, and which ports to open.

Kowan is one server and one agent per extra Docker host. The server holds all the state and serves the web console, the API and the MCP server; agents give it access to the Docker of the hosts they run on. Knowing how the parts connect, where data lives and what runs in the background helps you plan networks, firewalls and backups.

The parts

   Browser        kowanctl       AI assistant
      |               |                |
      +------- HTTPS, or HTTP :5081 ---+
                      |
             +------------------+   Docker socket
             |   Kowan server   |-----------------> Docker on the
             |  (SQLite data)   |                   server's own host
             +------------------+
                ^            |
     edge: the  |            |  direct: the server
     agent      |            |  connects to :9001
     connects   |            v
          +-----------+  +-----------+
          |  agent    |  |  agent    |
          |  host A   |  |  host B   |
          +-----------+  +-----------+
The Kowan server
A single container (ghcr.io/kowan-lab/kowan) listening on port 5081. It serves the web console, the REST API under /api/v1, the MCP server for AI assistants at /mcp, incoming webhooks under /hooks/, the optional public status page at /status, and /health for health checks. It stores everything in SQLite, in its data directory: there is no external database to run.
Agents
A container (ghcr.io/kowan-lab/kowan-agent) on each extra host, with that host's Docker socket mounted. The agent runs Docker operations for the server and streams events, logs and stats back. It keeps no state of its own.
kowanctl
The command-line client. It talks to the server's REST API with a session token or an API key, never to agents directly. See Command line.

The server manages the host it runs on through the Docker socket mounted into its container, with no agent. Kowan talks to Docker through the Docker Engine API, the same one the docker command uses.

Both images are published for x86-64 (amd64) and ARM64, and include a Docker health check.

How agents connect

An agent and the server share one connection, a WebSocket that carries many streams at once: a log you follow, a shell, a file download and routine operations travel side by side, and a slow stream does not hold up the others. Once connected, the server can send operations to the agent and the agent can push events to the server, whichever side opened the connection.

Which side opens it depends on the host's mode:

Edge Direct
Opens the connection The agent, to KOWAN_SERVER_URL The server, to the host's address
Endpoint /edge/connect on the server /connect on the agent, port 9001
Encryption The server's HTTPS, when KOWAN_SERVER_URL starts with https:// TLS served by the agent, with a self-signed certificate unless you provide one
Reconnects The agent, every 1 to 30 seconds The server, every 1 to 30 seconds
Allowlist KOWAN_EDGE_ALLOW_CIDRS on the server KOWAN_AGENT_ALLOW_CIDRS on the agent

To add a host in either mode, see Adding servers.

How the connection is authenticated

Each host has its own 64-character token, generated by Kowan when you add the host. One rule applies in both modes: the side that opened the connection proves it knows the token, and the side that accepted it checks it.

  • Edge: the agent sends its token, and the server checks it before it accepts the WebSocket. The agent verifies the server's HTTPS certificate.
  • Direct: the token never travels. Before the WebSocket opens, the server presents a time-limited proof derived from the token, accepted within 2 minutes of the agent's clock. Then the server and the agent each prove they know the token with a challenge bound to the agent's TLS certificate. A machine in the middle with its own certificate is refused by both sides, and the server sends nothing to an agent that cannot prove it has the token. The agent's check means a server without the right token cannot drive it.

The agent refuses to start in direct mode with a token shorter than 32 characters. Messages on the connection are capped at 64 KB, and the handshake must finish within 10 seconds.

Where data is stored

The server keeps everything under its data directory, /data in the container (KOWAN_DATA_DIR). Mount a volume there, as the installation commands do.

Path Contents
kowan.db The main database: users, hosts, deployments and revisions, policies, alerts, the audit log and encrypted secrets.
logs.db The retained logs, in a separate database with a full-text index.
secret.key The key that encrypts stored secrets (AES-256-GCM). Generated on first start unless you set KOWAN_SECRET_KEY.
jwt.key The key that signs sign-in sessions. Generated on first start unless you set KOWAN_JWT_SECRET.
setup-token The one-time setup token, deleted once the first administrator exists.
stacks/ Compose files and working data of deployments.
backups/ Database snapshots taken before each server update.

Passwords are stored as scrypt hashes. A Kowan backup contains kowan.db, the two keys and stacks/.

Warning

Losing secret.key makes every stored secret unrecoverable. Keep it in your backups, or keep KOWAN_SECRET_KEY somewhere safe if you set it yourself.

What runs in the background

The server does its routine work on its own, on a fixed rhythm:

Task How often Setting
Check every host, sample container and host metrics, evaluate alert rules Every 15 seconds KOWAN_MONITOR_INTERVAL
Keep those metric samples 7 days KOWAN_METRICS_RETENTION
Record each workload's resource history 5-minute buckets, kept 30 days
Redeploy deployments with auto-heal on whose containers are missing or stopped Checked every 5 seconds, at most once every 120 seconds per deployment KOWAN_RECONCILE_INTERVAL, KOWAN_RECONCILE_COOLDOWN
Delete old audit log entries, resolved alerts and workflow runs About once an hour KOWAN_AUDIT_RETENTION (90 days), KOWAN_ALERT_RETENTION (30 days), KOWAN_WORKFLOW_RUNS_KEEP (100 runs per workflow)
Look for a new Kowan release Every 6 hours KOWAN_RELEASE_REPOSITORY

KOWAN_MONITOR_INTERVAL, KOWAN_METRICS_RETENTION, KOWAN_AUDIT_RETENTION and KOWAN_ALERT_RETENTION accept durations such as 15s, 720h, 1h30m or 90d, or a whole number of seconds; 0 turns the audit log or alert cleanup off. KOWAN_RECONCILE_INTERVAL and KOWAN_RECONCILE_COOLDOWN accept the same formats. See Configuration.

The server also follows the logs of every workload that keeps them, on every host, and listens to Docker events from all hosts. The web console updates from those events as they happen, with periodic refreshes only as a safety net.

Helper containers

For some jobs Kowan starts short-lived containers on the host concerned: the helper that swaps containers during an update, vulnerability scans, volume browsing and volume backups. They, the server and the agents are hidden from Workloads, the Overview, Logs and search unless an admin turns on Kowan's own containers in Settings → General → Features.

Ports and network paths

From To Port Needed for
Browsers, kowanctl, AI assistants Kowan server 5081, or 443 through your reverse proxy Everything
Edge agents Kowan server 5081, or 443 through your reverse proxy Edge hosts
Kowan server Direct agents 9001 Direct hosts
Git providers, other services Kowan server, /hooks/ 5081 or 443 Webhooks, GitOps, previews
Docker on each host, and the Kowan server Image registries 443 Pulling images, update checks, release checks

KOWAN_UI_ALLOW_CIDRS limits who can reach the console, the API and MCP; webhooks and /health stay open. See Network access.

Security model in short

  • Whoever controls Docker on a host controls the host. Both the server (through its socket mount) and every agent have that power, so protect the server like a root account. See Security.
  • Every user has one of three roles, admin, operator or viewer, and teams can narrow access to some hosts and workloads. See Users and roles.
  • Sessions are checked against the database on every request: signing out, changing a password or deleting a user takes effect at once.
  • Every change made through the console, the API or MCP is recorded in the audit log.

Edit this page on GitHub