-
Clone and configure:
git clone https://github.com/maddefientist/Readarr.git cd Readarr cp .env.example .env -
Edit
.envfile:nano .env
Set at least:
BOOKS_PATH- Where your books are storedDOWNLOADS_PATH- Where downloads are savedTZ- Your timezone (e.g.,America/New_York)
-
Start Readarr:
docker compose up -d
-
Access the UI:
- Open: http://localhost:8787
- Complete initial setup wizard
SQLite is used by default with no additional configuration needed. Database files are stored in the /config volume.
Pros:
- Zero configuration
- Simple backup (copy database file)
- Good for most users
Cons:
- Not ideal for high-concurrency scenarios
- Limited to single-node deployments
For better performance or multi-node setups, use PostgreSQL:
-
Edit
docker-compose.yml: Uncomment thepostgresservice section -
Edit
.env:POSTGRES_USER=readarr POSTGRES_PASSWORD=your_secure_password POSTGRES_MAINDB=readarr-main
-
Edit
docker-compose.yml: Uncomment PostgreSQL environment variables in thereadarrservice -
Start services:
docker compose up -d
Pros:
- Better performance
- Supports concurrent operations
- Production-ready
Cons:
- Requires additional container
- More complex backup/restore
| Volume | Purpose | Location |
|---|---|---|
readarr-config |
App config, database, logs | /config |
books |
Your book library | /books |
downloads |
Download client output | /downloads |
Edit .env to use host paths instead of Docker volumes:
# Use absolute paths
BOOKS_PATH=/mnt/media/books
DOWNLOADS_PATH=/mnt/downloadsThen update docker-compose.yml:
volumes:
- ./config:/config # Use local directory
- ${BOOKS_PATH}:/books
- ${DOWNLOADS_PATH}:/downloads- Readarr:
8787
Edit .env:
READARR_PORT=9999location /readarr {
proxy_pass http://localhost:8787;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
}Set in .env:
READARR__URL_BASE=/readarrAdd labels to docker-compose.yml:
labels:
- "traefik.enable=true"
- "traefik.http.routers.readarr.rule=Host(`readarr.example.com`)"
- "traefik.http.routers.readarr.entrypoints=websecure"
- "traefik.http.routers.readarr.tls.certresolver=letsencrypt"
- "traefik.http.services.readarr.loadbalancer.server.port=8787"Built-in health check monitors:
- Web server responsiveness
- Database connectivity
Check status:
docker compose psManual health check:
curl http://localhost:8787/pingExpected response:
{"status": "OK"}Minimum:
- CPU: 2 cores
- RAM: 512MB
- Storage: 100MB (app) + database size
Recommended:
- CPU: 4 cores
- RAM: 2GB
- Storage: SSD for database
-
Change default credentials on first login
-
Use API key authentication:
READARR__API_KEY=your-secure-api-key
-
Enable authentication:
READARR__AUTH_METHOD=Forms READARR__AUTH_REQUIRED=Enabled READARR__USERNAME=admin READARR__PASSWORD=secure_password
-
Run behind reverse proxy with HTTPS
-
Restrict network access:
# docker-compose.yml ports: - "127.0.0.1:8787:8787" # Only localhost
-
Use secrets for sensitive data:
echo "my_password" | docker secret create postgres_password -
SQLite:
# Stop Readarr
docker compose stop readarr
# Backup config volume
docker run --rm -v readarr_readarr-config:/config \
-v $(pwd):/backup alpine \
tar czf /backup/readarr-backup-$(date +%Y%m%d).tar.gz /config
# Restart
docker compose start readarrPostgreSQL:
docker compose exec postgres pg_dump -U readarr readarr-main > backup.sqlSQLite:
docker compose down
docker run --rm -v readarr_readarr-config:/config \
-v $(pwd):/backup alpine \
tar xzf /backup/readarr-backup-20260109.tar.gz -C /
docker compose up -dPostgreSQL:
cat backup.sql | docker compose exec -T postgres psql -U readarr readarr-main# Pull latest image
docker compose pull readarr
# Recreate container
docker compose up -d readarrEdit docker-compose.yml:
services:
readarr:
image: readarr:0.4.20 # Pin to specific versionView logs:
docker compose logs -f readarrLog location:
- Container:
/config/logs/readarr.txt - Host: Check volume mount
Monitor via:
curl http://localhost:8787/api/v1/healthReturns health check results for:
- Download clients
- Indexers
- Import lists
- System health
Export logs to monitoring tools:
# docker-compose.yml
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
labels: "service=readarr"Send to Loki, Elasticsearch, or Sentry.
# Check logs
docker compose logs readarr
# Check health
docker inspect readarr | jq '.[0].State.Health'Fix volume permissions:
docker compose down
sudo chown -R 1000:1000 ./config ./books ./downloads
docker compose up -dOr adjust PUID/PGID in .env:
PUID=1001
PGID=1001SQLite:
- Check disk space
- Verify
/configvolume is writable
PostgreSQL:
- Ensure
postgrescontainer is healthy - Check connection env vars
- Verify network connectivity:
docker compose exec readarr ping postgres
Increase container limits:
# docker-compose.yml
services:
readarr:
mem_limit: 2g
memswap_limit: 2g-
Build from source:
./build.sh --all -r linux-x64
-
Copy to
/opt:sudo cp -r _output/linux-x64/net8.0/Readarr /opt/readarr
-
Create systemd service:
sudo nano /etc/systemd/system/readarr.service
[Unit] Description=Readarr Daemon After=network.target [Service] User=readarr Group=readarr Type=simple ExecStart=/opt/readarr/Readarr -nobrowser -data=/var/lib/readarr Restart=on-failure TimeoutStopSec=20 KillMode=process [Install] WantedBy=multi-user.target
-
Enable and start:
sudo systemctl enable --now readarr
Use the Inno Setup installer:
./build.sh --installer -r win-x64Installs as Windows Service by default.
Use the .app bundle:
./build.sh --packages -r osx-arm64 # or osx-x64Copy Readarr.app to /Applications.
-
Backup old installation (database + config)
-
Stop old service
-
Copy config to new location:
docker run --rm -v readarr_readarr-config:/config \ -v $(pwd)/old-config:/source alpine \ sh -c "cp -r /source/* /config/"
-
Start new Docker container:
docker compose up -d
-
Verify migration - check logs and UI
- Operations Guide - Housekeeping, backups, monitoring
- Development Guide - Contributing
- Architecture Overview - Technical details