Docker Compose
The simplest self-hosted deploy — one compose file, no cloud dependencies.
Compose file
Section titled “Compose file”services: storyshelf: image: storyshelf:latest ports: - "3000:3000" volumes: - storyshelf-data:/app/data environment: - SECRET=$(openssl rand -hex 32) # ≥ 32 chars - CAPTURE_CONCURRENCY=2 - PURGE_TTL_DAYS=30 - BRANCH_TTL_DAYS=30 - BRANCH_GC_INTERVAL_MS=86400000 # Auth — see /guides/auth/ # - AUTH_PASSWORD=a-long-admin-password # ≥ 12 chars (local admin) # - OIDC_ISSUER=https://keycloak.example.com/realms/myteam # - OIDC_CLIENT_ID=storyshelf # - OIDC_CLIENT_SECRET=secretvolumes: storyshelf-data:Swap the database for @storyshelf/db-postgres or @storyshelf/db-sqlite/turso without changing the rest of the stack.
Published Storybook subdomains
Section titled “Published Storybook subdomains”Opt in to per-project subdomains by setting PUBLISHED_BASE_DOMAIN and adding a wildcard DNS record + TLS cert:
*.stories.example.com → your.serverThen https://<slug>.stories.example.com serves the latest published Storybook, and https://<buildId>.<slug>.stories.example.com serves a specific build.
- Local accounts — invite-only (
AUTH_PASSWORD≥ 12 bootstraps the first admin). - Social / enterprise SSO / passkeys — GitHub, Google, Entra, Keycloak, Okta, SAML, WebAuthn (see Auth).
- None — for VPN-protected deployments.
For cloud targets see AWS, Azure, and GCP. The cloud assembly guide covers swapping each layer independently across Vercel, Cloudflare, Deno, Bun, and Lambda.