# ---- Copy this file to .env and fill in the values ---- # Postgres (used by docker-compose for the db service and the DATABASE_URL) POSTGRES_USER=siftlode POSTGRES_PASSWORD=change-this-password POSTGRES_DB=siftlode # Host port the app is exposed on (http://localhost:) APP_PORT=8080 # Session signing key. Generate with: python -c "import secrets;print(secrets.token_urlsafe(48))" # In production (an https OAUTH_REDIRECT_URL) the app refuses to start with this placeholder # or any key shorter than 32 chars — a known signing key would let anyone forge a session. SECRET_KEY=change-me-session-key # Fernet key for encrypting stored OAuth refresh tokens. Generate with: # python -c "import base64,os;print(base64.urlsafe_b64encode(os.urandom(32)).decode())" TOKEN_ENCRYPTION_KEY=change-me-fernet-key # Google OAuth client (Google Cloud Console -> APIs & Services -> Credentials -> OAuth client ID, type "Web application"). # Authorized redirect URI must match OAUTH_REDIRECT_URL exactly. GOOGLE_CLIENT_ID= GOOGLE_CLIENT_SECRET= OAUTH_REDIRECT_URL=http://localhost:8080/auth/callback # Invite list: only these Google account emails may sign in (comma-separated). ALLOWED_EMAILS= # Admin emails (subset of the above) get the admin role. ADMIN_EMAILS= # Optional: origin of a separately-served frontend dev server (enables CORS). Leave empty in production. FRONTEND_ORIGIN= # Optional YouTube Data API key (Google Cloud Console -> Credentials -> Create API key). # When set, all public reads (channels/videos/playlist backfill + enrichment) use the key # instead of a user's OAuth token, so 24/7 backfill never depends on a refresh token that # would otherwise expire (Google expires refresh tokens after 7 days while the OAuth consent # screen is in "Testing"). Strongly recommended for the always-on server instance. YOUTUBE_API_KEY= # Optional: outbound email for onboarding (access-request + approval notices). Gmail SMTP + # App Password (account needs 2FA; generate at https://myaccount.google.com/apppasswords under # the SENDING account). All optional — if unset, email is skipped and onboarding still works # via in-app notifications. SMTP_FROM falls back to SMTP_USER. SMTP_HOST= SMTP_PORT=587 SMTP_USER= SMTP_PASSWORD= SMTP_FROM= # --- Scheduler --- # The background scheduler (subscription sync, backfill, enrichment) runs inside the app. # DATABASE_URL is set for you by docker-compose to the bundled `db` service. If you ever run # more than one instance against the same database, keep SCHEDULER_ENABLED=true on exactly one # of them and false on the rest, to avoid double quota use and write races. SCHEDULER_ENABLED=true # --- Download center --- # The Download Center adds a `worker` container (runs the yt-dlp/ffmpeg job loop) and a small # `bgutil-pot` sidecar (mints YouTube tokens) — both come up automatically with docker compose. # Downloaded media defaults to a Docker-managed named volume. Set DOWNLOAD_HOST_PATH to a host # directory instead — e.g. one your Plex server can read — to keep the Plex-style tree there. # The path must be writable by the container user (uid of `appuser`, 1000): chown 1000:1000 . # DOWNLOAD_HOST_PATH=/mnt/media/youtube # --- Plex integration (optional) --- # The optional Plex module browses/plays your Plex library, playing the LOCAL physical file # directly (Plex is used for metadata only). Enable it in the admin Config page (server URL, # token, path map, libraries). For playback the container must be able to READ the media files, # so bind-mount your Plex media into the container read-only via PLEX_MEDIA_HOST_PATH — it maps # to /plex-media inside the container (the local side of the admin "path map", whose default is # /data=/plex-media). Leave unset if you don't use Plex. # PLEX_MEDIA_HOST_PATH=/mnt/media # Optional: scratch dir for on-the-fly HLS remux segments. Defaults to DOWNLOAD_ROOT; point it at # fast local storage if your download volume is slow. # PLEX_HLS_DIR=/var/tmp/plex-hls