Files
stack/docs/scratchpads/357-openbao-docker-compose.md
Jason Woltje 6521cba735
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
feat: add flexible docker-compose architecture with profiles
- Add OpenBao services to docker-compose.yml with profiles (openbao, full)
- Add docker-compose.build.yml for local builds vs registry pulls
- Make PostgreSQL and Valkey optional via profiles (database, cache)
- Create example compose files for common deployment scenarios:
  - docker/docker-compose.example.turnkey.yml (all bundled)
  - docker/docker-compose.example.external.yml (all external)
  - docker/docker.example.hybrid.yml (mixed deployment)
- Update documentation:
  - Enhance .env.example with profiles and external service examples
  - Update README.md with deployment mode quick starts
  - Add deployment scenarios to docs/OPENBAO.md
  - Create docker/DOCKER-COMPOSE-GUIDE.md with comprehensive guide
- Clean up repository structure:
  - Move shell scripts to scripts/ directory
  - Move documentation to docs/ directory
  - Move docker compose examples to docker/ directory
- Configure for external Authentik with internal services:
  - Comment out Authentik services (using external OIDC)
  - Comment out unused volumes for disabled services
  - Keep postgres, valkey, openbao as internal services

This provides a flexible deployment architecture supporting turnkey,
production (all external), and hybrid configurations via Docker Compose
profiles.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 16:55:33 -06:00

4.8 KiB

Issue #357: Add OpenBao to Docker Compose (turnkey setup)

Objective

Add OpenBao secrets management to the Docker Compose stack with auto-initialization, auto-unseal, and Transit encryption key setup.

Implementation Status

Status: 95% Complete - Core functionality implemented, minor JSON parsing fix needed

What Was Implemented

1. Docker Compose Services

  • openbao service: Main OpenBao server

    • Image: quay.io/openbao/openbao:2
    • File storage backend
    • Port 8200 exposed
    • Health check configured
    • Runs as root to avoid Docker volume permission issues (acceptable for dev/turnkey setup)
  • openbao-init service: Auto-initialization sidecar

    • Runs once on startup (restart: "no")
    • Waits for OpenBao to be healthy via depends_on
    • Initializes OpenBao with 1-of-1 Shamir key (turnkey mode)
    • Auto-unseals on restart
    • Creates Transit keys and AppRole

2. Configuration Files

  • docker/openbao/config.hcl: OpenBao server configuration

    • File storage backend
    • HTTP listener on port 8200
    • mlock disabled for Docker compatibility
  • docker/openbao/init.sh: Auto-initialization script

    • Idempotent initialization logic
    • Auto-unseal from stored key
    • Transit engine setup with 4 named keys
    • AppRole creation with Transit-only policy

3. Environment Variables

Updated .env.example:

OPENBAO_ADDR=http://openbao:8200
OPENBAO_PORT=8200

4. Docker Volumes

Three volumes created:

  • mosaic-openbao-data: Persistent data storage
  • mosaic-openbao-config: Configuration files
  • mosaic-openbao-init: Init credentials (unseal key, root token, AppRole)

5. Transit Keys

Four named Transit keys configured (aes256-gcm96):

  • mosaic-credentials: User credentials
  • mosaic-account-tokens: OAuth tokens
  • mosaic-federation: Federation private keys
  • mosaic-llm-config: LLM provider API keys

6. AppRole Configuration

  • Role: mosaic-transit
  • Policy: Transit encrypt/decrypt only (least privilege)
  • Credentials saved to /openbao/init/approle-credentials

7. Comprehensive Test Suite

Created tests/integration/openbao.test.ts with 22 tests covering:

  • Service startup and health checks
  • Auto-initialization and idempotency
  • Transit engine and key creation
  • AppRole configuration
  • Auto-unseal on restart
  • Security policies
  • Encrypt/decrypt operations

Known Issues

Minor: JSON Parsing in init.sh

Issue: The unseal key extraction from bao operator init JSON output needs fixing.

Current code:

UNSEAL_KEY=$(echo "${INIT_OUTPUT}" | sed -n 's/.*"unseal_keys_b64":\["\([^"]*\)".*/\1/p')

Status: OpenBao initializes successfully, but unseal fails due to empty key extraction.

Fix needed: Use jq for robust JSON parsing, or adjust the sed regex.

Workaround: Manual unseal works fine - the key is generated and saved, just needs proper parsing.

Files Created/Modified

Created:

  • docker/openbao/config.hcl
  • docker/openbao/init.sh
  • tests/integration/openbao.test.ts
  • docs/scratchpads/357-openbao-docker-compose.md

Modified:

  • docker/docker-compose.yml - Added openbao and openbao-init services
  • .env.example - Added OpenBao environment variables
  • tests/integration/docker-stack.test.ts - Fixed missing closing brace

Testing

Run integration tests:

pnpm test:docker

Manual testing:

cd docker
docker compose up -d openbao openbao-init
docker compose logs -f openbao-init

Next Steps

  1. Fix JSON parsing in init.sh (use jq or improved regex)
  2. Run full integration test suite
  3. Update to ensure 85% test coverage
  4. Create production hardening documentation

Production Hardening Notes

The current setup is optimized for turnkey development. For production:

  • Upgrade to 3-of-5 Shamir key splitting
  • Enable TLS on listener
  • Use external KMS for auto-unseal (AWS KMS, GCP CKMS, Azure Key Vault)
  • Enable audit logging
  • Use Raft or Consul storage backend for HA
  • Revoke root token after initial setup
  • Run as non-root user with proper volume permissions
  • See docs/design/credential-security.md for full details

Architecture Alignment

This implementation follows the design specified in:

  • docs/design/credential-security.md - Section: "OpenBao Integration"
  • Epic: #346 (M7-CredentialSecurity)
  • Phase 2: OpenBao Integration

Success Criteria Progress

  • docker compose up starts OpenBao without manual intervention
  • Container includes health check
  • Container restart auto-unseals (90% - needs JSON fix)
  • All 4 Transit keys created
  • AppRole credentials file exists (90% - needs JSON fix)
  • Health check passes
  • All tests pass with ≥85% coverage (tests written, need passing implementation)

Estimated Completion Time

Time remaining: 30-45 minutes to fix JSON parsing and validate all tests pass.