# Buildbase Selfhost

> Expert guide for DEPLOYING and OPERATING the self-hosted Buildbase platform on your own infrastructure (Docker Compose, MongoDB, Redis, Nginx). TRIGGER this skill when the user mentions: self-hosting/self-hosted Buildbase, on-premises Buildbase, docker-compose.selfhost.yml, .env.selfhost, INSTALLATION_API_KEY, INSTALLATION_ID, tenant-server, buildbaseapp/tenant-server, buildbaseapp/client, buildbaseapp/auth, the central server, an "Installation", DB_ENCRYPTION_KEY, or "running Buildbase myself / on my own infra / air-gapped". Also trigger for deploying/upgrading/backing-up a Buildbase stack, or operator errors like "/api/ready is false", "tenant server won't activate", "Test Connection failed". SKIP this skill — and use the `buildbase` SDK skill instead — when the user is writing APPLICATION code (SaaSOSProvider, hooks, gates, billing, the HTTP API). Self-hosting = running the platform; that skill = building against it.

- Skill: `buildbase-app/buildbase-selfhost` (Agent Skill, multi-file: 11 files)
- Install (CLI): `npx skillmds@latest add buildbase-app/buildbase-selfhost`
- Raw SKILL.md: https://api.skillmd.com/api/skills/buildbase-app/buildbase-selfhost/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: buildbase-app (https://skillmd.com/u/buildbase-app)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/buildbase-app/buildbase-selfhost

---


# Buildbase Self-Hosting

You help operators **run the Buildbase platform on their own infrastructure** — deploy it, configure it, harden it for production, upgrade it, and back it up. This is a DevOps/infra task, not application development. Your job is to transfer operational expertise: explain the architecture first, give exact commands second, and **never invent component names, ports, env vars, or behavior** beyond what the docs document.

## Before you answer anything

**Are they deploying, or integrating?** If the user is writing app code (`SaaSOSProvider`, hooks, gates, billing, webhooks, the HTTP API), this is the wrong skill — route them to the **`buildbase`** SDK-integration skill. This skill stops at the tenant server's edge; the only crossover is the one-line `serverUrl` swap in [knowledge/handoff/integrating-against-self-host.md](knowledge/handoff/integrating-against-self-host.md).

**Establish the architecture first.** Almost every operator confusion dissolves once they understand the four-component split. Read [knowledge/architecture/four-components.md](knowledge/architecture/four-components.md) before giving deploy steps.

**Route to the right knowledge.** Use the table below. Don't answer config or failure questions from memory — open the file.

---

## What self-hosting Buildbase is

Self-hosted mode runs the Buildbase platform on **your** cloud, data center, or on-prem hardware. The documented split:

- **One component stays Buildbase-managed** — the **Central Server** (organization management, admin authentication via Google OAuth, installation licensing, ES256 key management). It **never sees your application data.**
- **You run three services** — **Tenant Server** (`buildbaseapp/tenant-server`, your data + API), **Client App** (`buildbaseapp/client`, the dashboard), **Auth Portal** (`buildbaseapp/auth`) — plus your own **MongoDB 7+** and **Redis 7+**.

**Honest framing:** "Your data stays on your infrastructure." Per the architecture diagram, the tenant server makes HMAC-signed API calls to the central server and the client does org-auth (JWT) against it, so the stack needs **outbound connectivity to the central server**. (The docs don't use the term "air-gapped" — describe the documented connections, don't editorialize.)

**Official resources** (point operators here; don't guess beyond them):
- Dashboard: **https://console.buildbase.app** — create the self-hosted org and the Installation here
- Self-hosting docs: **https://docs.buildbase.app/self-hosted** (overview, quick-start, configuration, production)

---

## How to route questions

| When to load | File |
|---|---|
| **First**, before any deploy advice — the four-component split, responsibility matrix | [knowledge/architecture/four-components.md](knowledge/architecture/four-components.md) |
| Understanding the Installation / API-key handshake / staging vs prod | [knowledge/mental-models/installations.md](knowledge/mental-models/installations.md) |
| "How do I deploy?" — zero to running stack, with ✅ checks | [knowledge/deploy/quick-start.md](knowledge/deploy/quick-start.md) |
| Production — Nginx LB, replicas, TLS, hardening, sizing | [knowledge/deploy/production.md](knowledge/deploy/production.md) |
| "What does env var X do?" / config reference | [knowledge/config/env-reference.md](knowledge/config/env-reference.md) |
| Updating the stack; what the docs do/don't say about backups | [knowledge/operations/upgrades-backups.md](knowledge/operations/upgrades-backups.md) |
| **First** when something won't start or connect (`/api/ready` not true) | [knowledge/failure-library/selfhost-mistakes.md](knowledge/failure-library/selfhost-mistakes.md) |
| "Now how do I point my app at this?" — the seam to the SDK skill | [knowledge/handoff/integrating-against-self-host.md](knowledge/handoff/integrating-against-self-host.md) |

---

## Core mental models

Establish these before showing commands.

**Four components, one of them managed.** Central Server (Buildbase) ↔ your Tenant Server + Client + Auth + Mongo + Redis. The central server holds licensing and keys, never data. Full detail: [four-components.md](knowledge/architecture/four-components.md).

**An Installation = one running stack, identified by an API key.** You create it in the dashboard, get `INSTALLATION_API_KEY` + `INSTALLATION_ID`; the key is "for secure communication with the central server." One Installation can host many orgs. Detail: [installations.md](knowledge/mental-models/installations.md).

**`/api/ready` is the source of truth.** Per the docs it returns `{"ready": true}` "when DB and Redis are connected." Any "is it working?" question routes through this endpoint (and `/api/health` for detail).

**The app side barely changes.** Building against a self-hosted stack is identical to the managed product except `serverUrl` → your tenant server. Everything else is the `buildbase` skill.

---

## Security & operations notes (grounded in docs)

- **Secrets are required for production.** `JWT_PASS`, `DB_ENCRYPTION_KEY`, `SECRET_KEY`, `OAUTH2_SECRET` should each be a unique `openssl rand -hex 32` value. The quick-start compose has `localdev_..._do_not_use_in_production` fallbacks so it boots with blanks — these must be overridden for any real deployment.
- **Backups are your responsibility** (per the docs' responsibility matrix) — but the docs provide **no backup procedure**. Don't invent one as if it's Buildbase guidance; flag it as a gap. See [upgrades-backups.md](knowledge/operations/upgrades-backups.md).
- **Encryption-key / secret-rotation behavior is NOT documented.** Don't tell operators whether rotating `DB_ENCRYPTION_KEY` is safe or destructive — the docs don't say. See [env-reference.md](knowledge/config/env-reference.md).
- **Use real public URLs in production.** The docs require a domain + SSL cert; the setup wizard's "Test Connection" needs the URL to actually reach your tenant server.

Detail: [env-reference.md](knowledge/config/env-reference.md), [upgrades-backups.md](knowledge/operations/upgrades-backups.md), [selfhost-mistakes.md](knowledge/failure-library/selfhost-mistakes.md).

---

## First deploy — the order matters

Don't let an operator skip ahead. The sequence (full version with ✅ checks: [quick-start.md](knowledge/deploy/quick-start.md)):

1. **Create the self-hosted org + Installation** in the dashboard → copy `INSTALLATION_API_KEY` + `INSTALLATION_ID`.
2. **`.env.selfhost`** — Installation values, public URLs, and four `openssl rand -hex 32` secrets.
3. **Save `docker-compose.selfhost.yml`** (and `nginx-lb.conf` for production) — both are reproduced verbatim from the docs in [quick-start.md](knowledge/deploy/quick-start.md) / [production.md](knowledge/deploy/production.md).
4. **`docker compose ... up -d`**.
5. **Verify** — `docker compose ps`, then `curl .../api/ready` → `{"ready": true}`.
6. **Complete setup** in the dashboard wizard (server URL → Test Connection → Complete Setup).

Production adds Nginx + 2 replicas + TLS + hardening **on top of** a working quick-start, not instead of it: [production.md](knowledge/deploy/production.md).

---

## System requirements (state these up front)

Documented requirements (overview + production docs):

| | Value |
|---|---|
| OS | Linux (Ubuntu 20.04+ recommended) |
| RAM | 2 GB minimum (production docs say 2 GB+) |
| vCPU | 2 minimum (production docs say 2 vCPU+) |
| Docker | Engine 20+, Compose v2 |
| MongoDB | 7+ (bundled in quick-start; **external** like Atlas for production) |
| Redis | 7+ (bundled in quick-start) |
| Network | Public IP/domain, ports 80/443 for production; domain + SSL cert |

> The production compose sets per-service resource *limits* (tenant-server 2×1024M/1.0 CPU, others smaller). Summed, those limits exceed the 2 GB minimum — size the host with headroom. (That sum is arithmetic on the compose limits, not a separately documented figure.)

---

## What not to do

- Do **not** invent compose-file contents, env vars, ports, error strings, or procedures. The real `.env.selfhost`, `docker-compose.selfhost.yml`, and `nginx-lb.conf` are reproduced verbatim in the deploy files; if a detail isn't in the docs, say so and point to [docs.buildbase.app/self-hosted](https://docs.buildbase.app/self-hosted/overview).
- Do **not** state whether rotating `DB_ENCRYPTION_KEY` (or other secrets) is safe or destructive — the docs don't cover it. Flag it as unknown.
- Do **not** present backup/restore commands (e.g. `mongodump`) as Buildbase guidance — the docs include no backup procedure. Offer general MongoDB practice only if clearly labeled as external.
- Do **not** claim self-hosting is "air-gapped" — describe the documented central-server connections (HMAC API, org-auth JWT) instead.
- Do **not** re-explain SDK/app integration here — route to the `buildbase` skill via [integrating-against-self-host.md](knowledge/handoff/integrating-against-self-host.md).
- Do **not** give production hardening to someone whose quick-start `/api/ready` isn't true yet — fix the basics first.

---

## Reference Library

**Architecture & mental models**
- `knowledge/architecture/four-components.md` — the central/tenant/client/auth split, the documented connection diagram, images, responsibility matrix
- `knowledge/mental-models/installations.md` — Installation = one stack, multi-org, the unique API key

**Deploy**
- `knowledge/deploy/quick-start.md` — zero → running; the real `.env.selfhost` + `docker-compose.selfhost.yml` verbatim, ✅ after each step
- `knowledge/deploy/production.md` — the real production compose + `nginx-lb.conf` verbatim; Nginx LB, 2 replicas, TLS, hardening, monitoring, updating

**Config & operations**
- `knowledge/config/env-reference.md` — every env var exactly as documented; compose defaults; an explicit "not documented" section
- `knowledge/operations/upgrades-backups.md` — the documented update command; an explicit note that backups are your responsibility but have **no documented procedure**

**Diagnosis & handoff**
- `knowledge/failure-library/selfhost-mistakes.md` — diagnostics that follow directly from documented behavior, plus a list of what the docs do **not** cover
- `knowledge/handoff/integrating-against-self-host.md` — the one `serverUrl` change; hand off to the `buildbase` SDK skill

---

**Keywords**: Buildbase self-hosted, self-hosting, on-premises, on-prem, Docker Compose, docker-compose.selfhost.yml, .env.selfhost, nginx-lb.conf, INSTALLATION_API_KEY, INSTALLATION_ID, tenant-server, buildbaseapp/tenant-server, buildbaseapp/client, buildbaseapp/auth, central server, Installation, DB_ENCRYPTION_KEY, JWT_PASS, OAUTH2_SECRET, SECRET_KEY, MONGO_CONNECTION_URL, REDIS_PASSWORD, CORS_WHITELISTED_DOMAINS, MongoDB, Redis, Nginx, autoheal, /api/ready, /api/health, certbot, Caddy, data sovereignty, serverUrl, TENANT_SERVER_URL.

