DockerSelf-HostingAIAI Coding Agents

Kortix CompanyOS (formerly Suna): self-host the AI agent platform on your own server (Linux, Windows, Mac)

Before you start

  • 20 min read
  • 26 to run in terminal
  • 1 file content

Boxes marked Run in terminal are what you type; plain text explains why. Check what you need first

What you get in one minute#

Kortix CompanyOS (the project formerly called Suna) is an open-source platform where AI agents do work for you and your team, each session in its own cloud computer, and you can run the control side on your own Linux server.

Kortix official logo

Logo: the official Kortix project (github.com/kortix-ai/suna)

Agents, skills, memory and connectors live in one git repository you own, and a person approves what the agents change. The repository address still says suna; the README now says Kortix CompanyOS. Old Suna tutorials describe an older setup.

Say it plainly: self-hosting here is not "everything on my machine". The web app, API, database and HTTPS run on your server. The agent sessions run in sandboxes at Platinum, a paid cloud service, and the AI models come from a provider you pay with your own key. Your server must be reachable from the internet so those sandboxes can call it back.

WhatValue (official docs, read October 2026)
Current versionv0.14.12, released 30 October 2026 (release page)
Default update trackstable (a release promoted after it runs in production)
LicenceElastic License 2.0: free to use and self-host, but you may not sell it to others as a hosted service
Time neededAbout 45 minutes plus DNS waiting (our estimate, not measured)
Server sizeNot published. Per-container memory limits are listed under Performance
Ports80 and 443 open to the internet. Loopback only: frontend 13737, API 13738, Supabase 13740
Official docskortix.com/docs/host and the repository

At a glance:

  • What it is: a company operating system for AI agents: agents, shared skills, a drive, connectors (3,000+ apps plus MCP) and scheduled or webhook triggers.
  • Local on your server: web app, REST API, LLM gateway, a full Supabase stack with Postgres, a file store for recordings, and Caddy for HTTPS.
  • Not local: Platinum sandboxes (every session), the Drive and App volumes (stored at Platinum), your model provider, and GitHub for project repositories.
  • You must bring: a Linux server with a public IP, a domain with DNS records, a Platinum API key and a model provider key.
  • Platforms: the server must be Linux. Windows and Mac are admin computers: you use a browser and SSH there. The kortix command line runs on Linux and Mac, and on Windows inside WSL.
  • Cost: the software is free; Platinum bills prepaid credits per second (see Performance).

How it fits together#

You open your domain in a browser. Caddy on your server answers with a Let's Encrypt certificate and routes to the web app and the API. The API stores data in the local database, starts a Platinum sandbox for each session, calls your model provider and pushes project work to GitHub.

Left to right: your browser reaches Caddy on ports 80 and 443, which routes to the frontend and API on your Linux server; the API stores data in Supabase and Postgres on the same server, and calls outside services: a Platinum sandbox per session, your model provider and GitHub

Drawn for this guide from the official self-hosting page. Orange boxes are outside services and need the internet.

Before you start#

NeedDetail (official docs)
ServerA Linux server with a public IP. The bootstrap script runs on Linux only and installs Docker Engine and the Compose plugin if missing. No minimum CPU, RAM or disk is published
DNSA or AAAA records for kortix.example.com and api.kortix.example.com, plus a wildcard *.p.kortix.example.com for previews
Ports80 and 443 open inbound. The docs use them for the certificate (HTTP-01)
PlatinumAn account and an API key (PLATINUM_API_KEY). Without it sessions do not start and projects have no Drive
Model keyOne provider key, added in the web app after the first sign-in. A self-hosted instance has no Kortix-managed models
GitHubA GitHub identity for managed repositories, set at /admin/git after sign-in (or link an existing repository)

Use your own domain wherever you see kortix.example.com.

Linux server: check Docker if it is already installed (the script installs it otherwise):

Run in terminalbash
docker --version
docker compose version

Windows: an admin computer only. Check the SSH client you will use to reach the server:

Run in terminalpowershell
ssh -V

Mac: an admin computer only. Same check in Terminal:

Run in terminalbash
ssh -V

Checklist:

  • [ ] A Linux server you can SSH into, with sudo
  • [ ] DNS records created and pointing at the server's public IP
  • [ ] Ports 80 and 443 free on the server and open in its firewall
  • [ ] Platinum API key and a model provider key ready, kept in a password manager
  • [ ] You will back up .env: it holds the encryption key API_KEY_SECRET

Tested by DIY Lab Hub: not yet. This needs a public domain and paid keys, so every command comes from the official docs and the bootstrap script, read in October 2026. We did not run them. The docs publish no sample output, so "Check it worked" says what to look for.

Step 1: Create the DNS records and collect your keys#

The records must exist before the first start, because Caddy needs them to get the certificate. At your DNS provider, create A (or AAAA) records for kortix.example.com and api.kortix.example.com pointing at the server's public IP, plus a wildcard A record for *.p.kortix.example.com. At Platinum, create an API key. Keep both keys out of chat windows and screenshots.

Linux#

Check the records from any Linux computer (any random name tests the wildcard):

Run in terminalbash
getent hosts kortix.example.com
getent hosts api.kortix.example.com
getent hosts test1.p.kortix.example.com

Windows (PowerShell)#

Codepowershell
Resolve-DnsName kortix.example.com -Type A
Resolve-DnsName api.kortix.example.com -Type A
Resolve-DnsName test1.p.kortix.example.com -Type A

Mac (Terminal)#

Run in terminalbash
dig +short kortix.example.com
dig +short api.kortix.example.com
dig +short test1.p.kortix.example.com

Check it worked. All three names return your server's public IP. If one is empty, wait for DNS and ask again.

Tip: Create the wildcard *.p.<domain> record now. The docs say that without it browser previews fall back to a path proxy that breaks links, and kortix self-host doctor fails.

Step 2: Run the bootstrap script on the server#

The official bootstrap installs Docker if needed, installs the kortix command line, writes the Compose files and starts the stack with a TLS certificate. It is safe to run again. We read the script before writing this step: it takes the key from the environment variable PLATINUM_API_KEY if you set it, so the key stays out of your shell history. The docs run it straight from the dev branch of the repository; we download it first so you can read it.

Linux#

Run this on the server:

Run in terminalbash
read -rs -p "Platinum API key: " PLATINUM_API_KEY; echo; export PLATINUM_API_KEY
curl -fsSL https://raw.githubusercontent.com/kortix-ai/suna/dev/scripts/kortix-selfhost-up.sh -o kortix-selfhost-up.sh
less kortix-selfhost-up.sh
bash kortix-selfhost-up.sh --domain kortix.example.com --email [email protected]

--domain turns on Caddy and TLS. --email is the contact for the certificate. The first image pull can take several minutes.

Windows (PowerShell)#

Not supported as the server. The bootstrap script runs on Linux only, and a server must be reachable from the internet. Log in to your Linux server from PowerShell, then run the Linux commands above inside that session:

Run in terminalpowershell
ssh <your-user>@<your-server-address>

Mac (Terminal)#

Not supported as the server. Log in to your Linux server and run the Linux commands there:

Run in terminalbash
ssh <your-user>@<your-server-address>

Check it worked. The script ends with "kortix self-host is up." and lists the commands for status, logs, doctor, configure and update. Check the containers:

Run in terminalbash
kortix self-host ps

Tip: If the script says it added your user to the docker group, open a new shell before the next kortix self-host command, as the docs ask.

Step 3: Answer the setup questions and start#

The bootstrap sets no admin email and no preview domain, so you run configure once. Each answer is pre-filled with the current value, and Enter keeps it.

Linux#

On the server:

Run in terminalbash
kortix self-host configure
kortix self-host start

Give your admin email and the preview domain p.kortix.example.com. Press Enter to keep the Platinum key the bootstrap set. configure only writes files; start applies them.

Windows (PowerShell)#

Run the Linux commands in your SSH session to the server.

Mac (Terminal)#

Run the Linux commands in your SSH session to the server.

Check it worked. From any computer:

Run in terminalbash
curl -I https://kortix.example.com

You should see an HTTP status line over HTTPS with no certificate error. On the server, kortix self-host status shows the containers, the last update and the schedule. On Windows use curl.exe -I https://kortix.example.com in PowerShell.

Tip: Caddy asks for each hostname's certificate on the first request, so the first visit can be slow. A lasting certificate error means DNS or port 80 is wrong.

Step 4: Sign up as admin, then close the doors#

The docs are firm about this: until you set EMAIL_URL or DISABLE_SIGNUP=true, anyone who reaches the instance can create a confirmed account for any address, the admin address included. Do it right after the stack starts.

Open https://kortix.example.com in your browser (Windows, Mac and Linux alike) and sign up with the address you gave as admin. Then, on the server:

Linux#

Either connect email (a bare EMAIL_URL makes the command ask for the value, so the password stays out of your history):

Run in terminalbash
kortix self-host env set EMAIL_URL

Or, once your team has signed up, close sign-up:

Run in terminalbash
kortix self-host env set DISABLE_SIGNUP=true
kortix self-host start
kortix self-host doctor

Windows (PowerShell)#

Run the Linux commands in your SSH session to the server.

Mac (Terminal)#

Run the Linux commands in your SSH session to the server.

Check it worked. kortix self-host doctor exits 0 and prints no failing check. It checks Docker, the Compose file, the preview domain, the email setting and open sign-up. The docs publish no sample output.

Tip: Closing sign-up with DISABLE_SIGNUP=true blocks everyone, the admin included, if done before your own account exists. Sign up first.

Step 5: Connect GitHub, add a model key, run a session#

These are browser steps, the same on every system.

  1. Connect managed git. Open /admin/git. Kortix creates every project repository through this one GitHub identity. Pick "Create a GitHub App" (the docs recommend it), paste an existing App, or use an access token.
  2. Create the team account. Your sign-up account is personal and cannot hold single sign-on. Create one project at /new, then open the project menu, choose Switch Project, then Create an account. Only platform admins can create accounts by default.
  3. Create a project in the team account.
  4. Add a model key in the project: Customize, then Models, then Providers. Each project needs its own key.
  5. Start a session from the project page.

Linux#

The command-line way to add a model key (run from a computer with the CLI, see Step 6):

Run in terminalbash
kortix providers set <provider>

Windows (PowerShell)#

Use the web app. The command line runs in WSL; see Step 6.

Mac (Terminal)#

Same command as Linux:

Run in terminalbash
kortix providers set <provider>

Check it worked. The session starts, a sandbox is created and the agent replies. If the session never starts, the Platinum key is missing or wrong (see Troubleshooting).

Tip: Start with the docs' own small prompt: "Summarize this week's commits and open a change request". Nothing reaches main until a person approves.

Step 6: Use the command line from your own computer (optional)#

The kortix command line does from a terminal what the web app does. It runs on Linux and Mac, and on Windows inside WSL.

Linux#

Run in terminalbash
curl -fsSL https://kortix.com/install | bash
kortix hosts add mycompany --url https://api.kortix.example.com --login
kortix whoami

Windows (PowerShell)#

The installer does not run natively on Windows. Open your WSL shell and use the Linux commands:

Run in terminalpowershell
wsl

Mac (Terminal)#

Same commands as Linux:

Run in terminalbash
curl -fsSL https://kortix.com/install | bash
kortix hosts add mycompany --url https://api.kortix.example.com --login
kortix whoami

Check it worked. kortix whoami shows the host mycompany, your user and the active account. The browser opens so you can approve the login.

Put it behind HTTPS (with or without Traefik)#

This stack already includes HTTPS: in domain mode a bundled Caddy takes ports 80 and 443 and gets Let's Encrypt certificates by itself. Usually you need nothing more. Both routes need a public domain, because the Platinum sandboxes must reach your API.

With Traefik#

There is no official Traefik recipe, so this guide gives no Traefik labels. The generated stack has its own Caddy, and the docs say only one domain-mode instance per server can run because Caddy binds 80 and 443. If Traefik already owns those ports on your server, the supported choice is a second server or virtual machine for Kortix. Putting Traefik in front is possible, but the docs do not cover it and you would write the routes yourself.

Without Traefik: Caddy#

This is the default and the supported route. --domain in Step 2 turned on the bundled Caddy. You do not write a Caddyfile; kortix self-host init writes one. For orientation, this is the routing it does, taken from the docs' routing table. It is a simplified sketch, not the generated file, which also adds health checks, two replicas, an HSTS header and the wildcard blocks:

File contenttext
kortix.example.com {
    @supabase path /rest/v1/* /auth/v1/* /storage/v1/* /realtime/v1/* /functions/v1/* /graphql/v1/*
    handle @supabase {
        reverse_proxy supabase-kong:8000
    }
    handle {
        reverse_proxy frontend:3000
    }
}

api.kortix.example.com {
    handle /v1/llm* {
        reverse_proxy llm-gateway:8090
    }
    handle {
        reverse_proxy kortix-api:8008
    }
}

What this means for you:

CaseWhat to do
Public domainCreate the DNS records, open ports 80 and 443, run Step 2 with --domain. Certificates are automatic.
Home only, no public domainA local certificate (tls internal) does not help here. Without a public address the sandboxes cannot reach your API, so sessions do not run. The docs call the no-domain mode "local": it binds loopback ports only and is for looking around.

Check it worked. curl -I https://kortix.example.com and curl -I https://api.kortix.example.com both return an HTTP status line over HTTPS.

Security and testing#

ControlHow (official docs)
Public portsOnly Caddy publishes 80 and 443. Every other published port binds 127.0.0.1
Secrets file.env and docker-compose.yml are written with mode 0600. Keep it that way
Sign-upSet EMAIL_URL or DISABLE_SIGNUP=true (Step 4). Account creation is restricted to platform admins by default
ConnectorsThey refuse private and internal addresses (connector_egress_blocked). List allowed internal hosts in KORTIX_CONNECTOR_EGRESS_ALLOW_HOSTS
Supabase StudioAnswers on 127.0.0.1:13740 on the server only. Use an SSH tunnel
Encryption keyAPI_KEY_SECRET in .env encrypts every stored secret. Back it up; the CLI refuses to rotate it

Quick tests, on the server:

Run in terminalbash
kortix self-host doctor
kortix self-host ps
kortix self-host logs kortix-api

What leaves your server: calls to Platinum, your model provider and GitHub, image pulls from Docker Hub, and the optional app catalog if you set COMPOSIO_API_KEY. The README says so: this is a self-hosted install, not a disconnected one.

Licence note: a separate free white-label licence exists for reselling. Its one requirement is Platinum as your exclusive compute provider, and Kortix may end it with notice.

Common mistakes#

These come from the official docs' own warnings, the project's issue tracker, and typical AI assistant answers.

MistakeWhy it happensDo this instead
Installing without --domain and expecting agents to workThe no-domain "local" mode binds loopback ports only. The docs say sessions do not run, because the sandbox cannot reach your APIUse a domain and a public server for real use; treat local mode as a look around
Leaving out the Platinum keyEverything looks fine until a session fails. The docs: without PLATINUM_API_KEY sessions do not start and projects have no DriveSet the key in Step 2, or later with kortix self-host configure
Leaving sign-up openA new instance confirms every sign-up without an email. doctor reports open-sign-upSign up as admin first, then set EMAIL_URL or DISABLE_SIGNUP=true
Forgetting the *.p.<domain> wildcard recordThe page works without it, so people skip it. Previews then use a path proxy that breaks root-absolute links, and doctor failsAdd the wildcard A record and set the preview domain in configure
Losing .envIt looks like a plain config file. API_KEY_SECRET in it decrypts every stored key and token; without it you get SECRET_UNDECRYPTABLEBack up the instance folder (see Updates and backups) and keep a copy off the server
Following an old Suna tutorialThe repository address still says suna. Older setups used your own Supabase project and a Daytona key; the bootstrap script calls Daytona a legacy fallback. Issue #2459 shows an old Supabase Cloud setup failing on WSL2Use only the current self-hosting page and the bootstrap script from this guide
Running the server on Windows or MacThe bootstrap script exits on non-Linux systems. Issues #3072 and #3073 (April 2026, closed) report a Mac Docker Desktop install stuck on "Unreachable" in an old versionUse a Linux server. Windows and Mac are for the browser, SSH and the CLI
Pinning a version and expecting auto-updatesA pinned --tag wins over the channel. The docs say a pin holds through every daily updateRun kortix self-host update when you want to move; unpin by updating without --tag
Selling access to your instance"Open source" suggests anything goes. Elastic License 2.0 forbids a hosted service for othersUse it for your own team, or read the white-label licence
AI assistants: mixing old Suna steps into KortixAssistants can repeat older tutorials: a Supabase project and a Daytona key in a .env, or a plain docker compose up in the cloned repository. The current stack is generated by kortix self-hostRun only commands from the current docs and this guide; check every flag with kortix self-host --help

Tip: Before running any command an AI assistant suggests, search the official self-hosting page for it. The CLI changed a lot between 0.8.x and 0.14.x.

Tip: Test one tiny session before inviting a team. A working sign-in does not prove the sandbox, the model key and GitHub all work.

Troubleshooting#

ProblemSolution
Sessions never startCheck the Platinum key: kortix self-host env ls (secrets are masked), then kortix self-host configure and start. Look at kortix self-host logs kortix-api
kortix self-host doctor fails preview-originsAdd the wildcard record *.p.<domain>, then kortix self-host env set KORTIX_PREVIEW_BASE_DOMAIN=p.<domain> KORTIX_PREVIEW_ALLOW_DIRECT_EDGE=true
doctor fails open-sign-upSet EMAIL_URL, or DISABLE_SIGNUP=true once your team is in
Certificate error on the first visitCheck DNS for both hostnames and that ports 80 and 443 reach the server. Caddy needs HTTP-01
New project form: "Kortix-managed repositories are not available on this instance."Set up managed git at /admin/git
403 sso_personal_accountYour sign-up account is personal. Create a team account (Step 5) and set up SSO there
409 SECRET_UNDECRYPTABLE or credential_undecryptableAPI_KEY_SECRET changed or was lost. Restore .env from a backup, or enter each secret again
session log release refused during an updatePin the converting version first: kortix self-host update --tag 0.14.9, wait for the log line, then kortix self-host update
A change does not take effectRun kortix self-host start; it recreates every service whose configuration changed

Known bugs#

The issue tracker had no open issues when we looked in October 2026. The closed April 2026 reports (#3070, #3072, #3073, #3086) describe the older local-mode installer. Issue #3086 notes an installer exit on a flaky registry or DNS lookup during the image pull; if your first start stops with a network error, run kortix self-host start again.

Diagnostics:

Run in terminalbash
kortix self-host status
kortix self-host ps
kortix self-host logs kortix-api
kortix self-host doctor --json

Updates and backups#

Update. Auto-update is on by default: a container named kortix-updater pulls new images once a day at 02:00 New York time. It checks disk space, runs the database migration, then rolls the services; a failed migration or swap keeps the previous version serving. To do it yourself:

Run in terminalbash
kortix self-host version
kortix self-host update
kortix self-host update --tag 0.14.12
kortix self-host rollback --release <version>

version shows the running version, the latest and the channel. A --tag pin holds through the daily runs. The stable images were last updated on 22 October 2026, so they can be older than 0.14.12; kortix self-host version shows what you run.

Back up. The docs split the data in two: the instance folder ~/.config/kortix/self-host/<instance>/ (it holds .env, the database and the stored files) and four Docker volumes. Stop the stack so the files are consistent. This script is the docs' own, with the instance named default:

Run in terminalbash
kortix self-host stop
cd ~
sudo tar -czf kortix-backup.tgz -C ~/.config/kortix/self-host default
for v in db-config kortix-capture-data kortix-caddy-data kortix-updater-state; do
  docker run --rm -v "kortix-default_$v":/data -v "$PWD":/backup alpine:3.20 \
    tar -czf "/backup/$v.tgz" -C /data .
done
kortix self-host start
chmod 600 kortix-backup.tgz *.tgz

The backup holds every secret, so keep it private. Drive folders, App volumes and each session's /workspace live at Platinum and are not in this backup. To run it nightly at 03:00 on Linux, put the same commands in a script and add a crontab line; the stack is stopped for the duration, so choose a quiet hour.

Restore. On a server with Docker and the CLI, put the archives in your home folder, then:

Run in terminalbash
mkdir -p ~/.config/kortix/self-host
sudo tar -xzf kortix-backup.tgz -C ~/.config/kortix/self-host
for v in db-config kortix-capture-data kortix-caddy-data kortix-updater-state; do
  docker run --rm -v "kortix-default_$v":/data -v "$PWD":/backup alpine:3.20 \
    tar -xzf "/backup/$v.tgz" -C /data
done
kortix self-host start

start warns that each volume was not created by Docker Compose; the docs call it harmless. Test a restore on a spare server first. kortix self-host uninstall deletes the database, files, recordings and certificates and cannot be undone.

Windows (PowerShell)#

Copy the backup off the Linux server from your PC (it has the keys, so store it somewhere safe):

Run in terminalpowershell
scp <your-user>@<your-server-address>:~/kortix-backup.tgz .

Mac (Terminal)#

Use the same scp command from Terminal:

Run in terminalbash
scp <your-user>@<your-server-address>:~/kortix-backup.tgz .

Performance and resources#

The docs publish no required CPU, RAM or disk for the server, so this guide gives none. They publish these defaults:

SettingDefault
kortix-api memory limit (KORTIX_API_MEMORY_LIMIT)2048m
llm-gateway memory limit (KORTIX_GATEWAY_MEMORY_LIMIT)2048m
frontend memory limit (KORTIX_FRONTEND_MEMORY_LIMIT)512m
Postgres memory limit1280m, fixed
Replicas in domain mode2 each of API, gateway and frontend
Logs3 files of 10 MB per container
Free disk the updater needs2048 MB (KORTIX_MIN_FREE_DISK_MB)
Sandbox stops after idle time15 minutes (KORTIX_SANDBOX_AUTOSTOP_MINUTES)
Default sandbox size2 vCPU, 4 GB RAM, 20 GB disk

These are ceilings per container, not measured use. Measure your own server:

Run in terminalbash
docker stats --no-stream
df -h

Cost note. Platinum's website lists $0.0324 per vCPU-hour and $0.0108 per GB of RAM-hour, billed per second while a sandbox runs, with prepaid credits and no subscription. By our arithmetic a default 2 vCPU, 4 GB sandbox is about 11 cents per running hour. This is not an official figure; the page marked its prices verified in July 2026. Model calls are billed by your provider on top.

FAQ#

Is Kortix CompanyOS the same as Suna? It is the same repository and project, renamed. The README now says Kortix CompanyOS. Older Suna guides describe an older setup.

Is it free? The software is free under Elastic License 2.0. Sandboxes and model calls cost money.

Can I run it fully offline or on my own models only? Not from what the docs say. Sessions run in Platinum sandboxes, and the stack pulls images from Docker Hub. A project can connect any provider with your own key, but the docs do not describe a local-model setup, and we did not test one.

Can I run it on Windows or a Mac? Not as the server. Use a Linux server. Windows and Mac work as admin computers: browser, SSH, and the CLI (on Windows inside WSL).

Sources#

Checked against the official docs on 2026-10-31.