|
| 1 | +# devstack — Quickstart |
| 2 | + |
| 3 | +`devstack` runs one warm set of shared infrastructure (Postgres/Redis/MinIO) on a |
| 4 | +tool-owned Docker network and lets many project stacks attach to it — instead of a |
| 5 | +duplicate database per repo. This guide covers the commands that work today. |
| 6 | + |
| 7 | +> **Prerequisites:** Docker Engine + Compose v2.20+, git ≥ 2.30. Run |
| 8 | +> `devstack doctor` first — it probes everything and prints a one-line fix for |
| 9 | +> anything missing. |
| 10 | +
|
| 11 | +## 1. Lay out a workspace |
| 12 | + |
| 13 | +A workspace is one `workspace.yaml` (the shared layer) plus a `devstack.yaml` per |
| 14 | +repo (the portable project layer): |
| 15 | + |
| 16 | +```yaml |
| 17 | +# workspace.yaml |
| 18 | +apiVersion: devstack/v1 |
| 19 | +kind: Workspace |
| 20 | +name: acme |
| 21 | +shared: |
| 22 | + postgres: { template: postgres, params: { version: "16" } } |
| 23 | + redis: { template: redis } |
| 24 | +projects: |
| 25 | + - { name: api, path: services/api } |
| 26 | +``` |
| 27 | +
|
| 28 | +```yaml |
| 29 | +# services/api/devstack.yaml |
| 30 | +apiVersion: devstack/v1 |
| 31 | +kind: Project |
| 32 | +name: api |
| 33 | +services: |
| 34 | + api: |
| 35 | + template: php.laravel.nginx |
| 36 | + uses: [workspace.shared.postgres, workspace.shared.redis] |
| 37 | + healthcheck: { kind: http, port: 8080, path: /healthz } |
| 38 | + env: |
| 39 | + import: |
| 40 | + - { from: workspace.shared.postgres, vars: [host, port, user, password, database] } |
| 41 | +``` |
| 42 | +
|
| 43 | +## 2. Bring it up |
| 44 | +
|
| 45 | +```bash |
| 46 | +devstack up |
| 47 | +``` |
| 48 | + |
| 49 | +One idempotent command runs the saga: **preflight → network → generate → |
| 50 | +shared (health-gated) → compose-up → hooks**. The shared services start once and |
| 51 | +are gated healthy *before* your project starts. Re-running `up` is near-instant — |
| 52 | +satisfied phases are skipped (resumable via the state ledger); a crash mid-run |
| 53 | +resumes; a failure compensates (drops ref rows / downs the project) but **never |
| 54 | +destroys data** (your DB volumes survive). |
| 55 | + |
| 56 | +```bash |
| 57 | +devstack up --json # machine-readable phase records |
| 58 | +devstack up api # only the named project(s) + the shared services they use |
| 59 | +devstack up --build # rebuild images first |
| 60 | +devstack up --no-hooks # skip lifecycle hooks |
| 61 | +``` |
| 62 | + |
| 63 | +## 3. Inspect and tear down |
| 64 | + |
| 65 | +```bash |
| 66 | +devstack status # per-project service health + last saga outcome + shared ref graph |
| 67 | +devstack shared status # shared services, ref counts, consuming projects |
| 68 | +devstack down # stop this workspace's project stacks, release their refs |
| 69 | +devstack shared gc # report shared services at zero refs (--stop to actually stop them) |
| 70 | +``` |
| 71 | + |
| 72 | +`down` leaves the shared services running by default (warm DBs are cheap). The |
| 73 | +external network and volumes are never touched by `down`. |
| 74 | + |
| 75 | +## 4. Recovery |
| 76 | + |
| 77 | +The state ledger is a *cache of reality*, never the source of truth: |
| 78 | + |
| 79 | +```bash |
| 80 | +devstack shared doctor # reconcile: prune ref rows for projects no longer live |
| 81 | +devstack doctor --rebuild-state # reconstruct the ledger from live container labels + config |
| 82 | +``` |
| 83 | + |
| 84 | +## 5. Local HTTPS, DNS, and secrets (opt-in) |
| 85 | + |
| 86 | +```bash |
| 87 | +# Reverse proxy: set network.proxy.engine: caddy in workspace.yaml, then: |
| 88 | +sudo devstack dns setup # marker-fenced /etc/hosts for *.localhost |
| 89 | +sudo devstack trust install # install the local CA (mkcert) |
| 90 | +devstack trust status # diagnose CA / certutil / WSL2 readiness |
| 91 | + |
| 92 | +# Offline secrets with SOPS+age: |
| 93 | +devstack secrets keygen -o ~/.config/devstack/age.txt # generate an age key |
| 94 | +export SOPS_AGE_KEY_FILE=~/.config/devstack/age.txt |
| 95 | +# reference secrets in devstack.yaml env as secret://<provider>/<file>#<key> |
| 96 | +``` |
| 97 | + |
| 98 | +See [TROUBLESHOOTING.md](TROUBLESHOOTING.md) when something doesn't work, and |
| 99 | +[ARCHITECTURE.md](ARCHITECTURE.md) for the design. |
0 commit comments