Skip to content
🚧 These docs are a work in progress and may contain inaccuracies. Content is being actively reviewed and validated.

Configuration

Dubby can be configured in multiple ways. When the same setting is defined in multiple places, the highest-priority source wins:

Environment variables β†’ YAML config file β†’ Admin UI / database β†’ Auto-detected values β†’ Defaults

Most users only need environment variables. The YAML file is useful for managing many settings in one place, especially in Docker or Kubernetes.


Required variables are validated at startup β€” the server will exit with a descriptive error if they’re missing or invalid.

VariableDescription
BETTER_AUTH_SECRETSecret for session signing and stream token HMAC. Min 32 characters. Generate with openssl rand -base64 32.
DATABASE_URLSQLite database path. Format: file:/path/to/dubby.db. Set automatically in Docker (file:/data/dubby.db).
VariableDefaultDescription
PORT3000HTTP server port
HOST0.0.0.0HTTP server bind address
NODE_ENVdevelopmentproduction for JSON logs and strict CORS. development for pretty-printed logs and permissive CORS. test for unit tests.
LOG_LEVELinfoLog verbosity: debug, info, warn, error
VariableDefaultDescription
DUBBY_DATA_DIR./dataBase data directory (database, images, trickplay)
DUBBY_CACHE_DIR./cacheTranscode cache directory (HLS segments)
DUBBY_METADATA_CACHE_DIRDUBBY_DATA_DIR/imagesImage proxy cache for TMDB artwork
DUBBY_TRICKPLAY_CACHE_DIRDUBBY_DATA_DIR/trickplayTrickplay thumbnail sprites
DUBBY_TRANSCODES_DIR./transcodesAhead-of-time transcode output
DUBBY_LOGS_DIR./logsLog file directory
DUBBY_STATIC_DIRβ€”Web app static files (standalone mode SPA serving)

For details on what’s stored where, see Storage & Paths.

VariableDefaultDescription
REDIS_URLβ€”Valkey/Redis URL for background jobs and real-time events. Format: redis://host:port or redis://:password@host:port
TMDB_API_KEYβ€”TMDB API key for metadata. Free at themoviedb.org. Can also be set in the admin UI.
SENTRY_DSNβ€”Sentry DSN for error tracking (optional)
DATABASE_AUTH_TOKENβ€”Auth token for Turso remote SQLite databases. Only needed if DATABASE_URL uses libsql://.
VariableDefaultDescription
DUBBY_METRICS_ENABLEDtrueEnable Prometheus /metrics endpoint. Set false to disable.

Log format is controlled by NODE_ENV β€” JSON in production, pretty-printed in development. See Monitoring for scrape configuration and available metrics.

VariableDefaultDescription
DUBBY_GPU_ENABLEDtrueEnable hardware transcoding when a GPU is available

See Transcoding for the full list of transcoding environment variables.

VariableDefaultDescription
DUBBY_MODEstandalonestandalone (HTTP + workers), api (HTTP only), worker (workers only)
DUBBY_QUEUESallComma-separated list of enabled queue names. Useful for partitioning work across specialized workers.

Available queues: scan, ingest-prepare, ingest-enrich, ingest-enhance, analyze, metadata, subtitle, detect-intros, optimize, optimize-orchestrator, system, backup, migration

VariableDefaultDescription
DUBBY_ENCRYPTION_KEYauto-generatedEncryption key for sensitive config values (API keys stored in DB). Min 32 chars. Auto-generated and saved to DUBBY_DATA_DIR/.encryption-key if not set.
Terminal window
# Required
BETTER_AUTH_SECRET=your-secret-here-at-least-32-chars
# Optional: metadata (can also be set in admin UI)
TMDB_API_KEY=your-tmdb-api-key
# Optional: job queue (recommended)
REDIS_URL=redis://valkey:6379
# Optional: logging
LOG_LEVEL=info

If REDIS_URL is set but the connection fails, the server logs a warning and continues without the job system:

WARN Failed to connect to Redis/Valkey β€” job queue disabled

Playback and browsing continue working. Background tasks (scanning, metadata, subtitles) are paused until the connection is restored.


For managing many settings at once, Dubby supports a YAML configuration file. This is especially useful in Docker or Kubernetes where you can mount a config file into the container.

Dubby looks for the config file in this order:

  1. Path specified by DUBBY_CONFIG_FILE environment variable
  2. /config/dubby.yaml (Docker default)
  3. ./dubby.yaml (current working directory)

In Docker Compose, mount a config file:

volumes:
- ./dubby.yaml:/config/dubby.yaml:ro

In Kubernetes, use a ConfigMap:

volumes:
- name: config
configMap:
name: dubby-config
containers:
- volumeMounts:
- name: config
mountPath: /config

API keys and secrets cannot be set in the YAML file β€” use environment variables or the admin UI for these:

  • DUBBY_TMDB_API_KEY
  • DUBBY_TVDB_API_KEY
  • DUBBY_MDBLIST_API_KEY
  • DUBBY_OPENSUBTITLES_API_KEY
  • DUBBY_LICENSE_KEY

The full config file with all available settings and their defaults. Uncomment and change as needed. Each key shows the corresponding DUBBY_* environment variable.

# ── Session ──────────────────────────────────────────────────────────────
session:
# maxTranscodesPerUser: 1 # 1–10 DUBBY_MAX_TRANSCODES_PER_USER
# maxTranscodesGlobal: # 1–32, auto-detected DUBBY_MAX_TRANSCODES_GLOBAL
# idleTimeoutMs: 120000 # 10s–10min DUBBY_SESSION_IDLE_TIMEOUT_MS
# seekDebounceMs: 150 # 50–1000ms DUBBY_SESSION_SEEK_DEBOUNCE_MS
# processGracePeriodMs: 5000 # 1s–30s DUBBY_SESSION_PROCESS_GRACE_PERIOD_MS
# reaperIntervalMs: 10000 # 5s–60s DUBBY_SESSION_REAPER_INTERVAL_MS
# tombstoneRetentionMs: 1800000 # 1min–2hr DUBBY_SESSION_TOMBSTONE_RETENTION_MS
# statsIntervalMs: 60000 # 10s–5min DUBBY_SESSION_STATS_INTERVAL_MS
# firstSegmentTimeoutMs: 90000 # 10s–5min DUBBY_SESSION_FIRST_SEGMENT_TIMEOUT_MS
# noProgressTimeoutMs: 120000 # 10s–5min DUBBY_SESSION_NO_PROGRESS_TIMEOUT_MS
# ── Transcoding ──────────────────────────────────────────────────────────
transcoding:
# gpuEnabled: true # GPU hardware accel DUBBY_GPU_ENABLED
# multiQualityEnabled: true # Multi-quality ABR DUBBY_MULTI_QUALITY
# maxQualityTiers: 4 # 1–6 DUBBY_MAX_QUALITY_TIERS
# defaultCrf: 23 # 0–51, lower=better DUBBY_TRANSCODING_DEFAULT_CRF
# defaultPreset: fast # ultrafast..veryslow DUBBY_TRANSCODING_DEFAULT_PRESET
# hlsSegmentDuration: 4 # 2–10 seconds DUBBY_TRANSCODING_HLS_SEGMENT_DURATION
# diskWarningThresholdGB: 10 # 1–1000 GB DUBBY_TRANSCODING_DISK_WARNING_THRESHOLD_GB
# diskCriticalThresholdGB: 2 # 1–100 GB DUBBY_TRANSCODING_DISK_CRITICAL_THRESHOLD_GB
# maxCacheSizePerUserGB: 20 # 1–1000 GB DUBBY_TRANSCODING_MAX_CACHE_SIZE_PER_USER_GB
# maxTotalCacheSizeGB: 100 # 1–10000 GB DUBBY_TRANSCODING_MAX_TOTAL_CACHE_SIZE_GB
# ── Library ──────────────────────────────────────────────────────────────
library:
# ingestConcurrency: # 1–20, auto-detected DUBBY_INGEST_CONCURRENCY
# watcherPollIntervalMs: 5000 # 1s–30s DUBBY_LIBRARY_WATCHER_POLL_INTERVAL_MS
# metadataRetryIntervalMs: 3600000 # 1min–24hr DUBBY_LIBRARY_METADATA_RETRY_INTERVAL_MS
# fileStableChecks: 3 # 1–10 DUBBY_LIBRARY_FILE_STABLE_CHECKS
# ── Rate Limiting ────────────────────────────────────────────────────────
rateLimit:
# loginMaxAttempts: 5 # 1–100 DUBBY_RATE_LIMIT_LOGIN_MAX_ATTEMPTS
# loginWindowMs: 900000 # 10s–24hr (15min) DUBBY_RATE_LIMIT_LOGIN_WINDOW_MS
# registerMaxAttempts: 3 # 1–100 DUBBY_RATE_LIMIT_REGISTER_MAX_ATTEMPTS
# registerWindowMs: 3600000 # 10s–24hr (1hr) DUBBY_RATE_LIMIT_REGISTER_WINDOW_MS
# refreshMaxAttempts: 10 # 1–100 DUBBY_RATE_LIMIT_REFRESH_MAX_ATTEMPTS
# refreshWindowMs: 60000 # 10s–24hr (1min) DUBBY_RATE_LIMIT_REFRESH_WINDOW_MS
# apiMaxRequests: 100 # 1–10000 DUBBY_RATE_LIMIT_API_MAX_REQUESTS
# apiWindowMs: 60000 # 10s–24hr (1min) DUBBY_RATE_LIMIT_API_WINDOW_MS
# ── Server ───────────────────────────────────────────────────────────────
server:
# allowedOrigins: [] # CORS origins (JSON) DUBBY_SERVER_ALLOWED_ORIGINS
# transcodeDir: /tmp/dubby/transcode DUBBY_SERVER_TRANSCODE_DIR
# ssePingIntervalMs: 30000 # 5s–120s DUBBY_SERVER_SSE_PING_INTERVAL_MS
# ── UI ───────────────────────────────────────────────────────────────────
ui:
# accentColor: sky # DUBBY_ACCENT_COLOR
# titleDisplayMode: logo # logo|text|hidden DUBBY_TITLE_DISPLAY_MODE
# allowUserAccentOverride: false # DUBBY_ALLOW_USER_ACCENT_OVERRIDE
# ── Privacy ──────────────────────────────────────────────────────────────
privacy:
# level: private # maximum|private|balanced|open DUBBY_PRIVACY_LEVEL
# allowExternalConnections: false # DUBBY_ALLOW_EXTERNAL
# localAnalyticsEnabled: true # DUBBY_PRIVACY_LOCAL_ANALYTICS
# anonymousSharingEnabled: false # DUBBY_PRIVACY_ANONYMOUS_SHARING
# tmdbEnabled: false # DUBBY_PRIVACY_TMDB_ENABLED
# tmdbProxyImages: true # DUBBY_PRIVACY_TMDB_PROXY_IMAGES
# opensubtitlesEnabled: false # DUBBY_PRIVACY_OPENSUBTITLES_ENABLED
# maskFilePaths: true # DUBBY_PRIVACY_MASK_FILE_PATHS
# maskMediaTitles: true # DUBBY_PRIVACY_MASK_MEDIA_TITLES
# maskUserInfo: true # DUBBY_PRIVACY_MASK_USER_INFO
# maskIpAddresses: true # DUBBY_PRIVACY_MASK_IP_ADDRESSES
# analyticsRetentionDays: null # days, null=indefinite DUBBY_PRIVACY_ANALYTICS_RETENTION_DAYS
# auditRetentionDays: null # days, null=indefinite DUBBY_PRIVACY_AUDIT_RETENTION_DAYS
# ── Optimization ─────────────────────────────────────────────────────────
optimization:
# enabled: false # DUBBY_OPTIMIZATION_ENABLED
# maxResolution: 4k # 4k|1080p DUBBY_OPTIMIZATION_MAX_RESOLUTION
# encodingPriority: balanced # quality|balanced|speed DUBBY_OPTIMIZATION_ENCODING_PRIORITY
# hdrDisplays: false # DUBBY_OPTIMIZATION_HDR_DISPLAYS
# remoteStreaming: false # DUBBY_OPTIMIZATION_REMOTE_STREAMING
# uploadSpeedMbps: 0 # 0=not set DUBBY_OPTIMIZATION_UPLOAD_SPEED_MBPS
# simultaneousStreams: 1 # 1–10 DUBBY_OPTIMIZATION_SIMULTANEOUS_STREAMS
# storageMode: cache_dir # cache_dir|alongside DUBBY_OPTIMIZATION_STORAGE_MODE
# storagePath: "" # DUBBY_OPTIMIZATION_STORAGE_PATH
# storageBudgetGb: 0 # 0=unlimited DUBBY_OPTIMIZATION_STORAGE_BUDGET_GB
# replaceOriginals: false # DUBBY_OPTIMIZATION_REPLACE_ORIGINALS
# autoOptimizeOnIngest: false # DUBBY_OPTIMIZATION_AUTO_OPTIMIZE_ON_INGEST
# retentionMode: keep_originals # keep_originals|archive_local|replace_originals
# # DUBBY_OPTIMIZATION_RETENTION_MODE
# archivePath: "" # DUBBY_OPTIMIZATION_ARCHIVE_PATH
# primaryLanguage: en # DUBBY_OPTIMIZATION_PRIMARY_LANGUAGE
# keepOriginalLanguage: true # DUBBY_OPTIMIZATION_KEEP_ORIGINAL_LANGUAGE
# additionalLanguages: [] # DUBBY_OPTIMIZATION_ADDITIONAL_LANGUAGES
# encodingProfile: "" # DUBBY_OPTIMIZATION_ENCODING_PROFILE
# deviceCategories: [] # apple_tv|android_tv|roku|smart_tvs|ios_devices|
# # android_mobile|web_browsers|playstation|xbox|
# # mac|windows|fire_tv_vega
# # DUBBY_OPTIMIZATION_DEVICE_CATEGORIES
# audioEnvironments: {} # {"name": "home_theater"|"soundbar"|"tv_speakers"}
# # DUBBY_OPTIMIZATION_AUDIO_ENVIRONMENTS
# subtitleLanguages: [] # DUBBY_OPTIMIZATION_SUBTITLE_LANGUAGES
# ── Providers ────────────────────────────────────────────────────────────
providers:
# displayMovieProvider: tmdb # DUBBY_PROVIDERS_DISPLAY_MOVIE_PROVIDER
# displayTvProvider: tmdb # DUBBY_PROVIDERS_DISPLAY_TV_PROVIDER
# enabledRatingSources: [imdb, rt_critics] DUBBY_PROVIDERS_ENABLED_RATING_SOURCES
# ratingSourceOrder: null # custom order or null DUBBY_PROVIDERS_RATING_SOURCE_ORDER