Installation
This guide stands up a single-host Paas instance on a VM that has Docker installed.
Prerequisites
- A Linux VM (Ubuntu 24.04 tested) with public IP and root/sudo access.
- Docker Engine ≥ 24 with the Compose v2 plugin (
docker compose version). openssl(used by the installer to generate secrets).- Two DNS records pointing at the VM (you'll add them after install):
paas.example.com— the dashboard + API.*.apps.example.com— wildcard for auto-assigned app hostnames.git.example.com— git remote (can be the same A record as the dashboard).
If you're just trying it out, you can skip DNS and use
paas.localhost,apps.localhost,git.localhost— see the Local-only quickstart below.
1. Clone
git clone <this-repo> paas
cd paas
2. First-run installer
./deploy/installer/install.sh
The installer prompts for four things (platform hostname, admin email, admin
password, whether to use Let's Encrypt staging) and generates strong random
values for everything else. It writes .env (mode 600), brings the stack up,
and waits for the platform Let's Encrypt cert to issue.
Prerequisite: DNS A record for the platform hostname must already point at this server's public IP, with port 80 reachable from the internet so the HTTP-01 ACME challenge succeeds.
The installer creates the paas-secrets Docker volume containing
/etc/paas/master.key (32 bytes, mode 600), pre-creates the paas-control
and paas-apps networks, builds images, runs migrations, and starts the
stack.
3. Sign in
Open https://paas.example.com/. Sign in with the bootstrap admin printed at
the end of the installer (also in your .env as PAAS_BOOTSTRAP_EMAIL /
PAAS_BOOTSTRAP_PASSWORD).
4. Add an SSH key
Account → SSH keys → paste your ~/.ssh/id_ed25519.pub. This is required
before you can git push to your apps.
5. (Recommended) verify the deploy loop on staging certs
PAAS_ACME_STAGING=true is the default. Create an org and an app, push a
commit, hit your custom domain. Once you see end-to-end works (with a browser
warning about the staging cert), set PAAS_ACME_STAGING=false in .env and
re-issue:
docker compose restart cert-manager
This avoids burning real Let's Encrypt rate limits while you're shaking out your DNS / config.
Local-only quickstart (no real DNS)
For a hack-on-it-locally setup, edit /etc/hosts:
127.0.0.1 paas.localhost git.localhost
127.0.0.1 my-acme-acme.apps.localhost
…and set in .env:
PAAS_PLATFORM_HOSTNAME=paas.localhost
PAAS_GIT_PUBLIC_HOST=git.localhost
PAAS_WILDCARD_BASE=apps.localhost
PAAS_HTTP_PORT=80
ACME will fail (Let's Encrypt won't validate localhost) — that's fine for
local dev; HTTP-only access still works on http://paas.localhost.
Where things live
| Path on host | What it is |
|---|---|
Volume paas-secrets |
/etc/paas/master.key, ACME account |
Volume pg-data |
Control-plane Postgres |
Volume repos |
Bare git repos for all apps |
Volume registry-data |
Local Docker registry |
Volume nginx-confd |
Generated vhost configs |
Volume certs |
Issued TLS certs |
./deploy/nginx/nginx.conf |
Public-facing nginx config (read-only) |
Updating
git pull
docker compose -f docker-compose.yml build
docker compose -f docker-compose.yml run --rm migrate
docker compose -f docker-compose.yml up -d
Uninstall
docker compose -f docker-compose.yml down
docker volume rm pg-data registry-data repos paas-secrets nginx-confd certs \
acme-account acme-challenges builder-work
docker network rm paas-control paas-apps