Motherbase installs a Platform Console and lets that Console provision isolated project stacks. The supported entry point is ./setup.sh; deploy/README.md explicitly treats the files under deploy/ as implementation and maintenance helpers.
Topologies
| Topology | Selected by | Project Compose file | Routing |
|---|---|---|---|
| Local multi-project | ./setup.sh, then choose Local | deploy/docker-compose.dev-multi.yml | HTTP at <name>.localhost |
| Production multi-project | ./setup.sh, then choose VPS, or use DOMAIN=... ./setup.sh --yes --prod | deploy/docker-compose.prod.yml | HTTPS at <name>.<base-domain> |
| Root development stack | docker compose up in the repository root | docker-compose.yml | Loopback ports only, no proxy |
Local mode starts deploy/traefik/docker-compose.dev.yml and deploy/console/docker-compose.dev.yml. Production starts deploy/traefik/docker-compose.yml and deploy/console/docker-compose.yml. In both modes, the Console creates projects afterwards; setup.sh does not create a default project.
The root docker-compose.yml is a single-stack development convenience, not a supported
production topology: setup.sh never starts it. Use the Console-managed production
topology for a normal installation. See Docker topology.
Host requirements
The checks in setup.sh require:
- Bash, because the setup must be executed as
./setup.shand refuses to be sourced. - A working Docker daemon and either
docker composeor the legacydocker-composecommand. - Access to
/var/run/docker.sock; only the internal orchestration daemon receives the socket in the Console stacks. - Host ports
80and443in VPS mode. The script opens them through activeufw, or insertsiptablesaccept rules when available. - Outbound HTTPS access to pull images, resolve their immutable repository digests, query
https://ifconfig.me, and complete ACME challenges.
If Docker is absent on Linux, setup.sh runs the installer from https://get.docker.com. On macOS and other systems it stops and asks you to install Docker manually. No Node.js installation is required for setup.sh: deploy/deps.Dockerfile builds with node:22-bookworm-slim. A manual host build is separate and is guarded by scripts/check-node-version.cjs, which requires Node 22.12.0 or newer.
The repository does not enforce a CPU, RAM, disk, or Linux-distribution minimum. Production project defaults in apps/server/console/lib/manifest.ts limit API and Postgres to 0.5 CPU and 512M each, and MinIO to 0.25 CPU and 256M.
DNS
For DOMAIN=example.com, create one wildcard record pointing to the VPS:
Type: A
Name: *
Value: <VPS_IP>The generated project defaults in apps/server/console/lib/manifest.ts use:
console.example.com
<name>.example.com
<name>-storage.example.com
<name>-minio.example.com*.example.com does not cover the apex example.com. If CONSOLE_DOMAIN is outside DOMAIN, setup.sh prints and checks a second explicit record. A custom project domain outside the wildcard also needs its own DNS record.
When the base domain already contains at least two dots, for example test.example.com, setup.sh treats the resulting project hosts as deep subdomains and offers the GoDaddy DNS-01 configuration. See Traefik and TLS.
What is installed where
| Location | Contents | Persistence |
|---|---|---|
Repository root .env | Local project environment, or the VPS install marker with BASE_HOST, CONSOLE_DOMAIN, and ACME_EMAIL | Kept on normal reruns; removed by reset |
deploy/console/.env | Console credentials, orchestration bearer, image references, domain suffix, and resolver | Mode 600; kept and repaired on normal reruns |
deploy/traefik/.env | ACME email, pinned proxy images, optional dashboard and DNS-01 values | Kept on normal reruns |
/srv/projects/<name>/.env.prod | One production project's generated configuration and secrets | Mode 600; kept by stop/update, deleted by project destruction |
/srv/projects/<name>/manifest.json | Non-secret project manifest | Kept by stop/update, deleted by project destruction |
console_projects volume | Local-mode Console project directory mounted at /srv/projects | Kept by normal recreation |
Per-project db_data and minio_data volumes | PostgreSQL and MinIO data | Kept by stop/update; deleted by destroy/reset |
Per-project api_backups and api_data volumes | Production SQL dumps and assistant SQLite data | Kept by stop/update; deleted by destroy/reset |
deploy/traefik/acme/ | Traefik ACME state, including acme.json | Bind-mounted into the production Traefik container |
traefik_proxy | External Docker network shared by Traefik, Console, APIs, and MinIO | Created by setup when missing |
Project Destroy, ./setup.sh --reset, and ./deploy/reset.sh remove Docker volumes. A normal stop, restart, setup rerun, or project update does not.
Next steps
- Follow Setup script for interactive and unattended installs.
- Use Docker topology to identify the service and volume involved in an incident.
- Read Backups and restore before the first production upgrade.
- Keep Operations at hand for the day-to-day start/stop/logs/reset runbook.