Run your own copy
Run OpenKuasa on your laptop with Docker, or self-host it on your own Supabase project and any Node server.
OpenKuasa is free to self-host under AGPL-3.0. The quickest way is Docker on your own computer. You can also point it at your own Supabase project and run it on any Node server.
Run it on your laptop with Docker
Before you start
- Docker Desktop (Mac or Windows), or Docker Engine with Compose v2.24 or newer (Linux).
- Nothing else. No Supabase account and no Node.
Steps
git clone --depth 1 https://github.com/OpenKuasa/OpenKuasa.git
cd OpenKuasa
cp .env.example .env # fill in your own keys (optional ones can stay blank)
docker compose up -d
Open http://localhost:58272. Sign up to get your own workspace, or press "Try the demo" to see the sample company.
Sign-up is confirmed for you locally, so you don't need email to get started. To get password-reset and invite emails, start with docker compose --profile mail up -d and read them in the mail viewer at http://localhost:58274.
Every key in .env is optional. Add OPENROUTER_API_KEY to turn on the AI chat. See AI models and keys.
Update, stop and wipe
git pull && docker compose pull && docker compose up -d # update
docker compose down # stop, keeps your data
docker compose down -v # wipe, deletes all local data
Troubleshooting
- Port already in use. The app uses ports 58272 and 58273 (and 58274 with the mail viewer). On macOS these sit in a range the system lends out briefly to other apps, so another app can hold one now and then. Find it with
lsof -i :58273(swap in the port from the error). Quit that app or restart the Mac, then rundocker compose up -dagain. - Docker isn't running. Start Docker Desktop and wait until it says it is running.
- "dependency failed to start", or the page never loads. Run
docker compose logs migrate(ordocker compose logs init) to see why. Fix it, then rundocker compose up -dagain. It carries on from where it stopped. - Start over completely. Run
docker compose down -v. This deletes all local data. Then rundocker compose up -d. - Changed
POSTGRES_PASSWORDafter the first run. The existing database keeps its old password. Set it before the first run, or rundocker compose down -vto start over.
On a cloud computer
To try it on a BoxCompute computer in Malaysia instead of your laptop, see Run it on BoxCompute.
Docker app with online Supabase
Use this path to run the app in Docker while your data lives in your own project on supabase.com, with Supabase's backups. You need only Docker on your machine.
Steps (online Supabase)
- Create a project on supabase.com.
- Copy the example settings:
cp .env.example .env. - In
.env, fill in from the Supabase dashboard:NEXT_PUBLIC_SUPABASE_URL(Project Settings → Data API), andNEXT_PUBLIC_SUPABASE_ANON_KEYandSUPABASE_SERVICE_ROLE_KEY(Project Settings → API Keys → Legacy API keys: the longanonandservice_rolekeys that start witheyJ).DATABASE_URL: press Connect, choose Session pooler, and copy the connection string with your database password in it. Use the pooler, not the direct connection: the direct address needs IPv6, which many networks and Docker setups don't have.
- Set up Supabase Auth once, as in step 4 of the hosted steps: site URL
http://localhost:58272(or your own address), anonymous sign-ins on if you want "Try the demo", Confirm email off unless you have set up your own email sending, and paste the email templates. - Start it:
docker compose -f docker-compose.hosted.yml up -d
Open http://localhost:58272. Every start applies new database changes to your project before the app starts. If a setting is missing, docker compose -f docker-compose.hosted.yml logs init names it.
The database connection is encrypted. To also check Supabase's certificate, install its CA certificate and add ?sslmode=verify-full to DATABASE_URL.
Update: git pull && docker compose -f docker-compose.hosted.yml pull && docker compose -f docker-compose.hosted.yml up -d. Stop: docker compose -f docker-compose.hosted.yml down. Your data stays in Supabase either way.
Hosted Supabase
Use this path to run OpenKuasa on a server without Docker, with your own Supabase project for data and sign-in and a host that runs Node.
Who can do this
Anyone running their own copy. You need access to a Supabase project and to the server you deploy on.
Before you start (hosted)
- Node 22 or newer.
- pnpm. Always use pnpm, not npm or yarn.
- A Supabase project.
Hosted steps
1. Get the code
git clone https://github.com/OpenKuasa/OpenKuasa.git
cd OpenKuasa
pnpm install
pnpm dev
Open http://localhost:3000. With no Supabase project set, the app opens in preview mode: every visitor is a read-only "Guest" in a "Preview workspace", and the screens show sample data.
2. Point it at your Supabase project
Create a .env.local file in the project root with your project's URL and anon key. In the Supabase dashboard the URL is under Project Settings → Data API, and the anon key under Project Settings → API Keys → Legacy API keys (the long key that starts with eyJ):
NEXT_PUBLIC_SUPABASE_URL=https://<your-project-ref>.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=<your-anon-key>
The rest of the app is turned on by more variables. See Environment variables.
3. Create the tables
Run the migrations once against your project:
pnpm db:migrate --apply
It asks you to type the project ref before it writes anything. See Keep the database up to date.
4. Set up Supabase Auth
In the Supabase dashboard, under Authentication:
- Enable Anonymous sign-ins. It powers the demo workspace and the tests.
- Confirm email is your choice. With it off, signup signs the person in at once and lands on
/command. With it on, signup stops at a "check your email" message, and the person confirms and then signs in. Either way, an already-registered address always gets that same "check your email" message, so the form never says which addresses have an account.- Leave it off until you set up your own email sending (Authentication → Emails → SMTP Settings). Supabase's built-in email only sends to members of your Supabase team, a few messages an hour, so anyone else who signs up never gets the confirmation email.
- Leave hCaptcha off. The sign-in forms do not send a captcha token yet, so turning hCaptcha on breaks sign-in and signup.
The sign-in email templates are in supabase/email-templates/. They are not set by the migrations: paste each file into the matching template in the Supabase dashboard (Authentication → Emails → Templates). Every link in them points at the app's /auth/confirm route.
5. Build and run it on your server
pnpm build
pnpm start
Any host that runs Node 22 and these two commands will do. openkuasa.com runs on Railway.
6. Add the scheduler
Some background work runs only when your scheduler calls it. See Scheduled jobs.
Common problems
- Every request answers
503 Service unavailable. A production server (pnpm start, or any host) refuses to serve whenNEXT_PUBLIC_SUPABASE_URLorNEXT_PUBLIC_SUPABASE_ANON_KEYis missing. The server log names the two required variables. This is on purpose: a deployment that loses a variable fails visibly instead of turning into the sample app. - You want the sample-data preview on a production build. Set
OPENKUASA_PREVIEW=1. It is read only when the Supabase values are missing, so it does nothing on a configured deployment. Do not set it on the deployment that serves your real data. - Some pages show sample data instead of yours. The database is missing a table or column that the code needs. Run
pnpm db:migrateto see which migrations your project lacks. - Rate limits count everyone together. The app tells clients apart by the
X-Real-IPheader that Railway's edge sets. On a host or proxy that does not set it, every request counts against one shared counter, which has its own, wider limit. A proxy that passes on anX-Real-IPthe client sent is worse: each client can pick its own counter and dodge the per-client limits. Have the proxy set the header itself, from the connection. - MCP limits don't add up across servers. The per-key limits on the MCP endpoint are counted in each server process's memory, so with several instances each one counts on its own, and a restart starts the count again.
- The app stops working after a quiet week. Supabase pauses a free-plan project after about a week without activity. Open the project in the Supabase dashboard and press Restore project; your data comes back as it was.
- Password-reset links are sometimes refused. If you run several instances or a serverless host, set
AUTH_COOKIE_SECRET(32+ characters). See Environment variables.