Self-hosting

Sign-in and accounts

Choose how people sign in to your Oatmilk, who may make an account, and how to manage accounts.

A self-hosted Oatmilk keeps its accounts in your own database by default, with Better Auth. It can use Clerk, a hosted sign-in service, instead. Either way, people's roles and companies are kept in Oatmilk itself.

Accounts kept here (Better Auth)Clerk
Where accounts liveYour database, in the better_auth schemaClerk's service
Sign-inEmail and password, two-step codes from an authenticator app, backup codesEverything Clerk offers, such as Google sign-in and passkeys
AI apps and the CLI sign in throughYour Oatmilk, at /api/authClerk
Works with no internetYesNo
Choose itAccounts kept here in setup, or init --auth better-authClerk in setup with its two keys, or init --auth clerk

Changing the choice rebuilds the image with bun run self-host up. Accounts don't move between the two.

Who can make an account

SettingWhoDefault
OATMILK_AUTH_SIGNUP=closedOnly people you add, and people with an invitation: to a team, as an outside accountant, or as a contractorOn a server
OATMILK_AUTH_SIGNUP=openAnyone who can open the siteOn your own computer

On a server, keep sign-up closed unless you mean to run an open service. Open sign-up asks each new person to confirm their email before they can sign in or create a company, so it needs email. Without email, open sign-up stops and asks the person to contact you.

Add people

The usual way is an invitation from Settings › Team in Oatmilk. With email on, the person gets a link; without it, copy the link and send it yourself. The person makes their account from the link and joins your company with the role you chose.

From the server's command line:

Shell
bun run self-host user add --email ada@example.com --first-name Ada --last-name Lovelace   # asks for a password
bun run self-host user list
bun run self-host user reset-password --email ada@example.com                             # signs them out everywhere

A person added this way can sign in, then create a company or accept an invitation. In scripts, pipe the password in: echo "$PASSWORD" | bun run self-host user add --email ….

Each person can create up to three companies.

What people manage themselves

In their profile, each person changes their name and password, turns on two-step sign-in, prints backup codes, and signs out devices they no longer use. Ask administrators to turn on two-step sign-in.

Sign-in for AI apps, the CLI and the API

With accounts kept here, your Oatmilk runs its own sign-in server for apps, at /api/auth:

  • AI apps connected to https://<your address>/api/mcp open your Oatmilk's consent page, where the person approves them.
  • The CLI signs in with oatmilk login --host https://<your address>, the same way. See Sign in and choose a company.
  • API keys from Developers › API keys work as on the hosted Oatmilk: oat_test_… on an install for one computer, oat_live_… on a server.

Use Clerk instead

  1. Create an application in Clerk, and copy its publishable key and secret key.
  2. In Clerk, allow your Oatmilk's address as an origin, and turn on Organizations.
  3. Run setup and choose Clerk, or:
Shell
bun run self-host init --server --domain books.example.com --auth clerk   # add --force to rewrite an existing self-host/.env

Then add both keys to self-host/.env and start it:

self-host/.env
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_live_…
CLERK_SECRET_KEY=sk_live_…
Shell
bun run self-host up

bun run self-host user only manages accounts kept here. With Clerk, manage people in Clerk's dashboard and invite them in Oatmilk.