Skip to main content

Installation

Requirements

You'll need:

  • Node.js 18+ and pnpm if you're building from source (the repo pins versions in .node-version and package.json — match those if something won't install)
  • Docker only if you want the container image (no local Node toolchain)
  • SQLite by default (nothing to install) or PostgreSQL if you prefer it
  • At least one of Plex or Jellyfin so webhooks exist
  • Trakt and/or TVTime accounts when you're ready to sync out (you can link those after install)

Choose your installation method

Docker is the low-friction path: pull the image, map a port, keep a volume for data.

Quick start with Docker

Example: run on port 3000, store app data in a named volume scroblarr-data:

docker run -d \
--name scroblarr \
-p 3000:3000 \
-v scroblarr-data:/app/data \
ghcr.io/0xsysr3ll/scroblarr:latest

Then open http://localhost:3000 (or http://192.168.1.50:3000 from another machine on your LAN).

Using Docker Compose

Example compose.yml — Scroblarr on 3000, SQLite in the volume, optional Postgres block commented out:

services:
scroblarr:
image: ghcr.io/0xsysr3ll/scroblarr:latest
container_name: scroblarr
ports:
- "3000:3000"
volumes:
- scroblarr-data:/app/data
environment:
- NODE_ENV=production
- PORT=3000
# Optional: Use PostgreSQL instead of SQLite
# - POSTGRES_HOST=postgres
# - POSTGRES_PORT=5432
# - POSTGRES_USER=scroblarr
# - POSTGRES_PASSWORD=your_password
# - POSTGRES_DATABASE=scroblarr
healthcheck:
test:
[
"CMD-SHELL",
"wget --no-verbose --tries=1 --spider http://localhost:3000/api/v1/auth/check-admin || exit 1",
]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
restart: unless-stopped

# Optional: PostgreSQL for production
# postgres:
# image: postgres:18-alpine
# container_name: scroblarr-postgres
# environment:
# - POSTGRES_USER=scroblarr
# - POSTGRES_PASSWORD=your_password
# - POSTGRES_DB=scroblarr
# volumes:
# - postgres-data:/var/lib/postgresql/data
# restart: unless-stopped

volumes:
scroblarr-data:
# postgres-data:

Bring it up:

docker compose up -d

Docker volumes

The scroblarr-data volume is where SQLite (if you use it), logs, and app data live — think of it as “everything you'd cry about losing.” Backup = snapshot or copy that volume.

Environment variables

Examples of what you might actually set:

VariableExampleWhat it's for
PORT3000HTTP port inside the container
DATA_DIR(default /app/data in the image)Where SQLite + logs + app files go
DATABASE_PATH/app/data/custom.dbFull path to a specific SQLite file
POSTGRES_*host postgres, user scroblarr, …Switch to Postgres instead of SQLite
CORS_ALLOWED_ORIGINShttps://app.example.com,https://scroblarr.example.comOnly needed when the browser loads the UI from a different scheme/host/port than the API (see Configuration)
PUBLIC_DIR/app/publicThe image already ships the built UI here; you'd only change this for a custom build layout
TRUST_PROXYfalseOptional. In production the app trusts one proxy hop by default when behind a reverse proxy. Set to false / 0 / no only if Node is exposed directly without a proxy. Set to true / 1 / yes in non-production if a dev tunnel sends X-Forwarded-For. See Configuration — Trust proxy.

Updating Docker image

docker pull ghcr.io/0xsysr3ll/scroblarr:latest
docker compose down
docker compose up -d

With plain docker run, same idea: stop, remove, pull, run again — your scroblarr-data volume keeps the database.

Next steps

  1. Open the UI (e.g. http://localhost:3000)
  2. Create the first admin user
  3. Set an API key under Settings → General (webhooks won't work until this exists)
  4. Add Plex/Jellyfin under Settings → Media ServerConfiguration walks through it
  5. Paste webhook URLs into Plex/Jellyfin and link Trakt/TVTime when you're ready