Migrates this fork to the binarybeachio platform-architecture pivot: oauth2-proxy at the edge enforces a Zitadel session, the auth-bridge mints a short-lived RS256 JWT, and a NEW additive endpoint at /auth/sign-in-trusted/ verifies the JWT, claims its jti against shared-redis (single-use replay protection, fail-closed), find-or-creates the User, and starts a Django session via user_login(). Net surface vs. upstream-clean: 1 new view file + 1 url path + 1 exports __init__ entry + 7 reserved error codes (6000-6099 range). github.py and the GitHub-button rebrand patch are reverted to upstream — sign-in entry-point UX is now driven by Traefik redirectregex on /sign-in* in infrastructure/plane/docker-compose.yml. Replay protection contract: jti claim minted by bridge, consumed via Redis SETNX with ttl = exp - now + 30s. Documented at binarybeachio/docs/architecture/bridge-jwt-replay-protection.md. Public-key transport: BB_BRIDGE_PUBLIC_KEY_URL env points at the in-cluster bridge's /.well-known/bb-bridge.pub.pem (avoids the env-PEM corruption issue Coolify has with backslash-escaped keys). Endpoint is implicitly disabled (404) when env unset — vanilla upstream behavior preserved. Storage patches (Patch 2) unchanged. Brand asset preserved (dormant). Pre-migration source state preserved on branch pre-migration-2026-05-04. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
216 lines
6.1 KiB
YAML
216 lines
6.1 KiB
YAML
# bb-plane-fork local-test compose — binarybeachio
|
|
# ---------------------------------------------------------------------------
|
|
# Spins up a Plane stack on the laptop using:
|
|
# - OUR PATCHED images (plane-backend, plane-frontend) built from this fork
|
|
# - Upstream-vanilla images for the other 4 services (per architecture
|
|
# doc §7.4 — only build what we touched)
|
|
# - Ephemeral local Postgres + Redis + RabbitMQ + MinIO (NOT shared-postgres;
|
|
# this is a destructible dev stack — `docker compose down -v` wipes everything)
|
|
# - Hosted Zitadel (auth.binarybeach.io) for the OIDC flow
|
|
#
|
|
# Build first, then run:
|
|
#
|
|
# # Build patched images locally
|
|
# docker build -t plane-backend:bb-local -f apps/api/Dockerfile.api apps/api/
|
|
# docker build -t plane-frontend:bb-local -f apps/web/Dockerfile.web .
|
|
#
|
|
# # Bring up
|
|
# docker compose -f docker-compose.bb-local.yml --env-file .env.bb-local up -d
|
|
#
|
|
# # Watch logs
|
|
# docker compose -f docker-compose.bb-local.yml logs -f api worker
|
|
#
|
|
# # Visit http://localhost:8888 — log in with email+password (break-glass-style)
|
|
# # or, with BB_BRIDGE_PUBLIC_KEY_URL set, exercise the trusted-JWT endpoint
|
|
# # by hand: GET http://localhost:8888/auth/sign-in-trusted/?token=<jwt>
|
|
#
|
|
# Required env (.env.bb-local — gitignored):
|
|
# BB_BRIDGE_PUBLIC_KEY_URL= # leave unset for vanilla email+password testing
|
|
# ---------------------------------------------------------------------------
|
|
|
|
x-db-env: &db-env
|
|
PGHOST: plane-db
|
|
PGDATABASE: plane
|
|
POSTGRES_USER: plane
|
|
POSTGRES_PASSWORD: plane
|
|
POSTGRES_DB: plane
|
|
POSTGRES_PORT: 5432
|
|
PGDATA: /var/lib/postgresql/data
|
|
|
|
x-redis-env: &redis-env
|
|
REDIS_HOST: plane-redis
|
|
REDIS_PORT: 6379
|
|
REDIS_URL: redis://plane-redis:6379/
|
|
|
|
x-mq-env: &mq-env
|
|
RABBITMQ_HOST: plane-mq
|
|
RABBITMQ_PORT: 5672
|
|
RABBITMQ_DEFAULT_USER: plane
|
|
RABBITMQ_DEFAULT_PASS: plane
|
|
RABBITMQ_DEFAULT_VHOST: plane
|
|
RABBITMQ_USER: plane
|
|
RABBITMQ_PASSWORD: plane
|
|
RABBITMQ_VHOST: plane
|
|
|
|
x-minio-env: &minio-env
|
|
MINIO_ROOT_USER: access-key
|
|
MINIO_ROOT_PASSWORD: secret-key
|
|
|
|
x-aws-s3-env: &aws-s3-env
|
|
AWS_REGION: ""
|
|
AWS_ACCESS_KEY_ID: access-key
|
|
AWS_SECRET_ACCESS_KEY: secret-key
|
|
AWS_S3_ENDPOINT_URL: http://plane-minio:9000
|
|
AWS_S3_BUCKET_NAME: uploads
|
|
|
|
x-proxy-env: &proxy-env
|
|
APP_DOMAIN: localhost:8888
|
|
FILE_SIZE_LIMIT: 5242880
|
|
CERT_EMAIL: ""
|
|
# Plane proxy's Caddy parser requires a syntactically valid CA URL even
|
|
# when not actually using ACME (we serve plain HTTP locally).
|
|
CERT_ACME_CA: https://acme-v02.api.letsencrypt.org/directory
|
|
CERT_ACME_DNS: ""
|
|
LISTEN_HTTP_PORT: 80
|
|
LISTEN_HTTPS_PORT: 443
|
|
BUCKET_NAME: uploads
|
|
SITE_ADDRESS: ":80"
|
|
|
|
x-live-env: &live-env
|
|
API_BASE_URL: http://api:8000
|
|
LIVE_SERVER_SECRET_KEY: bb-local-test-live-secret-do-not-reuse
|
|
|
|
x-app-env: &app-env
|
|
WEB_URL: http://localhost:8888
|
|
CORS_ALLOWED_ORIGINS: http://localhost:8888
|
|
DEBUG: 1
|
|
GUNICORN_WORKERS: 1
|
|
USE_MINIO: 1
|
|
DATABASE_URL: postgresql://plane:plane@plane-db/plane
|
|
SECRET_KEY: bb-local-test-django-secret-do-not-reuse-anywhere-real
|
|
AMQP_URL: amqp://plane:plane@plane-mq:5672/plane
|
|
API_KEY_RATE_LIMIT: 60/minute
|
|
MINIO_ENDPOINT_SSL: 0
|
|
LIVE_SERVER_SECRET_KEY: bb-local-test-live-secret-do-not-reuse
|
|
# === binarybeachio fork: Bucket-4 trusted-JWT entry-point ===
|
|
# When BB_BRIDGE_PUBLIC_KEY_URL is set, /auth/sign-in-trusted/ is enabled
|
|
# and verifies bridge-issued JWTs against the URL-served PEM. When unset,
|
|
# the endpoint returns 404 and Plane behaves like upstream-vanilla.
|
|
# See apps/api/plane/authentication/views/app/trusted.py.
|
|
BB_BRIDGE_PUBLIC_KEY_URL: ${BB_BRIDGE_PUBLIC_KEY_URL:-}
|
|
# === binarybeachio session-lifecycle convention (15 min idle, slide-on-activity) ===
|
|
# Canonical: binarybeachio/infrastructure/_shared/.env.session-convention
|
|
SESSION_COOKIE_AGE: ${SESSION_COOKIE_AGE:-900}
|
|
ADMIN_SESSION_COOKIE_AGE: ${ADMIN_SESSION_COOKIE_AGE:-900}
|
|
SESSION_SAVE_EVERY_REQUEST: ${SESSION_SAVE_EVERY_REQUEST:-1}
|
|
|
|
services:
|
|
api:
|
|
image: plane-backend:bb-local
|
|
command: ./bin/docker-entrypoint-api.sh
|
|
environment:
|
|
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
|
|
depends_on:
|
|
- plane-db
|
|
- plane-redis
|
|
- plane-mq
|
|
|
|
worker:
|
|
image: plane-backend:bb-local
|
|
command: ./bin/docker-entrypoint-worker.sh
|
|
environment:
|
|
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
|
|
depends_on:
|
|
- api
|
|
|
|
beat-worker:
|
|
image: plane-backend:bb-local
|
|
command: ./bin/docker-entrypoint-beat.sh
|
|
environment:
|
|
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
|
|
depends_on:
|
|
- api
|
|
|
|
migrator:
|
|
image: plane-backend:bb-local
|
|
command: ./bin/docker-entrypoint-migrator.sh
|
|
restart: "no"
|
|
environment:
|
|
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
|
|
depends_on:
|
|
- plane-db
|
|
- plane-redis
|
|
|
|
web:
|
|
image: plane-frontend:bb-local
|
|
depends_on:
|
|
- api
|
|
- worker
|
|
|
|
space:
|
|
image: makeplane/plane-space:v1.3.0
|
|
depends_on:
|
|
- api
|
|
- worker
|
|
- web
|
|
|
|
admin:
|
|
image: makeplane/plane-admin:v1.3.0
|
|
depends_on:
|
|
- api
|
|
- web
|
|
|
|
live:
|
|
image: makeplane/plane-live:v1.3.0
|
|
environment:
|
|
<<: [*live-env, *redis-env]
|
|
depends_on:
|
|
- api
|
|
- web
|
|
|
|
plane-db:
|
|
image: postgres:15.7-alpine
|
|
command: postgres -c 'max_connections=1000'
|
|
environment:
|
|
<<: *db-env
|
|
volumes:
|
|
- bb-local-pgdata:/var/lib/postgresql/data
|
|
|
|
plane-redis:
|
|
image: valkey/valkey:7.2.11-alpine
|
|
volumes:
|
|
- bb-local-redisdata:/data
|
|
|
|
plane-mq:
|
|
image: rabbitmq:3.13.6-management-alpine
|
|
environment:
|
|
<<: *mq-env
|
|
volumes:
|
|
- bb-local-rmqdata:/var/lib/rabbitmq
|
|
|
|
plane-minio:
|
|
image: minio/minio:latest
|
|
command: server /export --console-address ":9090"
|
|
environment:
|
|
<<: *minio-env
|
|
volumes:
|
|
- bb-local-minio:/export
|
|
|
|
proxy:
|
|
image: makeplane/plane-proxy:v1.3.0
|
|
environment:
|
|
<<: *proxy-env
|
|
ports:
|
|
- "8888:80"
|
|
depends_on:
|
|
- web
|
|
- api
|
|
- space
|
|
- admin
|
|
- live
|
|
|
|
volumes:
|
|
bb-local-pgdata:
|
|
bb-local-redisdata:
|
|
bb-local-rmqdata:
|
|
bb-local-minio:
|