Self-hosting
Run it on a server
Host Oatmilk for your team on a VPS or your own server at your domain, with HTTPS from Let's Encrypt.
This guide puts Oatmilk on one Linux server at your own domain, such as books.example.com, for you and your team. It works the same on Hetzner, DigitalOcean, Linode, OVH, a homelab machine or any other host with Docker. Everything runs on the server; for managed databases, see the AWS, Google Cloud and Azure guides.
1. Get a server
- Ubuntu 24.04 or another current Linux.
- 2 CPUs, 8 GB of memory and 40 GB of disk. The build needs the memory; Oatmilk itself runs in about 4 GB.
- A public IP address, with ports 80 and 443 open to the internet.
Log in with SSH as a user that can run sudo.
2. Point your domain at it
At your DNS provider, add an A record (and an AAAA record for IPv6) for the name people will open, pointing at the server's IP address:
books.example.com. A 203.0.113.10Check it from your own computer before you continue. Caddy can only get a certificate once the name leads to the server.
dig +short books.example.com3. Install Docker, Bun and Git
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker "$USER" # then log out and back in
curl -fsSL https://bun.sh/install | bash
sudo apt-get install -y git
docker compose version # 2.20 or newerIf the server has a firewall, open the web ports:
sudo ufw allow 22/tcp && sudo ufw allow 80/tcp && sudo ufw allow 443/tcp && sudo ufw enable4. Get Oatmilk and run setup
git clone https://github.com/AGI-Ventures-Canada/oatmilk.git
cd oatmilk
bun install
bun run self-host setup| Question | Answer |
|---|---|
| Where will Oatmilk run? | On a server |
| Domain people will open | books.example.com |
| Use the standard web ports, 443 and 80? | Yes |
| Which PostgreSQL database? | Run one here, or your own (see Bring your own services) |
| Which Redis? | Run one here |
| Where should files be kept? | On this machine, or an S3-compatible bucket |
| How should people sign in? | Accounts kept here |
| Who can make an account? | Only people I add or invite |
| Which AI models…? | Vercel AI Gateway with an API key, or a model server your team runs (see Use local AI models) |
| Should Oatmilk send email? | Yes, with Resend, with your Resend API key and the domain you send from |
| Create your own account now? | Yes |
| Build and start Oatmilk now? | Yes |
The first build takes about 10 minutes. Caddy gets a Let's Encrypt certificate the first time someone opens the site.
5. Sign in and invite your team
- Open
https://books.example.comand sign in with the account setup made. - Create your company and fill in its profile.
- Invite people from Settings › Team. They get an email with a link, and make their account from it.
Sign-up is closed, so only people you invite, or add yourself, can make an account:
bun run self-host user add --email ada@example.com --first-name Ada --last-name LovelaceTurn on two-step sign-in for administrators in their profile. Sign-in and accounts covers the rest.
6. Set up email (recommended)
Without email, people only get invitations and reminders when you copy the link and send it yourself. With Resend:
- Add your sending domain in Resend, such as
books.example.com, and add the DNS records it shows. - Wait until Resend says the domain is verified.
- Run setup again and answer Yes, with Resend, or add these to
self-host/.envand runbun run self-host up:
ACCOUNTING_EMAIL_ENABLED=true
RESEND_API_KEY=re_…
OATMILK_EMAIL_DOMAIN=books.example.com7. Connect your tools
- API keys from Developers › API keys start with
oat_live_, and the API reference athttps://books.example.com/docs/apiuses your address. - AI apps: add
https://books.example.com/api/mcpas a remote MCP server. - The CLI:
npx @getoatmilk/cli login --host https://books.example.com.
Keep it running
| Task | Command |
|---|---|
| Check its health | bun run self-host doctor |
| Update to a new version | git pull, then bun run self-host up |
| Back up the database and files | bun run self-host backup |
Schedule backups with cron, and copy them off the server:
crontab -e
# 30 3 * * * cd /home/me/oatmilk && /home/me/.bun/bin/bun run self-host backupSee Update, back up and troubleshoot.
If something goes wrong
| Problem | Fix |
|---|---|
| The site has no certificate | The domain doesn't point at the server yet, or ports 80 and 443 are closed. Check with dig and bun run self-host logs caddy. |
| A teammate can't make an account | Sign-up is closed: invite them in Settings › Team, or bun run self-host user add. |
| Invitation emails don't arrive | Check that Resend shows the domain as verified, and read bun run self-host logs app. You can always copy the invitation link from Settings › Team. |
| The build stops with "killed" | The server ran out of memory. Use 8 GB, or add swap while building. |