Skip to content

Installation

Librariarr runs as a Docker container. The recommended setup uses Docker Compose with a PostgreSQL database.

  • Docker and Docker Compose v2+
  • A Plex, Jellyfin, or Emby media server
  1. Create a docker-compose.yml

    Create a directory for Librariarr and add the following docker-compose.yml:

    docker-compose.yml
    services:
    librariarr:
    image: ahembree/librariarr:latest
    container_name: librariarr
    ports:
    - "${LIBRARIARR_PORT:-3000}:3000"
    environment:
    - DATABASE_URL=postgresql://librariarr:${DB_PASSWORD}@librariarr-db:5432/librariarr
    - SESSION_SECRET=${SESSION_SECRET:-}
    - TZ=${TZ:-UTC}
    - PUID=${PUID:-1000}
    - PGID=${PGID:-1000}
    volumes:
    - ./config:/config
    healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
    interval: 30s
    timeout: 5s
    start_period: 60s
    retries: 3
    depends_on:
    librariarr-db:
    condition: service_healthy
    restart: unless-stopped
    librariarr-db:
    image: postgres:18-alpine
    container_name: librariarr-db
    environment:
    POSTGRES_USER: librariarr
    POSTGRES_PASSWORD: ${DB_PASSWORD}
    POSTGRES_DB: librariarr
    volumes:
    - librariarr-db:/var/lib/postgresql
    healthcheck:
    test: ["CMD-SHELL", "pg_isready -U librariarr"]
    interval: 5s
    timeout: 5s
    retries: 5
    restart: unless-stopped
    volumes:
    librariarr-db:
  2. Create a .env file

    .env
    # Required — database password
    DB_PASSWORD=your-secure-db-password
    # Optional — session encryption key (auto-generated if not set)
    # SESSION_SECRET=your-random-secret-here
    # Optional
    PUID=1000
    PGID=1000
    LIBRARIARR_PORT=3000
  3. Start the stack

    Terminal window
    docker compose up -d
  4. Open the app

    Navigate to http://your-server:3000. You'll be directed to the login page where you can sign in with Plex or create local credentials.

VariableRequiredDefaultDescription
DATABASE_URLYesPostgreSQL connection URL (provided in the docker-compose.yml above)
SESSION_SECRETNoAuto-generatedRandom string (32+ characters) used to secure your login sessions. Auto-generated and saved to /config/.session-secret if not set.
PUIDNo1000User ID for file permissions
PGIDNo1000Group ID for file permissions
UMASKNo022File permission mask. Override only if your environment requires different permissions.
LIBRARIARR_PORTNo3000Host port to expose
TZNoUTCTimezone for scheduled jobs (e.g., America/New_York) — full list
NEXT_TELEMETRY_DISABLEDNo1Always set to 1 by the container. Next.js telemetry is permanently disabled.
LOG_DEBUGNofalseEnable debug-level logging
BACKUP_DIRNo/config/backupsBackup storage directory
IMAGE_CACHE_DIRNo/config/cache/imagesArtwork cache directory
PREROLL_ALLOWED_PATHSNo/media,/data,/mnt,/opt/prerollsComma-separated list of allowed directory prefixes for preroll file validation
SSO_DISABLE_OVERRIDENounsetBreak-glass: set to true to force SSO off regardless of stored settings. Used to recover access when locked out of an IdP. Restart required.
COOKIE_SECURENofalseSet the Secure attribute on the session cookie (browser only sends it over HTTPS). Strongly recommended (COOKIE_SECURE=true) for any deployment fronted by HTTPS — prevents the cookie from being transmitted on accidental HTTP downgrades. Leave unset/false for direct HTTP access (LAN, http://host:3000 without a TLS-terminating proxy) — otherwise the browser will refuse to send the cookie and you won't stay logged in.
TRUST_PROXY_HEADERSNotrueWhether to trust X-Forwarded-For / X-Real-IP headers when computing rate-limit buckets. Leave as true when behind a reverse proxy. Set to false if Librariarr is exposed directly to the internet — preventing attackers from rotating X-Forwarded-For to bypass per-IP rate limits (at the cost of a single shared rate-limit bucket for all clients).

Librariarr images are published to Docker Hub:

TagDescription
latestThe most recent stable release. Recommended for most users.
X.Y.Z, X.Y, XSpecific release versions. Pin to one of these for reproducible deployments.
nightlyRolling build from the latest commit on main — the newest changes that haven't been cut into a release yet. Handy for testing upcoming fixes/features, but expect occasional breakage.
nightly-<sha>Immutable per-commit nightly build, useful for pinning to or rolling back to a specific commit.

The latest and version tags are published only from tagged releases. The nightly tags are built from every push to main and never overwrite a stable release, so switching back is just a matter of changing the tag.

All persistent data is stored under /config inside the container:

  • /config/backups/ — Backup files (override with BACKUP_DIR)
  • /config/cache/images/ — Cached artwork (override with IMAGE_CACHE_DIR)
  • Database — All configuration, rules, and media metadata is stored in PostgreSQL

If you already have a PostgreSQL server (e.g., a shared instance on your network or a managed database), you can skip the librariarr-db container and point Librariarr directly at it.

  • PostgreSQL 14 or later (17+ recommended)
  • A dedicated database for Librariarr (the app manages its own schema)
  • A user with full privileges on that database (CREATE, ALTER, DROP, INSERT, UPDATE, DELETE). The CREATE privilege is required: in addition to the application tables, Librariarr's background job queue (Graphile Worker) creates and manages a separate graphile_worker schema automatically on first start.
  • No PostgreSQL extensions are required
  1. Create the database and user on your PostgreSQL server:

    CREATE USER librariarr WITH PASSWORD 'your-secure-password';
    CREATE DATABASE librariarr OWNER librariarr;
  2. Use a simplified docker-compose.yml without the database service:

    docker-compose.yml
    services:
    librariarr:
    image: ahembree/librariarr:latest
    container_name: librariarr
    ports:
    - "${LIBRARIARR_PORT:-3000}:3000"
    environment:
    - DATABASE_URL=postgresql://librariarr:${DB_PASSWORD}@your-db-host:5432/librariarr
    - SESSION_SECRET=${SESSION_SECRET:-}
    - TZ=${TZ:-UTC}
    - PUID=${PUID:-1000}
    - PGID=${PGID:-1000}
    volumes:
    - ./config:/config
    healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
    interval: 30s
    timeout: 5s
    start_period: 60s
    retries: 3
    restart: unless-stopped
  3. Update your .env file with the database password and hostname:

    .env
    DB_PASSWORD=your-secure-password

    Adjust the DATABASE_URL in docker-compose.yml to match your PostgreSQL server's hostname, port, and credentials.

  4. Start the container:

    Terminal window
    docker compose up -d

By default, Docker Compose creates an isolated network for the Librariarr stack. This works well when you access media servers and integrations (Sonarr, Radarr, etc.) via their host IP addresses. However, if your other services are also running in Docker, you can connect them on a shared network so they can communicate by container name instead.

If your media server or Arr apps run in separate Docker Compose stacks, create an external network that all stacks share:

Terminal window
docker network create media

Then reference it in each stack. For Librariarr:

docker-compose.yml
services:
librariarr:
image: ahembree/librariarr:latest
container_name: librariarr
ports:
- "${LIBRARIARR_PORT:-3000}:3000"
environment:
- DATABASE_URL=postgresql://librariarr:${DB_PASSWORD}@librariarr-db:5432/librariarr
- SESSION_SECRET=${SESSION_SECRET:-}
- TZ=${TZ:-UTC}
- PUID=${PUID:-1000}
- PGID=${PGID:-1000}
volumes:
- ./config:/config
networks:
- default
- media
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
interval: 30s
timeout: 5s
start_period: 60s
retries: 3
depends_on:
librariarr-db:
condition: service_healthy
restart: unless-stopped
librariarr-db:
image: postgres:18-alpine
container_name: librariarr-db
environment:
POSTGRES_USER: librariarr
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: librariarr
volumes:
- librariarr-db:/var/lib/postgresql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U librariarr"]
interval: 5s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
default:
media:
external: true
volumes:
librariarr-db:

Add the same media network to your other stacks (Plex, Sonarr, Radarr, etc.):

Other stack's docker-compose.yml (excerpt)
services:
sonarr:
# ... existing config ...
networks:
- default
- media
networks:
default:
media:
external: true

Once all containers are on the media network, you can reference them by container name when adding servers and integrations in Librariarr (e.g., http://plex:32400, http://sonarr:8989).

On every container start, Librariarr:

  1. Checks database connectivity (retries up to 30 times)
  2. Runs any pending database updates automatically
  3. Starts the web server on port 3000

If database updates fail, the container uses a fallback method to ensure the database is current.

To update to the latest version:

Terminal window
docker compose pull
docker compose up -d

Database updates run automatically on startup — no manual steps needed.

Librariarr is an installable progressive web app. Open your instance in a mobile or desktop browser and use Add to Home Screen (iOS Safari / Android Chrome) or the browser's install prompt (desktop Chrome/Edge) to get a standalone app window with its own icon. The layout adapts to phones — the sidebar becomes a slide-out drawer and pages respect device safe areas.