Run Appbricx in your own cloud
Run the entire Appbricx platform on infrastructure you control: your Linux host, your database, your domain. Your apps and your users' data never leave your environment. Every service ships as a Docker container, and one docker-compose.yml wires them together.
When you would choose this
- Your data has to stay with you. Regulated teams, or customers whose contracts say where data may live.
- You want full control over the network, the database, backups and upgrades.
- You are building internal tools that should run inside your company's own network.
If you just want your app online, you do not need this: publish on an Appbricx link instead.
What you need
- Linux host. Ubuntu 22.04 or 24.04 LTS, x86_64, 2 vCPU and 2 GB RAM minimum (4 GB recommended for Puppeteer thumbnails and multiple per-project runtimes). 20 GB disk minimum.
- Docker + Docker Compose. The compose stack is the only supported install path for production self-host. macOS and Windows with Docker Desktop / WSL2 work for local trials.
- A domain you control (e.g.
app.example.com) with DNS pointing at the host, or a Cloudflare Tunnel if you would rather not expose ports directly. - Inbound ports 80 and 443 open on the host for Caddy's ACME challenge and HTTPS traffic. All other ports stay on the docker internal network.
- Root SSH access during install. The setup script writes systemd units, tweaks UFW, and configures PostgreSQL.
One-command install
Clone the repo and run the setup script from the docker directory. The script generates a .env with strong random secrets, provisions PostgreSQL, and brings the entire stack up:
git clone https://github.com/appbricx-me/appbricx.git
cd appbricx
./deployment/docker/setup.sh
docker compose --env-file deployment/docker/.env up -dFor a public VPS with a real domain, pass the domain and an ACME email so Caddy fetches a Let's Encrypt certificate on first boot:
DOMAIN=app.example.com EMAIL=you@example.com \
./deployment/docker/setup.shBehind Cloudflare Tunnel or another reverse proxy, add --skip-ssl so Caddy binds only to 127.0.0.1 and uses an internal self-signed cert for the tunnel-to-origin hop:
DOMAIN=app.example.com ./deployment/docker/setup.sh --skip-sslFirst boot takes a few minutes while Postgres initialises, migrations run, and images are pulled or built. Tail the logs to watch progress:
docker compose --env-file deployment/docker/.env logs -fDocker Compose services
The default deployment/docker/docker-compose.yml defines six services on a shared internal network:
| Service | What it does |
|---|---|
postgres | pgvector/pgvector:pg16: main database with pgvector, pg_trgm, and pgcrypto extensions. No host port published; reached only over the docker internal network. |
migrate | One-shot container that runs schema migrations against Postgres on every up, then exits. Uses the owning role for DDL; runtime services use a lower-privileged role. |
api | Hono API server: auth, project runtime, workflows, REST, CDC outbox. Reached through Caddy at /api/*. |
ws | Yjs CRDT WebSocket server for live collaborative editing. Reached through Caddy at /ws. |
web | Next.js dashboard, editor, and docs. Reached through Caddy at /. |
caddy | TLS termination and reverse proxy. Fetches Let's Encrypt certificates automatically, or serves mkcert-issued local certs for desktop installs. |
Optional stacks (layer on top)
The repo ships extra compose files you can layer on for backups and high availability. Enable them with -f:
docker-compose.replica.yml: streaming read replica for Postgres (hot standby).docker-compose.walg.yml: WAL-G continuous archiving to S3-compatible storage for point-in-time recovery.docker-compose.backup.yml: scheduledpg_dumpsidecar that writes compressed dumps to a host-mounted volume.
First-run bootstrap: become the platform admin
Once docker compose ps shows every service healthy, open the dashboard in a browser and sign up. There are two supported ways to claim the platform-admin role:
- First signup wins. With no accounts in the database yet, the first user that completes signup is promoted to platform admin automatically. This is the easy path for solo self-host: open the URL yourself and sign up before anyone else can reach the box.
- Bootstrap token. Set
INSTALL_BOOTSTRAP_TOKEN(and optionallyINSTALL_BOOTSTRAP_TOKEN_EXPIRES_AT) in the environment before first boot. Whichever signup presents the matching token is promoted to admin, even if other users have already signed up. Useful when the platform lives behind a shared onboarding URL.
Both paths are handled by the API's first-user bootstrap logic. After the first admin exists, every subsequent signup joins as a regular workspace member unless the admin invites them explicitly.
TLS and custom domain
Caddy inside the stack handles all TLS. Three env vars in deployment/docker/.env (written by setup.sh) tell it what to do:
| Env var | Meaning |
|---|---|
APPBRICX_SITE | Hostname the browser hits (e.g. app.example.com). |
APPBRICX_TLS | An email for Let's Encrypt ACME, or /certs/cert.pem /certs/key.pem for local mkcert certs, or internal for self-signed. |
APPBRICX_BIND_ADDR | 0.0.0.0 for direct public ingress, or 127.0.0.1 when running behind a tunnel/proxy. |
The committed Caddyfile reads these via env-var substitution, so a single static config covers every scenario. If you need to serve tenant subdomains through the API (multi-tenant custom-domain mode), the repo also ships Caddyfile.tenants-via-api as an alternative. Swap it in via a volume mount.
Backups
A daily pg_dump is the minimum recommended backup. The bare-metal cron line from the deployment guide:
0 3 * * * sudo -u postgres pg_dump appbricx \
| gzip > /root/backups/appbricx-$(date +%F).sql.gzFor docker installs, run the same dump from the postgres container:
docker compose exec -T postgres \
pg_dump -U appbricx appbricx | gzip > appbricx-$(date +%F).sql.gzAlso back up /data/sites/ (published static bundles) and each project's source tree. These live on named docker volumes (appbricx_sites, api_projects, api_thumbnails) and are not in Postgres.
For point-in-time recovery, layer docker-compose.walg.yml to stream WAL segments off-box, then use deployment/docker/restore-pitr.sh to restore to a specific timestamp.
Read replicas and WAL-G
Two optional compose files cover Postgres high-availability and off-site backup:
docker-compose.replica.ymlplus thedeployment/docker/replica/config directory brings up a streaming hot standby. Point read-only workloads at it, or use it as a fast failover target.docker-compose.walg.ymlplusdeployment/docker/walg/configures WAL-G to push base backups and continuous WAL segments to S3-compatible object storage. Combine withrestore-pitr.shfor point-in-time recovery.
Both stacks are documented alongside the compose files. Layer them with docker compose -f docker-compose.yml -f docker-compose.walg.yml up -d.
Upgrading
For pre-built images from GHCR:
docker compose --env-file deployment/docker/.env pull
docker compose --env-file deployment/docker/.env up -dMigrations run automatically on next boot. The migrate service is idempotent and skips anything already applied. Named volumes are preserved across the restart.
For source builds, git pull and then rebuild:
git pull
docker compose --env-file deployment/docker/.env up -d --buildEnv vars checklist
setup.sh generates strong random values for the security secrets. If you configure by hand, these are the ones that must be set:
| Variable | Purpose |
|---|---|
DATABASE_URL | Postgres connection string for the API and WS containers. In the default stack this is postgres://appbricx_app:...@postgres:5432/appbricx. |
JWT_SECRET | Signs the platform's session and access tokens. Rotate and every user is logged out. |
ENCRYPTION_KEY | Symmetric key for encrypting per-workspace secrets at rest (OAuth tokens, workflow secrets, etc.). |
APPBRICX_KEK | Key-encryption-key that wraps ENCRYPTION_KEY and any tenant-scoped data keys. Store this outside the box (secrets manager, KMS) if you can. |
INTERNAL_SECRET | Shared secret for service-to-service calls (API talking to WS, published-app runtime calling back to the API). Never exposed to the browser. |
INSTALL_BOOTSTRAP_TOKEN | Optional. If set, whichever signup presents this token is promoted to platform admin. See the bootstrap section above. |
Optional but common additions to .env: Google and GitHub OAuth client id/secret pairs, an ANTHROPIC_API_KEY or OPENAI_API_KEY for platform-owned AI features (users can also bring their own; see BYOK), and Stripe keys if you plan to bill from your own account.
Support
- Existing private-cloud contracts. If the Appbricx team operates the stack for you under an existing private-cloud contract, reach your named contact or write to contact@appbricx.com.
- Self-host license. Email help with installation at contact@appbricx.com, or open an issue on the GitHub repo. Both are read by the Appbricx team. The compose files, setup scripts, and
deployment/RUNBOOK.mdin the repo are the source of truth for day-two operations.
Related
Publish on a live link · Use your own AI key · For developers