Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ WHISPARR_API_KEY=
# Lidarr
LIDARR_URL=
LIDARR_API_KEY=
# qBittorrent (WebUI)
# QBITTORRENT_PASSWORD is the WebUI password, or an API key if QBITTORRENT_USERNAME is empty (qBittorrent 5.2+).
# Leave USERNAME and PASSWORD empty if qBittorrent bypasses authentication for Logarr's IP.
QBITTORRENT_URL=
QBITTORRENT_USERNAME=
QBITTORRENT_PASSWORD=

# =============================================================================
# SECURITY & AUTHENTICATION
Expand Down Expand Up @@ -156,6 +162,11 @@ WHISPARR_LOGS_PATH=
# Linux: ~/.config/Lidarr/logs
# Docker: /path/to/lidarr/config/logs
LIDARR_LOGS_PATH=
# qBittorrent examples (container path: /qbittorrent-logs):
# Docker (linuxserver, unverified): /path/to/qbittorrent/config/qBittorrent/logs
# Linux: ~/.local/share/qBittorrent/logs
# Windows: %LOCALAPPDATA%/qBittorrent/logs
QBITTORRENT_LOGS_PATH=

# =============================================================================
# MULTIPLE INSTANCES (optional - for multiple servers of the same type)
Expand Down Expand Up @@ -205,3 +216,6 @@ WHISPARR_LOGS_PATH_3=
LIDARR_LOGS_PATH_1=
LIDARR_LOGS_PATH_2=
LIDARR_LOGS_PATH_3=
QBITTORRENT_LOGS_PATH_1=
QBITTORRENT_LOGS_PATH_2=
QBITTORRENT_LOGS_PATH_3=
5 changes: 5 additions & 0 deletions .env.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ WHISPARR_API_KEY={{ op://Development/Logarr-Dev/WHISPARR_API_KEY }}
# Lidarr
LIDARR_URL={{ op://Development/Logarr-Dev/LIDARR_URL }}
LIDARR_API_KEY={{ op://Development/Logarr-Dev/LIDARR_API_KEY }}
# qBittorrent (not in the 1Password vault yet: add the items, then uncomment)
# QBITTORRENT_URL={{ op://Development/Logarr-Dev/QBITTORRENT_URL }}
# QBITTORRENT_USERNAME={{ op://Development/Logarr-Dev/QBITTORRENT_USERNAME }}
# QBITTORRENT_PASSWORD={{ op://Development/Logarr-Dev/QBITTORRENT_PASSWORD }}

# =============================================================================
# SECURITY & AUTHENTICATION
Expand All @@ -111,3 +115,4 @@ RADARR_LOGS_PATH={{ op://Development/Logarr-Dev/RADARR_LOGS_PATH }}
PROWLARR_LOGS_PATH={{ op://Development/Logarr-Dev/PROWLARR_LOGS_PATH }}
WHISPARR_LOGS_PATH={{ op://Development/Logarr-Dev/WHISPARR_LOGS_PATH }}
LIDARR_LOGS_PATH={{ op://Development/Logarr-Dev/LIDARR_LOGS_PATH }}
# QBITTORRENT_LOGS_PATH={{ op://Development/Logarr-Dev/QBITTORRENT_LOGS_PATH }}
2 changes: 1 addition & 1 deletion .github/agents/my-agent.agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ This is a pnpm + Turborepo TypeScript monorepo.
- `apps/backend`: NestJS 11 API with Drizzle/Postgres, Redis, Socket.IO, Swagger, auth/RBAC, audit logging, retention, ingestion, settings, and proxying.
- `apps/frontend`: Next.js 16 App Router UI with React 19, Tailwind 4, Radix UI, React Query, and realtime socket hooks.
- `packages/core`: shared provider interfaces and normalized cross-service types.
- `packages/provider-*`: provider adapters for Plex, Jellyfin, Emby, Sonarr, Radarr, Prowlarr, Whisparr, Lidarr, plus shared `provider-arr` base logic.
- `packages/provider-*`: provider adapters for Plex, Jellyfin, Emby, Sonarr, Radarr, Prowlarr, Whisparr, Lidarr, qBittorrent, plus shared `provider-arr` base logic.
- `e2e`: Playwright coverage for key UI flows.
- `.github/workflows/docker-publish.yml`: CI gates and container publishing.

Expand Down
109 changes: 72 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
[![Docker](https://img.shields.io/badge/Docker-Ready-2496ED?logo=docker&logoColor=white)](https://www.docker.com/)
[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)

Unified logging, intelligent issue detection, and AI-powered analysis for Plex, Jellyfin, Emby, Sonarr, Radarr, Prowlarr, Whisparr, Lidarr, and more.
Unified logging, intelligent issue detection, and AI-powered analysis for Plex, Jellyfin, Emby, Sonarr, Radarr, Prowlarr, Whisparr, Lidarr, qBittorrent, and more.

[Quick Start](#quick-start) · [Features](#features) · [Screenshots](#screenshots) · [Documentation](#documentation)

Expand Down Expand Up @@ -95,13 +95,13 @@ _Configure multiple AI providers for issue analysis (Anthropic, OpenAI, Google,

## Supported Servers

| Server | Status | Server | Status |
| ------------ | ------------ | ------------ | ------------ |
| **Jellyfin** | ✅ Supported | **Plex** | ✅ Supported |
| **Sonarr** | ✅ Supported | **Emby** | ✅ Supported |
| **Radarr** | ✅ Supported | **Whisparr** | ✅ Supported |
| **Prowlarr** | ✅ Supported | **Lidarr** | ✅ Supported |
| **Kodi** | 🚧 Planned | | |
| Server | Status | Server | Status |
| ------------ | ------------ | --------------- | ------------ |
| **Jellyfin** | ✅ Supported | **Plex** | ✅ Supported |
| **Sonarr** | ✅ Supported | **Emby** | ✅ Supported |
| **Radarr** | ✅ Supported | **Whisparr** | ✅ Supported |
| **Prowlarr** | ✅ Supported | **Lidarr** | ✅ Supported |
| **Kodi** | 🚧 Planned | **qBittorrent** | ✅ Supported |

> Logarr uses a provider architecture—adding support for new servers is straightforward. [Contributions welcome!](#contributing)

Expand Down Expand Up @@ -179,13 +179,15 @@ flowchart TB
PR[Prowlarr]
WH[Whisparr]
LI[Lidarr]
QB[qBittorrent]
end

FE <--> API
FE <--> WS
API <--> PG
API <--> RD
API <--> PX & JF & EM & SO & RA & PR & WH & LI
API <--> PX & JF & EM & SO & RA & PR & WH & QB
```

### How It Works
Expand Down Expand Up @@ -274,22 +276,44 @@ RADARR_LOGS_PATH=/path/to/radarr/config/logs
PROWLARR_LOGS_PATH=/path/to/prowlarr/config/logs
WHISPARR_LOGS_PATH=/path/to/whisparr/config/logs
LIDARR_LOGS_PATH=/path/to/lidarr/config/logs

# Download clients
QBITTORRENT_LOGS_PATH=/path/to/qbittorrent/config/qBittorrent/logs
```

2. **Restart Logarr** — The docker-compose mounts these paths automatically.

3. **Configure in UI** — Go to **Sources** → Edit your server → Enable file ingestion with the container path:

| Server | Container Path |
| -------- | ---------------- |
| Plex | `/plex-logs` |
| Jellyfin | `/jellyfin-logs` |
| Emby | `/emby-logs` |
| Sonarr | `/sonarr-logs` |
| Radarr | `/radarr-logs` |
| Prowlarr | `/prowlarr-logs` |
| Whisparr | `/whisp-logs` |
| Lidarr | `/lidarr-logs` |
| Server | Container Path |
| ----------- | ------------------- |
| Plex | `/plex-logs` |
| Jellyfin | `/jellyfin-logs` |
| Emby | `/emby-logs` |
| Sonarr | `/sonarr-logs` |
| Radarr | `/radarr-logs` |
| Prowlarr | `/prowlarr-logs` |
| Whisparr | `/whisp-logs` |
| Lidarr | `/lidarr-logs` |
| qBittorrent | `/qbittorrent-logs` |

#### qBittorrent authentication

qBittorrent is a standalone provider (WebUI API v2) and is detected from the stored credentials:

| Setup | Username | Password / API key | Notes |
| ---------------------------- | -------- | ------------------ | -------------------------------------------------------- |
| Username + password | set | WebUI password | Cookie session, re-login on expiry |
| API key (qBittorrent >= 5.2) | empty | API key | Sent as `Authorization: Bearer` |
| No authentication | empty | empty | "Bypass authentication" for Logarr's IP / subnet enabled |

Environment variables for auto-setup: `QBITTORRENT_URL`, `QBITTORRENT_USERNAME`, `QBITTORRENT_PASSWORD`.

- Stored passwords and API keys are never returned by the API. When editing a source, leave the password / API key field empty to keep the stored value. The request proxy sends API keys to qBittorrent as `Authorization: Bearer` and does not support username/password sources.
- qBittorrent bans an IP for 1 hour after 5 failed logins. After a failed login Logarr backs off (5, 15, then 60 minutes) instead of retrying every poll; fix the credentials and edit the source to retry immediately.
- Behind a reverse proxy or with Host header validation enabled, qBittorrent may answer 401; allow Logarr's host name in "Server domains".
- The API log feed only reports warnings and critical messages, and is skipped when a log path is configured (the `qbittorrent.log` file is tailed instead). Log file timestamps have no timezone: set the backend `TZ` to qBittorrent's timezone.
- Default log locations are best guesses: `/config/qBittorrent/logs` (linuxserver) and `/config/logs` (hotio) are unverified, so set the log path explicitly.

#### Multiple Instances (e.g., Movies vs Shorts, 1080p vs 4K)

Expand Down Expand Up @@ -325,16 +349,17 @@ Simply add multiple servers in the UI using the same server type but different U

#### Common Log Locations

| Server | Docker | Linux | Windows |
| -------- | -------------------------- | ----------------------------------- | --------------------------------------- |
| Plex | `/config/Library/.../Logs` | `/var/lib/plexmediaserver/.../Logs` | `%LOCALAPPDATA%\Plex Media Server\Logs` |
| Jellyfin | `/config/log` | `/var/lib/jellyfin/log` | `C:\ProgramData\Jellyfin\Server\log` |
| Emby | `/config/logs` | `/var/lib/emby/logs` | `C:\ProgramData\Emby-Server\logs` |
| Sonarr | `/config/logs` | `~/.config/Sonarr/logs` | `C:\ProgramData\Sonarr\logs` |
| Radarr | `/config/logs` | `~/.config/Radarr/logs` | `C:\ProgramData\Radarr\logs` |
| Prowlarr | `/config/logs` | `~/.config/Prowlarr/logs` | `C:\ProgramData\Prowlarr\logs` |
| Whisparr | `/config/logs` | `~/.config/Whisparr/logs` | `C:\ProgramData\Whisparr\logs` |
| Lidarr | `/config/logs` | `~/.config/Lidarr/logs` | `C:\ProgramData\Lidarr\logs` |
| Server | Docker | Linux | Windows |
| ----------- | ---------------------------------------------------- | ----------------------------------- | --------------------------------------- |
| Plex | `/config/Library/.../Logs` | `/var/lib/plexmediaserver/.../Logs` | `%LOCALAPPDATA%\Plex Media Server\Logs` |
| Jellyfin | `/config/log` | `/var/lib/jellyfin/log` | `C:\ProgramData\Jellyfin\Server\log` |
| Emby | `/config/logs` | `/var/lib/emby/logs` | `C:\ProgramData\Emby-Server\logs` |
| Sonarr | `/config/logs` | `~/.config/Sonarr/logs` | `C:\ProgramData\Sonarr\logs` |
| Radarr | `/config/logs` | `~/.config/Radarr/logs` | `C:\ProgramData\Radarr\logs` |
| Prowlarr | `/config/logs` | `~/.config/Prowlarr/logs` | `C:\ProgramData\Prowlarr\logs` |
| Whisparr | `/config/logs` | `~/.config/Whisparr/logs` | `C:\ProgramData\Whisparr\logs` |
| Lidarr | `/config/logs` | `~/.config/Lidarr/logs` | `C:\ProgramData\Lidarr\logs` |
| qBittorrent | `/config/qBittorrent/logs` (linuxserver, unverified) | `~/.local/share/qBittorrent/logs` | `%LOCALAPPDATA%\qBittorrent\logs` |

---

Expand Down Expand Up @@ -377,6 +402,7 @@ logarr/
│ ├── provider-prowlarr/ # Prowlarr integration
│ ├── provider-whisparr/ # Whisparr integration
│ ├── provider-lidarr/ # Lidarr integration
│ ├── provider-qbittorrent/ # qBittorrent integration
│ └── provider-arr/ # Base *arr provider
└── docker-compose.yml
```
Expand Down Expand Up @@ -481,15 +507,24 @@ pnpm test:e2e # Run Playwright E2E tests

### Test Packages

| Package | Description |
| --------------------------- | -------------------------------------- |
| `@logarr/backend` | Backend services and controllers |
| `frontend` | React components, hooks, and utilities |
| `@logarr/core` | Core HTTP utilities |
| `@logarr/provider-arr` | \*arr application log parser |
| `@logarr/provider-emby` | Emby log parser |
| `@logarr/provider-whisparr` | Whisparr provider |
| `@logarr/provider-lidarr` | Lidarr provider |
| Package | Description |
| ------------------------------ | -------------------------------------- |
| `@logarr/backend` | Backend services and controllers |
| `frontend` | React components, hooks, and utilities |
| `@logarr/core` | Core HTTP utilities |
| `@logarr/provider-arr` | \*arr application log parser |
| `@logarr/provider-emby` | Emby log parser |
| `@logarr/provider-whisparr` | Whisparr provider |
| `@logarr/provider-lidarr` | Lidarr provider |
| Package | Description |
| ------------------------------ | -------------------------------------- |
| `@logarr/backend` | Backend services and controllers |
| `frontend` | React components, hooks, and utilities |
| `@logarr/core` | Core HTTP utilities |
| `@logarr/provider-arr` | \*arr application log parser |
| `@logarr/provider-emby` | Emby log parser |
| `@logarr/provider-whisparr` | Whisparr provider |
| `@logarr/provider-qbittorrent` | qBittorrent provider |

> Coverage thresholds are enforced at 80% for statements, branches, functions, and lines.

Expand Down
2 changes: 2 additions & 0 deletions apps/backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ COPY --from=builder --chown=nestjs:nodejs /app/packages/provider-whisparr/packag
COPY --from=builder --chown=nestjs:nodejs /app/packages/provider-whisparr/dist ./packages/provider-whisparr/dist
COPY --from=builder --chown=nestjs:nodejs /app/packages/provider-lidarr/package.json ./packages/provider-lidarr/
COPY --from=builder --chown=nestjs:nodejs /app/packages/provider-lidarr/dist ./packages/provider-lidarr/dist
COPY --from=builder --chown=nestjs:nodejs /app/packages/provider-qbittorrent/package.json ./packages/provider-qbittorrent/
COPY --from=builder --chown=nestjs:nodejs /app/packages/provider-qbittorrent/dist ./packages/provider-qbittorrent/dist

# Copy backend
COPY --from=builder --chown=nestjs:nodejs /app/apps/backend/package.json ./apps/backend/
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ COPY apps/backend/ ./apps/backend/
RUN pnpm install

# Build only the packages (not backend itself - that will be done in watch mode)
RUN pnpm build --filter @logarr/core --filter @logarr/provider-arr --filter @logarr/provider-jellyfin --filter @logarr/provider-sonarr --filter @logarr/provider-radarr --filter @logarr/provider-prowlarr --filter @logarr/provider-plex --filter @logarr/provider-emby --filter @logarr/provider-whisparr --filter @logarr/provider-lidarr
RUN pnpm build --filter @logarr/core --filter @logarr/provider-arr --filter @logarr/provider-jellyfin --filter @logarr/provider-sonarr --filter @logarr/provider-radarr --filter @logarr/provider-prowlarr --filter @logarr/provider-plex --filter @logarr/provider-emby --filter @logarr/provider-whisparr --filter @logarr/provider-lidarr --filter @logarr/provider-qbittorrent

EXPOSE 4002

Expand Down
1 change: 1 addition & 0 deletions apps/backend/drizzle/0010_add-server-username.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE "servers" ADD COLUMN "username" text;
Loading