services: rnotes: build: context: .. dockerfile: rnotes-online/Dockerfile container_name: rnotes-online restart: unless-stopped environment: - INFISICAL_CLIENT_ID=${INFISICAL_CLIENT_ID} - INFISICAL_CLIENT_SECRET=${INFISICAL_CLIENT_SECRET} - INFISICAL_PROJECT_SLUG=rnotes - INFISICAL_ENV=prod - INFISICAL_URL=http://infisical:8080 - DATABASE_URL=postgresql://rnotes:${DB_PASSWORD}@rnotes-postgres:5432/rnotes # IPFS integration (encrypted file storage via rSpace collab-server kubo) - IPFS_ENABLED=true - IPFS_API_URL=https://ipfs-api.rspace.online - IPFS_GATEWAY_URL=https://ipfs.rspace.online # Y.js collaboration (client-side env var baked at build time) - NEXT_PUBLIC_COLLAB_WS_URL=wss://collab-ws.rnotes.online volumes: - uploads_data:/app/uploads labels: - "traefik.enable=true" - "traefik.http.routers.rnotes.rule=Host(`rnotes.online`) || Host(`www.rnotes.online`)" - "traefik.http.routers.rnotes.entrypoints=web" - "traefik.http.routers.rnotes.priority=130" - "traefik.http.services.rnotes.loadbalancer.server.port=3000" # Wildcard subdomain routing (e.g. cca.rnotes.online) - "traefik.http.routers.rnotes-wildcard.rule=HostRegexp(`{sub:[a-z0-9-]+}.rnotes.online`)" - "traefik.http.routers.rnotes-wildcard.entrypoints=web" - "traefik.http.routers.rnotes-wildcard.priority=100" - "traefik.http.routers.rnotes-wildcard.service=rnotes" networks: - traefik-public - rnotes-internal depends_on: rnotes-postgres: condition: service_healthy cap_drop: - ALL security_opt: - no-new-privileges:true read_only: true tmpfs: - /tmp - /home/nextjs/.npm # Y.js WebSocket server for real-time collaboration rnotes-yws: image: node:22-slim container_name: rnotes-yws restart: unless-stopped working_dir: /app command: - sh - -c - | npm init -y > /dev/null 2>&1 npm install y-websocket@1 ws > /dev/null 2>&1 node -e " const ws = require('ws'); const Y = require('yjs'); const {setupWSConnection, docs} = require('y-websocket/bin/utils'); const host = process.env.HOST || '0.0.0.0'; const port = parseInt(process.env.PORT || '1234'); const wss = new ws.Server({ host, port }); wss.on('connection', setupWSConnection); console.log('y-websocket server running on ' + host + ':' + port); " environment: - HOST=0.0.0.0 - PORT=1234 networks: - traefik-public - rnotes-internal labels: - "traefik.enable=true" - "traefik.http.routers.rnotes-yws.rule=Host(`collab-ws.rnotes.online`)" - "traefik.http.routers.rnotes-yws.entrypoints=web" - "traefik.http.routers.rnotes-yws.priority=140" - "traefik.http.services.rnotes-yws.loadbalancer.server.port=1234" cap_drop: - ALL security_opt: - no-new-privileges:true tmpfs: - /app rnotes-postgres: image: postgres:16-alpine container_name: rnotes-postgres restart: unless-stopped environment: - POSTGRES_USER=rnotes - POSTGRES_PASSWORD=${DB_PASSWORD} - POSTGRES_DB=rnotes volumes: - postgres_data:/var/lib/postgresql/data networks: - rnotes-internal healthcheck: test: ["CMD-SHELL", "pg_isready -U rnotes -d rnotes"] interval: 5s timeout: 5s retries: 5 cap_drop: - ALL cap_add: - DAC_OVERRIDE - FOWNER - SETGID - SETUID security_opt: - no-new-privileges:true networks: traefik-public: external: true rnotes-internal: internal: true volumes: postgres_data: uploads_data: