# Fixed project name so the updater container (which runs `docker compose` from a # bind-mount of this file) manages the same containers the host started. name: ${COMPOSE_PROJECT_NAME:-sharely} services: app: build: . ports: # Loopback only: the app trusts X-Forwarded-For from its first hop, so it # must be reachable solely through the reverse proxy. Set BIND_ADDRESS=0.0.0.0 # only behind an external firewall or without a proxy (README: "Cloudflare # Tunnel / proxy in a container"). - "${BIND_ADDRESS:-127.0.0.1}:${PORT:-3000}:3000" environment: MONGODB_URI: "mongodb://${MONGO_APP_USER:-appuser}:${MONGO_APP_PASSWORD}@mongo:27017/${MONGO_DB_NAME:-sharely}?authSource=${MONGO_DB_NAME:-sharely}" SESSION_SECRET: "${SESSION_SECRET}" BASE_URL: "${BASE_URL:-http://localhost:3000}" TRUST_PROXY: "${TRUST_PROXY:-1}" ENCRYPTION_KEY: "${ENCRYPTION_KEY:-}" INSTALL_TOKEN: "${INSTALL_TOKEN:-}" MAX_FILE_SIZE_MB: "${MAX_FILE_SIZE_MB:-100}" ALLOW_REGISTRATION: "${ALLOW_REGISTRATION:-true}" SITE_NAME: "${SITE_NAME:-sharely}" SMTP_HOST: "${SMTP_HOST:-}" SMTP_PORT: "${SMTP_PORT:-587}" SMTP_SECURE: "${SMTP_SECURE:-false}" SMTP_USER: "${SMTP_USER:-}" SMTP_PASS: "${SMTP_PASS:-}" SMTP_FROM: "${SMTP_FROM:-}" LDAP_URL: "${LDAP_URL:-}" LDAP_BIND_DN: "${LDAP_BIND_DN:-}" LDAP_BIND_PASSWORD: "${LDAP_BIND_PASSWORD:-}" LDAP_SEARCH_BASE: "${LDAP_SEARCH_BASE:-}" LDAP_SEARCH_FILTER: "${LDAP_SEARCH_FILTER:-}" LDAP_ATTR_EMAIL: "${LDAP_ATTR_EMAIL:-}" LDAP_TLS_REJECT_UNAUTHORIZED: "${LDAP_TLS_REJECT_UNAUTHORIZED:-}" UPDATE_ENABLED: "${UPDATE_ENABLED:-false}" UPDATE_CONTROL_DIR: "/app/control" UPDATE_CHANNEL: "${UPDATE_CHANNEL:-release}" UPDATE_BRANCH: "${UPDATE_BRANCH:-main}" UPDATE_REPO: "${UPDATE_REPO:-Christianoooooo/sharely}" THUMBNAIL_WORKER_DIR: "/app/thumbjobs" volumes: - uploads:/app/uploads - control:/app/control - thumbjobs:/app/thumbjobs depends_on: mongo: condition: service_healthy healthcheck: test: ["CMD-SHELL", "wget -q --spider http://localhost:3000/ || exit 1"] interval: 30s timeout: 5s retries: 3 start_period: 15s restart: unless-stopped logging: driver: "json-file" options: max-size: "50m" max-file: "5" # Runs ffmpeg/ghostscript on untrusted uploads. Isolated from the app: no network, # no secrets, no access to stored uploads, different user, read-only filesystem. # It only sees the job queue, where the app copies each file to be thumbnailed. thumbnailer: build: . command: ["node", "src/thumbnailWorker.js"] user: "65534:65534" network_mode: none read_only: true tmpfs: - /tmp cap_drop: [ALL] security_opt: - no-new-privileges:true mem_limit: 1g pids_limit: 256 environment: THUMBNAIL_WORKER_DIR: "/app/thumbjobs" volumes: - thumbjobs:/app/thumbjobs restart: unless-stopped logging: driver: "json-file" options: max-size: "10m" max-file: "3" # Privileged helper that applies updates on request from the app. It is the only # container with Docker socket access, so it is opt-in via the "updater" profile # and never starts with a plain `docker compose up`. Enable self-update by also # setting UPDATE_ENABLED=true for the app. updater: build: ./updater profiles: ["updater"] environment: COMPOSE_PROJECT_NAME: "${COMPOSE_PROJECT_NAME:-sharely}" UPDATE_BRANCH: "${UPDATE_BRANCH:-main}" APP_SERVICE: "app" THUMB_SERVICE: "thumbnailer" volumes: - /var/run/docker.sock:/var/run/docker.sock - .:/project - control:/control restart: unless-stopped logging: driver: "json-file" options: max-size: "10m" max-file: "3" mongo: image: mongo:9 ports: - "127.0.0.1:27017:27017" environment: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: "${MONGO_ROOT_PASSWORD}" MONGO_INITDB_DATABASE: "${MONGO_DB_NAME:-sharely}" MONGO_APP_USER: "${MONGO_APP_USER:-appuser}" MONGO_APP_PASSWORD: "${MONGO_APP_PASSWORD}" MONGO_DB_NAME: "${MONGO_DB_NAME:-sharely}" volumes: - mongo_data:/data/db - ./scripts/mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro healthcheck: test: - CMD-SHELL - > mongosh --quiet --eval "db.adminCommand('ping').ok" -u $$MONGO_INITDB_ROOT_USERNAME -p $$MONGO_INITDB_ROOT_PASSWORD --authenticationDatabase admin interval: 10s timeout: 5s retries: 5 start_period: 30s restart: unless-stopped logging: driver: "json-file" options: max-size: "10m" max-file: "3" volumes: uploads: mongo_data: control: thumbjobs: