# CLAUDE.md This file provides guidance to Claude Code when working with code in this repository. ## What this repo is A Docker Compose deployment stack for [Spindle](https://tangled.org) (a CI/CD pipeline tool) backed by [OpenBao](https://openbao.org) (an open-source HashiCorp Vault fork) for secrets management. Spindle is not developed here — it is cloned from `tangled.org/tangled.org/core` at tag `v1.13.0-alpha` and built inside `Dockerfile`. ## Current state This stack is actively being tested for first-time deployment on Ubuntu Linux. The init script and Docker config have had several fixes applied and may need further iteration. Known working: - OpenBao starts and reads config correctly - `init-openbao.sh` fixes data volume permissions, restarts OpenBao, and runs the full vault bootstrap Known issues / things being tested: - Full end-to-end stack (openbao → openbao-proxy → spindle) not yet verified - Spindle healthcheck is intentionally omitted pending manual testing of its HTTP endpoints ## Architecture ``` ┌──────────┐ AppRole ┌───────────────┐ KV v2 ┌─────────┐ │ spindle │ ─────────────► │ openbao-proxy │ ─────────────► │ openbao │ │ :6555 │ │ :8201 │ │ :8200 │ └──────────┘ └───────────────┘ └─────────┘ │ │ /var/run/docker.sock ▼ Host Docker daemon (pipeline containers run here) ``` - **openbao** — vault backend, file storage, sealed on every start - **openbao-proxy** — AppRole sidecar, auto-authenticates, token cached at `/tmp/openbao-token` - **spindle** — CI runner, starts only after proxy is healthy, mounts Docker socket ## Key config files | File | Purpose | |------|---------| | `docker-compose.yml` | Service definitions, volumes, port bindings, dependency order | | `Dockerfile` | Clones `tangled.org/core` at `v1.13.0-alpha`, builds with Go, produces Alpine image | | `config/openbao/server/server.hcl` | OpenBao server (file storage, TCP listener on 8200, TLS off) | | `config/openbao/proxy/proxy.hcl` | Proxy AppRole auto-auth, token sink at `/tmp/openbao-token`, listener on 8201 | | `config/openbao/spindle-policy.hcl` | Grants Spindle KV v2 CRUD on `spindle/data/*` and `spindle/metadata/*` | | `init-openbao.sh` | One-time bootstrap: fixes volume perms, inits vault, enables KV v2, creates AppRole | | `.env.sample` | All configurable env vars with defaults — copy to `.env` before starting | ## Important implementation details - Config directories are split: `config/openbao/server/` and `config/openbao/proxy/` are mounted separately so each service only sees its own HCL files. Mixing them caused OpenBao server to fail parsing proxy-specific stanzas. - The `openbao-data` Docker volume is created root-owned by default. `init-openbao.sh` fixes this with `docker compose exec --user root openbao chown -R openbao:openbao /openbao/data` before running init. - All `docker compose exec` calls in the init script use `-T` with ` ``` ## Verify the stack ```bash curl http://localhost:8200/v1/sys/health # OpenBao server (127.0.0.1 only) curl http://localhost:6555/ # Spindle ```