services: sofarr: image: docker.i3omb.com/sofarr:latest container_name: sofarr restart: unless-stopped ports: # Direct HTTPS (default — uses bundled snakeoil cert if TLS_CERT not set) - "3001:3001" # Uncomment the line below and comment out the above to bind to loopback # only when using a reverse proxy (set TLS_ENABLED=false in that case): # - "127.0.0.1:3001:3001" environment: - PORT=3001 - NODE_ENV=production - LOG_LEVEL=info # --- TLS --- # Default: TLS enabled using bundled snakeoil cert (self-signed). # Supply your own cert/key by mounting them and setting these paths: # - TLS_CERT=/app/certs/server.crt # - TLS_KEY=/app/certs/server.key # Set TLS_ENABLED=false if terminating TLS at a reverse proxy instead. # If using a reverse proxy, also set TRUST_PROXY=1 below. # - TRUST_PROXY=1 # --- Replace placeholders with real values or use Docker secrets --- - COOKIE_SECRET=change-me-generate-with-openssl-rand-hex-32 - EMBY_URL=https://emby.example.com - EMBY_API_KEY=your-emby-api-key - SONARR_INSTANCES=[{"name":"main","url":"https://sonarr.example.com","apiKey":"your-sonarr-api-key"}] - RADARR_INSTANCES=[{"name":"main","url":"https://radarr.example.com","apiKey":"your-radarr-api-key"}] - SABNZBD_INSTANCES=[{"name":"main","url":"https://sabnzbd.example.com","apiKey":"your-sabnzbd-api-key"}] - QBITTORRENT_INSTANCES=[{"name":"main","url":"https://qbittorrent.example.com","username":"admin","password":"your-password"}] volumes: # Persistent volume for token store and log file - sofarr-data:/app/data # Mount your own TLS certificate and key (optional — snakeoil used if omitted) # - /path/to/your/server.crt:/app/certs/server.crt:ro # - /path/to/your/server.key:/app/certs/server.key:ro # Run as the built-in non-root 'node' user (UID/GID 1000) user: "1000:1000" # Read-only root filesystem; only the data volume is writable read_only: true tmpfs: - /tmp # Node.js needs a writable /tmp security_opt: - no-new-privileges:true # prevent privilege escalation via setuid binaries cap_drop: - ALL # drop all Linux capabilities cap_add: [] # add back none — Node.js needs no special caps healthcheck: # Respects TLS_ENABLED: uses http when set to false, https otherwise. # --no-check-certificate handles self-signed / snakeoil certs. test: ["CMD", "/bin/sh", "-c", "[ \"${TLS_ENABLED:-true}\" = \"false\" ] && wget -qO- http://localhost:${PORT:-3001}/health || wget -qO- --no-check-certificate https://localhost:${PORT:-3001}/health"] interval: 30s timeout: 5s retries: 3 start_period: 10s volumes: sofarr-data: