101 lines
3.6 KiB
Markdown
101 lines
3.6 KiB
Markdown
# OpenBAO — Home Lab Deployment
|
|
|
|
Single-node OpenBAO (v2.5.5) running via Docker Compose with integrated Raft
|
|
storage. Suitable for a self-hosted home lab.
|
|
|
|
## Layout
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `docker-compose.yml` | Container definition (port 8200, Raft data volume, IPC_LOCK) |
|
|
| `config/openbao.hcl` | Server config: Raft storage, TCP listener, UI |
|
|
| `.gitignore` | Keeps unseal keys / tokens / data out of git |
|
|
|
|
## 1. Start the server
|
|
|
|
```bash
|
|
docker compose up -d
|
|
docker compose logs -f openbao # watch startup
|
|
```
|
|
|
|
The server starts **sealed and uninitialized** — this is expected.
|
|
|
|
## 2. Initialize (one time only)
|
|
|
|
This generates the unseal keys and the initial root token. Run it once.
|
|
|
|
```bash
|
|
docker compose exec openbao bao operator init \
|
|
-key-shares=5 -key-threshold=3 -format=json > init-output.json
|
|
```
|
|
|
|
⚠️ **`init-output.json` contains your unseal keys and root token.** Store them
|
|
in a password manager and delete the file afterward. It is git-ignored, but
|
|
treat it like the master key to everything — because it is.
|
|
|
|
## 3. Unseal
|
|
|
|
OpenBAO starts sealed after every restart. Provide 3 of the 5 keys:
|
|
|
|
```bash
|
|
docker compose exec openbao bao operator unseal # run 3x, paste a key each time
|
|
```
|
|
|
|
## 4. Log in & use
|
|
|
|
**Day-to-day: use the non-root `admin` user** (userpass auth, `admin` policy).
|
|
Credentials are in `admin-credentials.txt` (git-ignored) — change the password
|
|
and move it to your password manager.
|
|
|
|
```bash
|
|
# Local CLI (plaintext API is bound to loopback only):
|
|
export BAO_ADDR=http://127.0.0.1:8200
|
|
docker compose exec openbao bao login -method=userpass username=admin
|
|
|
|
# Break-glass only:
|
|
docker compose exec openbao bao login # paste the root token
|
|
```
|
|
|
|
The `admin` policy ([policies/admin.hcl](policies/admin.hcl)) grants full
|
|
day-to-day administration but **not** root-only operations (sys/raw, root-token
|
|
generation, rekey). Keep the root token offline.
|
|
|
|
A KV v2 secrets engine is mounted at `secret/`:
|
|
|
|
```bash
|
|
docker compose exec openbao bao kv put secret/myapp/db password=s3cr3t
|
|
docker compose exec openbao bao kv get secret/myapp/db
|
|
```
|
|
|
|
## Access via Traefik (LAN-only HTTPS)
|
|
|
|
OpenBAO is fronted by the Traefik stack (`../Traefik`) at
|
|
**https://openbao.famfi.home** — restricted to `192.168.0.0/16`, TLS terminated
|
|
by Traefik (default self-signed cert).
|
|
|
|
- Traefik dynamic config: `/srv/TRAEFIK/etc/traefik/traefik.d/openbao.yml`
|
|
- Traefik reaches the container by name (`http://openbao:8200`) over the shared
|
|
`traefik_proxy` Docker network.
|
|
- **DNS action required:** add an A record `openbao.famfi.home → 192.168.0.142`
|
|
(the `websecure` entrypoint IP) on your LAN DNS, or a hosts entry on clients.
|
|
- The built-in **web UI** is served at https://openbao.famfi.home once DNS is set.
|
|
- Because the cert is self-signed, CLI clients pointed at the HTTPS name need the
|
|
CA trusted or `BAO_SKIP_VERIFY=true` (local CLI can just use the loopback
|
|
http://127.0.0.1:8200 instead).
|
|
|
|
## Backups (Raft snapshots)
|
|
|
|
```bash
|
|
docker compose exec openbao bao operator raft snapshot save /openbao/file/snap.bak
|
|
docker compose cp openbao:/openbao/file/snap.bak ./snap-$(date +%F).bak
|
|
```
|
|
|
|
## Hardening checklist (before storing real secrets)
|
|
|
|
- [ ] Put TLS in front (reverse proxy) or enable native TLS in `openbao.hcl`
|
|
- [ ] Create a non-root admin policy + token; stop using the root token day-to-day
|
|
- [ ] Revoke or store the root token offline
|
|
- [ ] Enable auto-unseal (e.g. transit/KMS) if you don't want manual unseal on reboot
|
|
- [ ] Schedule the snapshot backup above
|
|
- [ ] Disable or encrypt swap on the host (OpenBAO 2.x dropped mlock support)
|