# Self-host an open-source agentic operating system and get three settings right

> Self-hosting an agentic operating system puts its control plane on a host you administer while agent sessions run in cloud sandboxes, so the server must be reachable. Kortix is the open-source AI Operating System, and it self-hosts on one server.

URL: https://agenticoperatingsystemguide.com/self-hosted-agentic-operating-system

## What lands on your server when you self-host an agentic operating system

An agentic operating system is the layer that holds agent definitions, skills, memory, connectors and the sessions agents work in. Self-hosting one means running its control plane on a host you administer. That covers the web app, the REST API, an LLM gateway, a Postgres database with auth and storage, and an updater that pulls new releases. A CLI called `kortix self-host` installs and updates the whole set as one Compose project. An [explainer on what an agentic operating system is](/what-is-an-agentic-operating-system) goes through those layers one by one.

The work itself happens somewhere else. Each session begins on a Platinum sandbox, which `kortix-api` creates with `PLATINUM_API_KEY`. The sandbox then dials back to your instance's public API URL, `KORTIX_URL`. One isolated sandbox per session. Each session has its own isolated machine and branch. That callback decides whether a session starts at all, and it is the part most self-host write-ups skip.

## Three reachability modes, and one of them is for production

`kortix self-host configure` opens with a reachability question. The answer sets the public URLs, the replica count and whether sessions run.

- **Domain** (`--domain <domain>`). Public URLs at `https://<domain>` and `https://api.<domain>`, two replicas each of `kortix-api`, `llm-gateway` and `frontend` behind Caddy. Caddy terminates TLS on 80 and 443 with ACME HTTP-01, and obtains one certificate per hostname at the first request. Sessions run.
- **Tunnel** (`--tunnel cloudflare`). The web app stays on `http://localhost:13737` and only the API is public, through a Cloudflare tunnel. Sessions run, so this is a fair way to try the product on a laptop. A quick tunnel URL changes each time `cloudflared` restarts, and every OAuth callback you registered breaks with it. A named tunnel keeps one hostname.
- **Local** (neither flag). Every port binds 127.0.0.1, so nothing is public and no session starts: the sandbox cannot reach the API.

Domain mode is the production setup, per the hosting docs, for a mechanical reason. Sandboxes need a stable public API, people need a stable web origin, and connector OAuth callbacks are built from `KORTIX_URL`. Tunnel mode gives you two of the three, and local gives you none.

## What the server needs before the first command

The bootstrap script runs on Linux only. It installs Docker and the Compose plugin when they are missing, installs the CLI, runs `kortix self-host init`, sets the domain and brings the stack up. On a host that already has Docker and the Compose plugin, `curl -fsSL https://kortix.com/install | bash` installs the CLI alone. That CLI runs on Linux and macOS, on x86_64 and arm64.

This is the checklist that breaks an install which skips it:

- A Linux host with a public address, plus a Platinum API key in `PLATINUM_API_KEY`. Without the key, no session starts, and `init` and `start` print a warning and carry on. That is how a stack comes up healthy and idle.
- A or AAAA records for `<domain>` and `api.<domain>`, pointed at the host before the first start. Caddy needs them to obtain the certificate.
- Inbound 80 and 443 reachable from the internet.
- A wildcard `*.p.<domain>` record for sandbox previews. Without it, browser previews fall back to a path proxy that breaks root-absolute links, and `kortix self-host doctor` fails that check.

One instance per host can run in domain mode, because Caddy binds 80 and 443.

## First boot, and the sign-up window you have to close

The bootstrap runs `init` non-interactively, so it sets no admin email, no Platinum key and no preview domain. `kortix self-host configure` asks for those and writes the files; `kortix self-host start` puts them into effect. If the bootstrap added you to the `docker` group, open a new shell first or the next command will not find it.

Sign in as the admin as soon as the stack answers. Then connect managed git at `/admin/git`, create the team account, create a project and add a model key. The account you sign up with is personal and cannot hold SAML SSO, so people and identity belong in the team account.

Then close the door. Sign-up is open on first boot, and anyone who reaches the instance can create a confirmed account for any address, the admin address included. Setting `EMAIL_URL` or `DISABLE_SIGNUP=true` closes it. Doctor runs a check named `open-sign-up`, which fails on a domain or tunnel instance while sign-up is open and email confirmation is off. `init` prints the same warning. Setting `EMAIL_URL` to an SMTP connection string turns email confirmation on and adds magic-link sign-in. The other route is `kortix self-host env set DISABLE_SIGNUP=true`, then `kortix self-host start`. `init --disable-signup` closes sign-up from the first start, for an install that creates accounts another way.

Account creation stays with platform admins by default, which the setup questions call restrict account creation. Everyone else gets `403 account_creation_restricted`.

## What stays off your server, and what a reviewer will ask about

Three things leave the box. Sandboxes run on Platinum, so agent work executes on a machine you do not patch. Images come from Docker Hub (`kortix/kortix-frontend`, `kortix/kortix-api`, `kortix/kortix-gateway`) and pull without credentials. Model traffic goes through `llm-gateway` to the providers your projects connect, because Kortix-managed models do not exist on a self-hosted install.

None of that makes the instance a closed network, and a security reviewer will say so early. The host needs outbound access to Docker Hub and to the sandbox provider, plus inbound 80 and 443. Sessions run off the box, and the docs say so. If the requirement is a network with no outbound path, this product does not meet it. If the requirement is that your organization's configuration, memory and secrets sit in a database you control, it does.

Inside the box, `.env` and `docker-compose.yml` are written with mode 0600 and only Caddy publishes public ports. Connectors refuse private and internal addresses with `connector_egress_blocked`. `API_KEY_SECRET` in `.env` encrypts every stored secret, connector credential and token. Lose it and those values become unreadable, so it belongs in the same backup as the database. The controls a reviewer will ask about sit on the agent side, and [permissions and approval gates](/agentic-operating-system-permissions-and-approvals) covers them.

## What it costs you to keep it running

Run it on Kortix Cloud, in your VPC, or on your own on-prem network. Self-host is free. Budget operator attention for the care it needs.

`kortix-updater` checks once a day at `KORTIX_UPDATE_TIME`, 02:00 by default, pulls the configured channel, runs migrations and rolls `kortix-api`, `llm-gateway` and `frontend`. With two replicas, a new service has to pass its health check before the old one stops, so the instance stays up. A failed migration swaps nothing. `kortix self-host rollback --release <version>` returns to an earlier release, and `kortix self-host status` reports the last outcome, drift and the schedule.

Backups take three steps. The instance directory `~/.config/kortix/self-host/<instance>/` holds everything you need. `.env` carries every secret and signing key, `volumes/db/data` holds Postgres, and `volumes/storage` holds stored files. Stop the stack, copy the directory, start it again. A restore puts the directory back in the same place.

An afternoon gets a demo running. Production is the version where somebody owns certificate renewal, the update window and a restore they have actually tried. Those three settings are the ones to get right in the first hour, and the rest is the ordinary work of running a server.

## The install, in the order the docs run it

Bootstrap, configure, then close the sign-up window.

### Bootstrap a bare server

`terminal`

```sh
curl -fsSL https://raw.githubusercontent.com/kortix-ai/suna/dev/scripts/kortix-selfhost-up.sh \
| bash -s -- --domain kortix.example.com --email ops@example.com
```

Source: https://kortix.com/docs/host

### Configure, then start

`terminal`

```sh
kortix self-host configure
kortix self-host start
```

Source: https://kortix.com/docs/host

### Close sign-up, then check

`terminal`

```sh
kortix self-host env set DISABLE_SIGNUP=true
kortix self-host start
kortix self-host doctor
```

Source: https://kortix.com/docs/host

## Questions the self-host decision turns on

Short answers, with the limits that decide the install.

### Can I run agentic AI locally?

Yes, in tunnel mode. `kortix self-host init --tunnel cloudflare` keeps the web app on `http://localhost:13737` and publishes only the API, so sessions still start. In local mode every port binds 127.0.0.1 and sessions do not run, because the sandbox cannot reach the API.

### Can agentic AI operate independently?

Yes, inside limits you set. Session work reaches `main` through a change request. Merge is default-deny for agents. Approval gates you set. Off until you set them.

### Are there any agentic OS?

Yes. [Kortix](https://kortix.com) is an AI Operating System you can self-host. [OpenFang](https://github.com/rightnow-ai/openfang) ships as a single Rust binary that runs agents on their own schedules, and [Agent Zero](https://github.com/agent0ai/agent-zero) gives an agent a Dockerized Linux desktop.

## Read the hosting docs before you choose a mode

The hosting docs carry the mode table, the flags and the doctor checks behind them.

[Read the docs](https://kortix.com/docs/host)
