Files
indee-demo/docker-compose.yml
Dorian a8dc82dc59 Update environment variables and enhance Docker configurations for improved deployment
- Modified .env.portainer to include new environment variables for S3 private bucket URL, Nostr JWT secrets, and SendGrid options.
- Updated docker-compose.yml to support the new environment variables, enhancing service configurations.
- Added a seed content script to the backend package.json for initializing the database with sample data.
- Refactored helper functions to construct S3 URLs more robustly, accommodating potential missing configurations.
- Enhanced dev.sh script to seed the database if empty, ensuring content availability during development.
2026-02-13 16:27:51 +00:00

288 lines
11 KiB
YAML

# ═══════════════════════════════════════════════════════════════
# IndeeHub — Production Stack for Portainer
# ═══════════════════════════════════════════════════════════════
#
# All ${VARIABLES} are resolved by Portainer at deploy time.
# Configure them in Portainer → Stacks → Environment variables
# before deploying.
#
# See .env.portainer for the full list of required variables.
#
# For local development, use: docker compose -f docker-compose.dev.yml up
# ═══════════════════════════════════════════════════════════════
version: '3.8'
services:
# ── Frontend (nginx serving built Vue app) ──────────────────
app:
build:
context: .
dockerfile: Dockerfile
args:
VITE_USE_MOCK_DATA: "false"
VITE_CONTENT_ORIGIN: ${FRONTEND_URL}
VITE_INDEEHUB_API_URL: /api
VITE_INDEEHUB_CDN_URL: /storage
VITE_NOSTR_RELAYS: ""
restart: unless-stopped
ports:
- "${APP_PORT:-7777}:7777"
depends_on:
- relay
- api
networks:
- indeedhub-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:7777/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# ── Backend API (NestJS) ────────────────────────────────────
api:
build:
context: ./backend
dockerfile: Dockerfile
restart: unless-stopped
environment:
# ── Core ─────────────────────────────────────────────
ENVIRONMENT: production
PORT: 4000
DOMAIN: ${DOMAIN}
FRONTEND_URL: ${FRONTEND_URL}
# ── Database ─────────────────────────────────────────
DATABASE_HOST: postgres
DATABASE_PORT: 5432
DATABASE_USER: ${POSTGRES_USER}
DATABASE_PASSWORD: ${POSTGRES_PASSWORD}
DATABASE_NAME: ${POSTGRES_DB}
# ── Redis / BullMQ ───────────────────────────────────
QUEUE_HOST: redis
QUEUE_PORT: 6379
QUEUE_PASSWORD: ${REDIS_PASSWORD:-}
# ── S3 / MinIO ──────────────────────────────────────
S3_ENDPOINT: ${S3_ENDPOINT:-http://minio:9000}
AWS_REGION: ${AWS_REGION:-us-east-1}
AWS_ACCESS_KEY: ${S3_ACCESS_KEY}
AWS_SECRET_KEY: ${S3_SECRET_KEY}
S3_PRIVATE_BUCKET_NAME: ${S3_PRIVATE_BUCKET:-indeedhub-private}
S3_PUBLIC_BUCKET_NAME: ${S3_PUBLIC_BUCKET:-indeedhub-public}
S3_PUBLIC_BUCKET_URL: ${S3_PUBLIC_BUCKET_URL}
S3_PRIVATE_BUCKET_URL: ${S3_PRIVATE_BUCKET_URL:-}
# ── CloudFront (leave empty for MinIO/self-hosted) ──
CLOUDFRONT_PRIVATE_KEY: ${CLOUDFRONT_PRIVATE_KEY:-}
CLOUDFRONT_KEY_PAIR_ID: ${CLOUDFRONT_KEY_PAIR_ID:-}
CLOUDFRONT_DISTRIBUTION_URL: ${CLOUDFRONT_DISTRIBUTION_URL:-}
# ── BTCPay Server ───────────────────────────────────
BTCPAY_URL: ${BTCPAY_URL}
BTCPAY_API_KEY: ${BTCPAY_API_KEY}
BTCPAY_STORE_ID: ${BTCPAY_STORE_ID}
BTCPAY_WEBHOOK_SECRET: ${BTCPAY_WEBHOOK_SECRET}
BTCPAY_ROUTE_HINTS: ${BTCPAY_ROUTE_HINTS:-false}
# ── Nostr Auth / JWT ─────────────────────────────────
NOSTR_JWT_SECRET: ${NOSTR_JWT_SECRET}
NOSTR_JWT_EXPIRES_IN: ${NOSTR_JWT_EXPIRES_IN:-7d}
NOSTR_JWT_REFRESH_SECRET: ${NOSTR_JWT_REFRESH_SECRET:-}
NOSTR_JWT_TTL: ${NOSTR_JWT_TTL:-}
NOSTR_JWT_REFRESH_TTL: ${NOSTR_JWT_REFRESH_TTL:-}
# ── AES-128 Content Encryption ──────────────────────
AES_MASTER_SECRET: ${AES_MASTER_SECRET}
# ── SMTP / Email ─────────────────────────────────────
SMTP_HOST: ${SMTP_HOST:-}
SMTP_PORT: ${SMTP_PORT:-587}
SMTP_USER: ${SMTP_USER:-}
SMTP_PASS: ${SMTP_PASS:-}
MAIL_FROM: ${MAIL_FROM:-noreply@indeedhub.local}
# ── SendGrid (optional -- alternative to SMTP) ──────
SENDGRID_API_KEY: ${SENDGRID_API_KEY:-}
SENDGRID_SENDER: ${SENDGRID_SENDER:-}
SENDGRID_WAITLIST: ${SENDGRID_WAITLIST:-}
# ── Cognito (optional -- disabled with Nostr auth) ──
COGNITO_USER_POOL_ID: ${COGNITO_USER_POOL_ID:-}
COGNITO_CLIENT_ID: ${COGNITO_CLIENT_ID:-}
# ── Flash Subscription Secrets (optional) ───────────
FLASH_JWT_SECRET_ENTHUSIAST: ${FLASH_JWT_SECRET_ENTHUSIAST:-}
FLASH_JWT_SECRET_FILM_BUFF: ${FLASH_JWT_SECRET_FILM_BUFF:-}
FLASH_JWT_SECRET_CINEPHILE: ${FLASH_JWT_SECRET_CINEPHILE:-}
FLASH_JWT_SECRET_RSS_ADDON: ${FLASH_JWT_SECRET_RSS_ADDON:-}
FLASH_JWT_SECRET_VERIFICATION_ADDON: ${FLASH_JWT_SECRET_VERIFICATION_ADDON:-}
# ── Transcoding API (optional) ──────────────────────
TRANSCODING_API_KEY: ${TRANSCODING_API_KEY:-}
TRANSCODING_API_URL: ${TRANSCODING_API_URL:-}
# ── PostHog Analytics (optional) ────────────────────
POSTHOG_API_KEY: ${POSTHOG_API_KEY:-}
# ── Sentry Error Tracking (optional) ────────────────
SENTRY_ENVIRONMENT: ${SENTRY_ENVIRONMENT:-production}
# ── DRM (optional) ──────────────────────────────────
DRM_SECRET_NAME: ${DRM_SECRET_NAME:-}
PRIVATE_AUTH_CERTIFICATE_KEY_ID: ${PRIVATE_AUTH_CERTIFICATE_KEY_ID:-}
# ── Podping (optional) ──────────────────────────────
PODPING_URL: ${PODPING_URL:-}
PODPING_KEY: ${PODPING_KEY:-}
PODPING_USER_AGENT: ${PODPING_USER_AGENT:-}
# ── Admin API (optional) ────────────────────────────
ADMIN_API_KEY: ${ADMIN_API_KEY:-}
# ── Partner Content (optional) ──────────────────────
PARTNER_API_BASE_URL: ${PARTNER_API_BASE_URL:-}
PARTNER_API_KEY: ${PARTNER_API_KEY:-}
# ── Strike (optional -- alternative payment provider) ─
STRIKE_API_KEY: ${STRIKE_API_KEY:-}
STRIKE_WEBHOOK_KEY: ${STRIKE_WEBHOOK_KEY:-}
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started
minio:
condition: service_started
networks:
- indeedhub-network
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:4000/nostr-auth/health"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
# ── PostgreSQL Database ─────────────────────────────────────
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- indeedhub-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
# ── Redis (BullMQ job queue) ────────────────────────────────
redis:
image: redis:7-alpine
restart: unless-stopped
command: >
sh -c "if [ -n '${REDIS_PASSWORD:-}' ]; then
redis-server --requirepass '${REDIS_PASSWORD}' --appendonly yes;
else
redis-server --appendonly yes;
fi"
volumes:
- redis-data:/data
networks:
- indeedhub-network
# ── MinIO (S3-compatible object storage) ────────────────────
minio:
image: minio/minio:latest
restart: unless-stopped
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
volumes:
- minio-data:/data
ports:
- "${MINIO_CONSOLE_PORT:-9001}:9001"
networks:
- indeedhub-network
# ── MinIO bucket init (one-shot: creates required buckets) ──
minio-init:
image: minio/mc:latest
depends_on:
- minio
entrypoint: >
/bin/sh -c "
sleep 5;
mc alias set local http://minio:9000 ${MINIO_ROOT_USER} ${MINIO_ROOT_PASSWORD};
mc mb local/${S3_PRIVATE_BUCKET:-indeedhub-private} --ignore-existing;
mc mb local/${S3_PUBLIC_BUCKET:-indeedhub-public} --ignore-existing;
mc anonymous set download local/${S3_PUBLIC_BUCKET:-indeedhub-public};
echo 'MinIO buckets initialized';
"
networks:
- indeedhub-network
restart: "no"
# ── FFmpeg Transcoding Worker ───────────────────────────────
ffmpeg-worker:
build:
context: ./backend
dockerfile: Dockerfile.ffmpeg
restart: unless-stopped
environment:
# Worker shares database + S3 + Redis config with the API
ENVIRONMENT: production
DATABASE_HOST: postgres
DATABASE_PORT: 5432
DATABASE_USER: ${POSTGRES_USER}
DATABASE_PASSWORD: ${POSTGRES_PASSWORD}
DATABASE_NAME: ${POSTGRES_DB}
QUEUE_HOST: redis
QUEUE_PORT: 6379
QUEUE_PASSWORD: ${REDIS_PASSWORD:-}
S3_ENDPOINT: ${S3_ENDPOINT:-http://minio:9000}
AWS_REGION: ${AWS_REGION:-us-east-1}
AWS_ACCESS_KEY: ${S3_ACCESS_KEY}
AWS_SECRET_KEY: ${S3_SECRET_KEY}
S3_PRIVATE_BUCKET_NAME: ${S3_PRIVATE_BUCKET:-indeedhub-private}
S3_PUBLIC_BUCKET_NAME: ${S3_PUBLIC_BUCKET:-indeedhub-public}
S3_PUBLIC_BUCKET_URL: ${S3_PUBLIC_BUCKET_URL}
AES_MASTER_SECRET: ${AES_MASTER_SECRET}
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started
minio:
condition: service_started
networks:
- indeedhub-network
# ── Nostr Relay ─────────────────────────────────────────────
relay:
image: scsibug/nostr-rs-relay:latest
restart: unless-stopped
volumes:
- relay-data:/usr/src/app/db
networks:
- indeedhub-network
networks:
indeedhub-network:
driver: bridge
volumes:
postgres-data:
redis-data:
minio-data:
relay-data: