Varken (Dutch for "PIG" — Plex/InfluxDB/Grafana)
Aggregate data from the Plex ecosystem into InfluxDB for beautiful Grafana dashboards.
Monitor Sonarr, Radarr, Tautulli, Overseerr, and more — all in one place.
Installation • Configuration • Services • Development
Built with TypeScript, Node.js, and a plugin-based architecture with scheduled data collection.
- Multiple data sources — Sonarr, Radarr, Readarr, Lidarr, Tautulli, Ombi, Overseerr, Prowlarr, Bazarr
- Multiple outputs — InfluxDB 1.x and InfluxDB 2.x
- Multi-instance support — connect multiple instances of each service
- GeoIP mapping — automatic geolocation of streaming sessions via Tautulli API (no external license required)
- Circuit breaker — automatic error recovery with exponential backoff and self-healing
- Health checks — built-in HTTP endpoints for monitoring and orchestration
- Easy configuration — simple YAML config with environment variable overrides
- Docker ready — multi-platform images for amd64 and arm64
- Lightweight — Node.js 24 Alpine-based image
- Configurable — environment variables, YAML, or legacy INI migration
| Service | Data Collected | Status |
|---|---|---|
| Sonarr | Queue, calendar (missing/future episodes) | ✅ |
| Radarr | Queue, missing movies | ✅ |
| Readarr | Queue, missing eBooks | ✅ |
| Lidarr | Queue, missing music | ✅ |
| Tautulli | Activity, libraries, statistics, GeoIP | ✅ |
| Ombi | Request counts, issue counts | ✅ |
| Overseerr | Request counts, latest requests | ✅ |
| Prowlarr | Indexer statistics | ✅ |
| Bazarr | Wanted subtitles, history | ✅ |
| Plex | Sessions, libraries (direct API) | 🚧 Planned |
| Jellyfin | Sessions, libraries, activity | 🚧 Planned |
| Output | Status |
|---|---|
| InfluxDB 2.x (recommended) | ✅ |
| InfluxDB 1.x (legacy) | ✅ |
mkdir varken && cd varken
curl -O https://raw.githubusercontent.com/navino16/Varken/develop/docker-compose.yml
mkdir config
curl -o config/varken.yaml https://raw.githubusercontent.com/navino16/Varken/develop/config/varken.example.yamlEdit config/varken.yaml with your settings, then:
docker compose up -d- Grafana: http://localhost:3000 (admin/admin)
- InfluxDB: http://localhost:8086
docker run -d \
--name varken \
-v /path/to/config:/config \
-v /path/to/data:/data \
-e TZ=Europe/Paris \
ghcr.io/navino16/varken:latestgit clone https://github.com/navino16/Varken.git
cd Varken
npm install
npm run build
cp config/varken.example.yaml config/varken.yaml
npm startoutputs:
influxdb2:
url: "http://influxdb:8086"
token: "your-influxdb-token"
org: "varken"
bucket: "varken"
inputs:
sonarr:
- id: 1
url: "http://sonarr:8989"
apiKey: "your-sonarr-api-key"
queue:
enabled: true
intervalSeconds: 30
calendar:
enabled: true
futureDays: 7
missingDays: 30
intervalSeconds: 300
tautulli:
- id: 1
url: "http://tautulli:8181"
apiKey: "your-tautulli-api-key"
activity:
enabled: true
intervalSeconds: 30Varken provides global configuration options for tuning timeouts and pagination. All settings have sensible defaults and are optional:
global:
httpTimeoutMs: 30000
healthCheckTimeoutMs: 5000
collectorTimeoutMs: 60000
paginationPageSize: 250
maxPaginationRecords: 10000| Setting | Default | Description |
|---|---|---|
httpTimeoutMs |
30000 | Timeout for HTTP requests to services |
healthCheckTimeoutMs |
5000 | Timeout for health check requests |
collectorTimeoutMs |
60000 | Timeout for collector execution |
paginationPageSize |
250 | Records per page for paginated APIs |
maxPaginationRecords |
10000 | Maximum records to fetch (safety limit) |
| Variable | Default | Description |
|---|---|---|
CONFIG_FOLDER |
/config |
Path to configuration files |
DATA_FOLDER |
/data |
Path to data storage |
LOG_FOLDER |
/logs |
Path to log files |
LOG_LEVEL |
info |
Log level: error, warn, info, debug |
TZ |
UTC |
Timezone (e.g., Europe/Paris, America/New_York) |
HEALTH_PORT |
9090 |
Port for the health check HTTP server |
HEALTH_ENABLED |
true |
Enable/disable the health check server |
You can override any configuration value using environment variables:
# Format: VARKEN_<SECTION>_<KEY>=value
VARKEN_OUTPUTS_INFLUXDB2_URL="http://influxdb:8086"
VARKEN_OUTPUTS_INFLUXDB2_TOKEN="my-secret-token"
# For array items, use numeric index
VARKEN_INPUTS_SONARR_0_APIKEY="secret-api-key"
VARKEN_INPUTS_SONARR_0_URL="http://sonarr:8989"The Tautulli API handles GeoIP geolocation directly — no external license or database download required.
inputs:
tautulli:
- id: 1
url: "http://tautulli:8181"
apiKey: "your-api-key"
geoip:
enabled: true
localCoordinates:
latitude: 48.8566
longitude: 2.3522How it works:
- Remote streams: Varken calls Tautulli's
get_geoip_lookupAPI to get location data - Local streams (LAN): Automatically detected and labeled as "Local Network"
- localCoordinates (optional): Custom coordinates to display for local streams on world maps
Note: If upgrading from a previous version with
licenseKeyorfallbackIp, these options are now deprecated and will be ignored with a warning.
You can monitor multiple instances of the same service:
inputs:
sonarr:
- id: 1
url: "http://sonarr-tv:8989"
apiKey: "api-key-1"
queue:
enabled: true
intervalSeconds: 30
- id: 2
url: "http://sonarr-anime:8989"
apiKey: "api-key-2"
queue:
enabled: true
intervalSeconds: 30Each instance must have a unique id.
Varken includes a built-in circuit breaker to handle failing services gracefully. When a scheduler encounters repeated errors, the circuit breaker:
- Applies backoff — increases the interval between retries (exponential backoff)
- Opens the circuit — temporarily disables the failing scheduler after too many errors
- Attempts recovery — after a cooldown period, tests if the service has recovered
- Closes the circuit — returns to normal operation after successful recovery
circuitBreaker:
maxConsecutiveErrors: 10 # Errors before disabling scheduler
backoffMultiplier: 2 # Interval multiplier per failure (30s → 60s → 120s...)
maxIntervalSeconds: 600 # Maximum interval cap (10 min)
cooldownSeconds: 300 # Cooldown before recovery attempt (5 min)
recoverySuccesses: 3 # Successes needed to fully recoverCLOSED (normal) ──[errors]──► OPEN (disabled)
│
[cooldown]
│
▼
HALF-OPEN (testing)
│
┌───────────────┼───────────────┐
│ │ │
[success x N] [failure] [success]
│ │ │
▼ ▼ │
CLOSED OPEN │
▲ │
└───────────────┘
Circuit breaker states are visible in the /status endpoint:
{
"schedulers": [
{
"name": "sonarr_1_queue",
"circuitState": "closed",
"currentIntervalSeconds": 30,
"consecutiveErrors": 0,
"recoverySuccesses": 0,
"nextRunAt": "2024-01-15T10:30:30.000Z"
}
]
}When a circuit is open:
{
"schedulers": [
{
"name": "sonarr_1_queue",
"circuitState": "open",
"currentIntervalSeconds": 120,
"consecutiveErrors": 10,
"disabledAt": "2024-01-15T10:30:00.000Z",
"nextAttemptAt": "2024-01-15T10:35:00.000Z",
"nextRunAt": "2024-01-15T10:35:00.000Z"
}
]
}Varken exposes HTTP endpoints for monitoring on port 9090 (configurable via HEALTH_PORT):
| Endpoint | Description |
|---|---|
GET /health |
Overall status: healthy, degraded, unhealthy |
GET /health/plugins |
Per-plugin health status (inputs and outputs) |
GET /status |
Detailed status with scheduler information |
The Docker image includes a built-in HEALTHCHECK instruction using these endpoints.
| Status | HTTP Code |
|---|---|
healthy |
200 |
degraded |
200 |
unhealthy |
503 |
| Status | Condition |
|---|---|
healthy |
All outputs healthy + all inputs healthy + all schedulers in closed state with < 3 errors |
degraded |
At least one output healthy + at least one scheduler not in open state |
unhealthy |
No outputs configured, all outputs unreachable, or all schedulers in open state |
- Go to Configuration > Data Sources > Add data source
- Select InfluxDB
- Configure:
- Query Language: Flux (for InfluxDB 2.x) or InfluxQL (for 1.x)
- URL:
http://influxdb:8086 - Organization:
varken(InfluxDB 2.x only) - Token: Your InfluxDB token (InfluxDB 2.x only)
- Default Bucket:
varken
- Go to Dashboards > Import
- Upload
assets/grafana-dashboard.jsonfrom this repository - Select your InfluxDB data source
- Click Import
Or find community dashboards on Grafana.com.
If you're upgrading from the legacy Python version of Varken:
- Keep your old
varken.iniin the config folder - Start Varken — it will automatically detect and migrate your configuration
- Review the generated
varken.yamland make any necessary adjustments - Remove
varken.inionce you've verified everything works
Legacy VRKN_* environment variables are also automatically migrated.
Varken can't connect to services:
- Verify URLs are accessible from the Varken container
- Check API keys are correct
- Input plugin URLs must include the protocol (
http://orhttps://), e.g.url: "https://sonarr.example.com" - Ensure
verifySsl: falseif using self-signed certificates
No data in Grafana:
- Check Varken logs:
docker logs varken - Verify InfluxDB connection settings
- Ensure at least one input is enabled with
enabled: true
GeoIP not working:
- Ensure
geoip.enabled: trueis set in your Tautulli configuration - Verify Tautulli is accessible and the API key is correct
- Check Varken logs for GeoIP lookup errors
# Docker
docker logs -f varken
# Manual installation
tail -f logs/combined.logSet LOG_LEVEL environment variable:
error— Errors onlywarn— Warnings and errorsinfo— General information (default)debug— Detailed debugging information
git clone https://github.com/navino16/Varken.git
cd Varken
npm install
npm run dev # Dev server with auto-reload
npm test -- --run # Run tests
npm run lint # Lint code
npm run build # Build for productionsrc/
├── core/ # Orchestrator, PluginManager, Logger
├── config/ # Configuration loading and validation
├── plugins/
│ ├── inputs/ # Data source plugins (Sonarr, Radarr, etc.)
│ └── outputs/ # Database plugins (InfluxDB, etc.)
├── types/ # TypeScript type definitions
└── utils/ # Utilities (HTTP, hashing)
- Create type definitions in
src/types/inputs/ - Add Zod schema in
src/config/schemas/config.schema.ts - Create plugin in
src/plugins/inputs/ - Register in
src/plugins/inputs/index.ts - Add tests in
tests/plugins/inputs/
- Fork the repository and create a feature branch
- Write tests for new functionality
- Ensure all tests pass:
npm test -- --run - Ensure code passes linting:
npm run lint - Update documentation if needed
- Submit a pull request to the
developbranch
- GitHub Issues: Bug reports and feature requests
- Discord: Join the community

