Overview
The Kodela platform runs on one Linux host that you own. A Python console server holds the control plane in a SQLite store and signs people in. A Caddy front door authenticates every request to a workspace. Each organisation gets its own Docker network, and its workspaces join only that network.
Nothing leaves a workspace on your host except through the host. git goes through the git broker. Model calls go through a model broker, which adds the credential on the host. Everything else goes through that organisation's egress proxy, behind a firewall that fails closed. Each of those decisions is written to a hash-chained audit log. Docker in a workspace, when an organisation allows it, goes through a per-workspace Docker broker on the host.
Members' computers. Workspaces run on your Kodela host. If a platform operator grants it and your organisation turns it on, a member's own computer can host their workspaces too. There, internet access is observed, not enforced; DNS filtering is not enforced; the source on its disk is readable by whoever uses it; and Docker is not available. Tested end to end only on Windows (Linux laptops up to enrolment; Mac only in a simulation).
Two defaults shape everything else. Egress ships in observe: it decides, logs and allows until you switch it to deny. The Guarded security profile keeps GitHub and model credentials out of the container.
Every part, and where it stops
The same nine layers the security model uses, read from the outside in, then each part of the diagram with its default and its limit.
The nine layers
- Front door
Authenticates every request to a workspace: terminal, IDE, preview and desktop attach.
The shared front-door password is not tied to a person until “require identity” is on. TLS is yours to put in front.
- Workspace container
A non-root container with no sudo, capped at 2 GB, 2 CPUs and 512 processes by default.
No cap-drop, custom seccomp, read-only root or user-namespace remapping yet. Under full Docker with the
privilegedruntime, the firewall and no-credentials guarantees no longer hold for that workspace. - Organisation network
One internal network per organisation. Workspace creation is refused until the firewall has verified it.
Desktop IDE attach, when an admin turns it on, bypasses file transfer by design and warns at switch-on.
- Firewall
Fails closed: anything that tries to leave without the proxy is dropped, including raw IP addresses.
Copy tools (ssh, rsync, ftp) are refused on their ports and, on any other port, by their opening bytes, while File transfer is below
both; not on members’ own computers, and not underprivilegedfull Docker. The firewall needs root to install. - Egress proxy and DNS filter
Decide every outbound connection by hostname and log it. Each organisation's DNS filter answers allowlisted names only and records refusals.
Observe is the default: it logs and allows. No TLS termination, no payload inspection, and
npm publishcan upload code. Neither applies on a member's own computer, where internet access is observed, not enforced, and DNS is not filtered. - Brokers
Hold git and model credentials on the host and act for the workspace, so the container never holds them at the default level. The Docker and portal brokers act for a workspace the same way, and both are off until an organisation turns them on.
Under Open or Metered, tokens are mounted in the container. Some AI APIs can still be reached directly.
- Approvals and profiles
Decide what the agent may do alone and what stops at an approval card.
Self-approval is the default. Second-person approval is off until an organisation turns it on.
- Validation gate
Decides what may be pushed: a passing verdict for that exact commit, bound to the repository.
Off by default, and not yet seen on a real GitHub push.
- Audit chain
Records it all in hash-chained streams, with credentials redacted, and names who made each pushed commit.
Not protected against host root, and nothing ships off the box until you export it.
The entrance
How a person reaches their work, and how the host knows who they are.
- YouOutside your host
A developer or operator in a browser. A desktop IDE (VS Code Remote-SSH, JetBrains Gateway, ssh) can attach through the same entrance.
Default: Browser access is on. Desktop IDE attach is off until an admin turns it on.
Limit: Desktop attach bypasses file-transfer control by design; the admin switch-on says so.
Workspaces docs- Your IdPOutside your host
Your organisation’s identity provider: Microsoft Entra ID, Google Workspace or a generic OIDC provider, set per organisation.
Default: No provider is configured. Sign-in is by invitation and password.
Limit: Tested in code against a stand-in provider only; never exchanged with a real IdP on record. No SAML or SCIM.
Identity and SSO docs- Console serverOn your host
One Python process (standard library only) that serves the console and its API, signs people in, and forwards workspace paths to the front door. Organisations, members, policy and workspaces live in its SQLite store.
Default: Invite-only. Plain HTTP unless you put a TLS front end in front of it.
Limit: One SQLite file on one host: no high availability, no replicas.
Administration docs- IdentityOn your host
Password sign-in (PBKDF2), 24-hour HMAC-signed session cookies, platform roles (operator, developer) and organisation roles (owner, admin, member, auditor). Per-organisation OIDC with PKCE and nonce checks.
Default: Password login on. "Require identity" at the front door is off.
Limit: While "require identity" is off, the shared front-door password is not tied to a person. MFA only as an IdP-asserted requirement.
Identity and SSO docs- Front doorOn your host
The authenticating entrance for every workspace path: terminal, VS Code, preview and desktop attach. It is joined to each organisation’s network so it can reach that organisation’s workspaces by name.
Default: On, without TLS.
Limit: TLS is yours. Put a TLS front end in front of it.
Front door and TLS docs
The workspace
Where the work happens. Everything inside it is treated as untrusted.
- WorkspaceInside your organisation’s network
A non-root container with no sudo: browser terminal (ttyd and tmux), VS Code in the browser, app preview, a headless browser and the agent CLIs. Its home volume persists. Each new workspace gets its own Postgres beside it by default (none, or connect your own server, are still choices), with a read-only Database tab.
Default: 2 GB memory, 2 CPUs, 512 processes. Suspends after 30 minutes idle. Runs on your host; a member’s own computer can host it only if a platform operator grants it and your organisation turns it on.
Limit: A Docker container, not a VM. No cap-drop, custom seccomp, read-only root or user-namespace remapping yet. On a member’s own computer, internet access is observed, not enforced, and DNS filtering is not enforced.
Workspaces docs
The way out
One route to the internet per organisation, and the rules that make it the only route.
- FirewallOn your host, per organisation
Host firewall rules that let a workspace reach only its proxy and brokers. A raw IP, SSH, or a tool that ignores the proxy is dropped. A second chain keeps workspaces off the control plane.
Default: On, in every egress mode. Survives a reboot through its boot unit.
Limit: Needs root. It makes the proxy unavoidable; it is not the allowlist. While File transfer is below
Egress docsboth, copy tools are refused on their ports, and on any other port the proxy recognises ssh, rsync and ftp by their opening bytes; a copy inside HTTPS to an allowed site is an allowlist question. Not on members’ own computers, and not for a workspace underprivilegedfull Docker.- Egress proxyOn your host, per organisation
Decides every outbound connection by hostname against the allowlist and writes the decision to the egress stream. An organisation can tighten the host allowlist, never loosen it.
Default: Observe: it decides, logs and allows. Deny is one setting, with no restart.
Limit: Starts in observe. Deny is one setting. It does not terminate TLS or inspect payloads, and npm publish can still upload code.
Egress docs- DNS filterOn your host, per organisation
One filter container per organisation network, on its gateway. A name resolves only when it is on the host or organisation allowlist; everything else gets REFUSED, and refusals are collected into the audit. Its health shows in
whats-runningand/api/readyz.Default: Always on for workspaces on your host, in every egress mode. Fails closed: no filter, no DNS, and no fallback resolver.
Limit: It filters names, not addresses; the firewall covers raw IPs. An organisation whose File transfer is
Egress docsbothhas every name resolved, and allowlist entries that are not plain DNS names are dropped. Not enforced on a member’s own computer.- InternetOutside your host
Package registries and services a workspace needs. The default allowlist covers GitHub (through the broker), npm, PyPI, the Anthropic API and Open VSX.
Default: Reached only through the egress proxy.
Limit: In observe, unlisted hosts are logged and still reached.
Egress docs
The brokers
Credentials stay on the host. The brokers act for the workspace instead of handing it a key.
- Git brokerOn your host
The workspace holds no GitHub credential. git talks to a socket mounted for that one workspace; the broker checks the branch rule and repository grant, runs the validation gate, mints a short-lived GitHub App token and records the push with its authorship.
Default: On under the default Guarded profile. Validation gate off.
Limit: Under Open or Metered the token is mounted in the container. The authorship record is an HMAC on this host, not third-party verifiable. The gate has not yet been seen on a real GitHub push.
Git and provenance docs- GitHubOutside your host
Push, pull requests and the pull-requests pane, through a GitHub App you install. A direct connection from the workspace to GitHub is refused.
Default: Reached only through the git broker, in every egress mode.
Limit: Needs a GitHub App. GitLab, Bitbucket and Azure DevOps are not supported.
Git and provenance docs- Model brokersOn your host
The model proxy holds the Anthropic credential on the host and injects it per request; the workspace gets a stand-in key that is worthless off the host. The key broker does the same for OpenAI and Codex.
Default: Model proxy on. Key broker off until an admin turns it on.
Limit: The Antigravity CLI in the workspace does not use a broker, and some AI APIs are reachable directly. Under Open or Metered, tokens are mounted in the container.
AI agents docs- Model providersOutside your host
The providers your organisation chose. Calls go from your host to them, with the credential added on the host.
Default: None until you add an account or key.
Limit: The model sees the context the agent sends it.
AI agents docs- Docker brokerOn your host, per workspace
Managed Docker: the workspace runs real
dockeranddocker compose, and every call goes through its own broker, which starts each container beside the workspace on the workspace’s own internal network. A workspace sees only its own containers, networks, volumes and builds.Default: Off until your organisation allows it (
workspace_docker_allowed: off, managed or full). Containers get no internet by default (docker_egress).Limit: Refuses privileged containers, host namespaces, outside binds and unlisted registries. Pulled images are one shared cache on the host, so a workspace can tell an image was already pulled. Full Docker needs a platform administrator and a supported runtime (Sysbox); under
Workspaces docsprivilegedthe firewall and no-credentials guarantees no longer hold for that workspace. Not available on members’ computers.- Portal brokerOn your host
The workspace-to-console channel. An agent in a workspace can list, start and stop its owners’ other workspaces in the same organisation, ask for a new workspace (an admin decides in Workspace requests) and record app feedback. Each call needs the broker’s secret and a current per-workspace key, and the organisation setting and the owners’ membership are checked every time.
Default: Off until an organisation admin turns it on (
workspace_portal_api_enabled). It listens on the workspace network’s gateway, never on all interfaces.Limit: It cannot change settings, members or credentials, or reach another organisation. A request creates no workspace. Rate-limited per workspace, and every call is audited.
AI agents docs
The record
What was decided, by whom, chained so an edit shows.
- Audit logOn your host
Append-only streams (git, egress, claude, keys, policy, detect, workspace, identity), each record chained to the one before. Credentials are redacted.
audit-log verifynames the stream and line of any break.Default: On. Kept 90 days; retention can only be raised.
Limit: Tamper-evident, not tamper-proof against host root.
Audit docs- Your SIEMOutside your host
Splunk, QRadar, Sentinel or anything that reads CEF, LEEF, RFC 5424 syslog, JSON or CSV.
Default: Nothing is sent. You run the export and ship the file.
Limit: No push to a SIEM and no off-box shipping is built.
Audit docs
Built, off by default, off your host
Present in the code, not in the request path of a default install. The Docker and portal brokers above are off by default too.
- Worker hostA second host
A second host enrolled over mutual TLS, so workspaces could be placed on more than one machine.
Default: Off. Nothing in the request path uses it yet.
Limit: Multi-host is built and off. There is no HA.
Deploy docs- Member’s computerA member’s own computer
A small agent on a member’s own laptop or desktop hosts their workspaces. It connects out to your host, needs no sudo, works behind NAT and updates itself. git, Claude, Codex and the portal go through the platform’s brokers, so no git token or AI key is stored there, and every create, start, stop and removal is decided and recorded on your host.
Default: Off. A platform operator grants it per organisation (
personal_hosts_allowed), then the organisation turns it on (personal_hosts_enabled). Access lapses after 30 days without a connection by default, and removing the computer revokes its key at once.Limit: There, internet access is observed, not enforced; DNS filtering is not enforced; the source on its disk is readable by whoever uses it; and Docker is not available. Tested end to end only on Windows (Linux laptops up to enrolment; Mac only in a simulation).
Workspaces docs
The flows, step by step
The five flows the diagram plays, written out. Each step names the part that acts. The host in the outbound request is an example.
Open a workspace
- YouA developer opens the console in a browser. Without a TLS front end of your own, this is plain HTTP.
- Console serverThe console server signs them in: a password, or their organisation’s OIDC provider. Their organisation role decides which workspaces they may open.
- Console serverStarting the workspace: the container goes on the organisation’s own network, and the console refuses unless the firewall has verified that network and a DNS filter answers on it.
- Front doorTerminal, editor and preview requests go on to the front door (Caddy), which authenticates every workspace path.
- WorkspaceThe workspace answers: a terminal, VS Code in the browser and the app preview. After 30 idle minutes it suspends.
Agent calls a model
- WorkspaceClaude Code in the workspace calls the model. The key it holds is a per-workspace stand-in, worthless off the host.
- Model brokersThe model proxy on the host strips what the container sent and injects the real credential. The container never sees it.
- Model providersThe request leaves from your host to Anthropic. The model sees the context the agent sends it.
- Audit logUsage is metered and the call is written to the claude stream. Codex goes the same way through the key broker, which is off until an admin turns it on; the Antigravity CLI does not use a broker.
Agent pushes code
- WorkspaceThe agent runs git push. The workspace holds no GitHub credential; git talks to a socket mounted for this one workspace.
- Git brokerThe git broker knows which workspace is asking from the socket it arrived on, then checks the branch rule and the repository grant.
- Git brokerValidation gate: when an organisation turns it on, the push needs a passing verdict for its exact commit. It ships off.
- GitHubThe broker mints a GitHub App token that lasts about an hour, keeps it in its own memory, and forwards the push.
- Git brokerGitHub answers. The broker records the result with the tip’s author: agent, human-console or unattributed, never a guess of human. It is signed with a key held on this host.
- Audit logThe decision and the result land in the git stream of the audit log.
Outbound request
- WorkspaceA package install in the workspace asks for a host that is not on the allowlist: unlisted.example.test.
- FirewallThe firewall lets the workspace reach only its proxy. A raw IP, or a tool that ignores the proxy, is dropped here in every mode.
- Egress proxyIn observe: The egress proxy decides by hostname. In observe, the default, it records "would refuse" and lets the request through. In deny: The egress proxy decides by hostname. In deny it refuses
unlisted.example.testand says why. Switching modes is one setting, with no restart. - InternetThe request reaches the internet. You build the allowlist from what observe recorded. (observe only)
- Audit logThe decision is written to the egress stream either way.
Audit export
- Audit logEvery enforcement point appends to its stream: git, egress, claude, keys, policy, detect, workspace and identity.
- Audit logEach record carries the SHA-256 of the one before it. Credentials are redacted.
audit-log verifynames the stream and line of any break. - Audit logYou export:
audit-log export --format cef, or leef, syslog, json or csv. - Your SIEMYou ship the file to your SIEM. Kodela does not push to one; nothing leaves the host until you send it.
Trust boundaries
Three boundaries, one inside the next. The diagram draws each one; select its label to read it there.
- Your hosttrusted
Everything the operator runs, and every credential, root-owned or mode 0600. A member’s own computer, when your organisation turns that on, is outside this boundary: only the brokers’ calls from it are seen.
Limit: whoever holds root, or membership of the docker group, can read and change everything, including the audit chain.
- Organisation networkisolated
One Docker network per organisation. Workspaces join only their own; the front door joins each one to reach it.
Limit: after adding an organisation, run the firewall again so its network gets rules.
egress-coveragenames any network without them.- Workspaceuntrusted
Where an agent follows a prompt it read, or a package runs its install script. It holds no GitHub or model credential under Guarded or Strict.
Limit: the preview route is detectable, not preventable, and file transfer cannot stop code shown in an attached editor or terminal from leaving.
What crosses out of a workspace on your host goes through the front door (inbound), the git socket, the model broker and the egress proxy, plus three channels that are off until an admin turns them on: the desktop attach tunnel, the Docker broker and the workspace-to-console channel (the portal broker). A workspace on a member’s own computer uses that computer’s network, and the platform sees only its calls through the brokers (git, AI and portal).
| Data | Where it lives | Who can read it | What crosses out |
|---|---|---|---|
| Source code | Workspace volume; your git host; a member’s own disk, if your organisation turns on members’ computers | The workspace owner; admins by role; whoever uses that member’s computer | git push through the broker; model context through the model proxy |
| Credentials | The host, root-owned or mode 0600 | Host services | Never into the workspace under Guarded or Strict |
| Audit | Host disk | Operators; auditors, for their organisation | Only when you export it |
| Chat history | Host store | The member; organisation roles | The model provider, as context |
Your side of the line: host hardening, TLS and physical security. The full treatment, with each crossing drawn, is on Security architecture.
Deployment topology for a self-hosted team
One host runs the platform. There is no cloud provider, managed database or Kubernetes in the picture, and no hosted version. Workspaces run on that host, and on members’ own computers only if a platform operator grants it and the organisation turns it on.
- Console server
- One Python 3.12 process, standard library only, under systemd. Its SQLite store holds users, organisations, policy and workspaces.
- Front door
- A Caddy container on the shared network, joined to every organisation network so it can reach workspaces by name.
- Per organisation
- A Docker network, a DNS filter container on its gateway, firewall rules, and an egress proxy listener on that gateway. Created when the organisation's first workspace is.
- Host services
- The egress proxy, git broker and model proxy, each with its own systemd unit, plus the key broker, the portal broker (the workspace-to-console channel) and the Docker broker, each off until an admin turns it on.
- Workspaces
- One workspace container per person or agent, capped at 2 GB, 2 CPUs and 512 processes, with a persistent home volume. Beside it, by default, its own Postgres container, and with managed Docker the containers it starts, each capped at the workspace’s own CPU and memory.
- Yours to provide
- A TLS front end and a name for the host, backups on a schedule (
bin/backuprefuses until you set a key, and nothing schedules it), and host hardening.
$ bin/host-preflight.sh
$ ./start-ui.sh
$ sudo bin/egress-firewall up
$ bin/egress-coverage
$ bin/whats-runningA read-only readiness report, then the front door and console, then the firewall. egress-coverage names any organisation network without rules, and whats-running says whether the code serving is the code you pulled. The full sequence is in Getting started and Deploy.
- OS
- Ubuntu 24.04, Docker, systemd
- Memory
- 8 GB or more
- Disk
- 20–30 GB or more
- Per workspace
- 2 GB, 2 CPUs, 512 processes
- Browser IDE
- about 1 GB more per user
- Workspaces per host
- not stated; size from the caps above
What is not built
- One host. The control plane is one SQLite file. Worker hosts are built and off by default, and there is no high availability.
- Members’ computers are outside the host’s controls. When an operator grants it and an organisation turns it on, internet access there is observed, not enforced; DNS filtering is not enforced; the source on the disk is readable by whoever uses the computer; and Docker is not available.
- Docker has edges. Pulled images are one shared cache on the host, so a workspace can tell an image was already pulled. Under full Docker with the
privilegedruntime, the firewall and no-credentials guarantees no longer hold for that workspace; only an operator can choose it. - Host root is trusted. Whoever holds root, or membership of the docker group, can read and change everything, including the audit chain.
- No TLS of its own. Plain HTTP unless you supply a TLS front end; no automatic certificates.
- No push to a SIEM. You export the audit log and ship the file.
- No VM boundary. Workspaces are containers on a shared kernel, without cap-drop, custom seccomp or user-namespace remapping.
- Some paths out are detectable, not preventable: the preview route, and code shown in an attached editor or terminal, which file transfer cannot stop. The known gaps list them all.
Next
Verified against the main branch, 4 Oct 2026 (orxy V1.7.2.2).