···11+# spindle secrets with openbao
22+33+This document covers setting up Spindle to use OpenBao for secrets
44+management instead of the default SQLite backend.
55+66+## installation
77+88+Install OpenBao from nixpkgs:
99+1010+```bash
1111+nix-env -iA nixpkgs.openbao
1212+```
1313+1414+## local development setup
1515+1616+Start OpenBao in dev mode:
1717+1818+```bash
1919+bao server -dev
2020+```
2121+2222+This starts OpenBao on `http://localhost:8200` with a root token. Save
2323+the root token from the output -- you'll need it.
2424+2525+Set up environment for bao CLI:
2626+2727+```bash
2828+export BAO_ADDR=http://localhost:8200
2929+export BAO_TOKEN=hvs.your-root-token-here
3030+```
3131+3232+Create the spindle KV mount:
3333+3434+```bash
3535+bao secrets enable -path=spindle -version=2 kv
3636+```
3737+3838+Set up AppRole authentication:
3939+4040+Create a policy file `spindle-policy.hcl`:
4141+4242+```hcl
4343+path "spindle/data/*" {
4444+ capabilities = ["create", "read", "update", "delete", "list"]
4545+}
4646+4747+path "spindle/metadata/*" {
4848+ capabilities = ["list", "read", "delete"]
4949+}
5050+5151+path "spindle/*" {
5252+ capabilities = ["list"]
5353+}
5454+```
5555+5656+Apply the policy and create an AppRole:
5757+5858+```bash
5959+bao policy write spindle-policy spindle-policy.hcl
6060+bao auth enable approle
6161+bao write auth/approle/role/spindle \
6262+ token_policies="spindle-policy" \
6363+ token_ttl=1h \
6464+ token_max_ttl=4h
6565+```
6666+6767+Get the credentials:
6868+6969+```bash
7070+bao read auth/approle/role/spindle/role-id
7171+bao write -f auth/approle/role/spindle/secret-id
7272+```
7373+7474+Configure Spindle:
7575+7676+Set these environment variables for Spindle:
7777+7878+```bash
7979+export SPINDLE_SERVER_SECRETS_PROVIDER=openbao
8080+export SPINDLE_SERVER_SECRETS_OPENBAO_ADDR=http://localhost:8200
8181+export SPINDLE_SERVER_SECRETS_OPENBAO_ROLE_ID=your-role-id-from-above
8282+export SPINDLE_SERVER_SECRETS_OPENBAO_SECRET_ID=your-secret-id-from-above
8383+export SPINDLE_SERVER_SECRETS_OPENBAO_MOUNT=spindle
8484+```
8585+8686+Start Spindle:
8787+8888+Spindle will now use OpenBao for secrets storage with automatic token
8989+renewal.
9090+9191+## verifying setup
9292+9393+List all secrets:
9494+9595+```bash
9696+bao kv list spindle/
9797+```
9898+9999+Add a test secret via Spindle API, then check it exists:
100100+101101+```bash
102102+bao kv list spindle/repos/
103103+```
104104+105105+Get a specific secret:
106106+107107+```bash
108108+bao kv get spindle/repos/your_repo_path/SECRET_NAME
109109+```
110110+111111+## how it works
112112+113113+- Secrets are stored at `spindle/repos/{sanitized_repo_path}/{secret_key}`
114114+- Each repository gets its own namespace
115115+- Repository paths like `at://did:plc:alice/myrepo` become
116116+ `at_did_plc_alice_myrepo`
117117+- The system automatically handles token renewal using AppRole
118118+ authentication
119119+- On shutdown, Spindle cleanly stops the token renewal process
120120+121121+## troubleshooting
122122+123123+**403 errors**: Check that your BAO_TOKEN is set and the spindle mount
124124+exists
125125+126126+**404 route errors**: The spindle KV mount probably doesn't exist - run
127127+the mount creation step again
128128+129129+**Token expired**: The AppRole system should handle this automatically,
130130+but you can check token status with `bao token lookup`