Files
indee-demo/docker-compose.yml
Dorian faa419fc28 fix: serve service worker with no-cache headers via exact-match location
The sw.js and workbox-*.js files were being caught by the immutable
static asset regex (expires 1y), causing stale service workers and
potential 502 errors during re-registration. Use location = /sw.js
(exact match, highest Nginx priority) and a regex for workbox files
that appears before the asset cache block.

Also removes the dead duplicate location blocks at the bottom of
the config that were never reached due to regex priority.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-13 22:16:13 +00:00

230 lines
7.9 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:
CACHEBUST: "15"
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
args:
CACHEBUST: "10"
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: http://minio:9000
AWS_REGION: us-east-1
AWS_ACCESS_KEY: ${S3_ACCESS_KEY}
AWS_SECRET_KEY: ${S3_SECRET_KEY}
S3_PRIVATE_BUCKET_NAME: indeedhub-private
S3_PUBLIC_BUCKET_NAME: indeedhub-public
S3_PUBLIC_BUCKET_URL: ${S3_PUBLIC_BUCKET_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}
# ── Nostr Auth / JWT ─────────────────────────────────
NOSTR_JWT_SECRET: ${NOSTR_JWT_SECRET}
NOSTR_JWT_EXPIRES_IN: ${NOSTR_JWT_EXPIRES_IN:-7d}
# ── AES-128 Content Encryption ──────────────────────
AES_MASTER_SECRET: ${AES_MASTER_SECRET}
# ── Admin API ────────────────────────────────────────
ADMIN_API_KEY: ${ADMIN_API_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 indeedhub"]
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
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/indeedhub-private --ignore-existing;
mc mb local/indeedhub-public --ignore-existing;
mc anonymous set download local/indeedhub-public;
echo 'MinIO buckets initialized';
"
networks:
- indeedhub-network
restart: "no"
# ── FFmpeg Transcoding Worker ───────────────────────────────
ffmpeg-worker:
build:
context: ./backend
dockerfile: Dockerfile.ffmpeg
args:
CACHEBUST: "12"
restart: unless-stopped
environment:
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: http://minio:9000
AWS_REGION: us-east-1
AWS_ACCESS_KEY: ${S3_ACCESS_KEY}
AWS_SECRET_KEY: ${S3_SECRET_KEY}
S3_PRIVATE_BUCKET_NAME: indeedhub-private
S3_PUBLIC_BUCKET_NAME: 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: