Teamarr ships as a single Docker container. The only runtime dependencies are a data volume and, optionally, a running Dispatcharr instance.
Quick start
services:
teamarr:
image: ghcr.io/pharaoh-labs/teamarr:latest
container_name: teamarr
restart: unless-stopped
ports:
- 9195:9195
volumes:
- ./data:/app/data
environment:
- TZ=America/New_York
After the container starts, the UI is available at http://localhost:9195.
Environment variables
General
| Variable | Type | Default | Description |
|---|
TZ | string | UTC | Timezone for date/time display in the UI. The EPG output timezone is set separately in Settings. |
LOG_LEVEL | string | INFO | Console log level: DEBUG, INFO, WARNING, or ERROR. File logs always capture DEBUG regardless of this setting. |
LOG_FORMAT | string | text | Log output format: text or json. Use json for log aggregation systems such as ELK, Loki, or Splunk. |
LOG_DIR | string | auto | Override log directory path. See Log directory detection. |
SKIP_CACHE_REFRESH | bool | false | Skip the team/league cache refresh on startup. Set to true, yes, or 1. Useful for faster restarts during development. |
ESPN API tuning
These settings control Teamarr’s connection to ESPN’s API. Most users do not need to change them. If you experience timeouts or connection failures during cache refresh or EPG generation, you may be hitting DNS throttling from PiHole, AdGuard, or router-level DNS filtering.
| Variable | Type | Default | Description |
|---|
ESPN_MAX_WORKERS | int | 100 | Maximum parallel workers for fetching team and event data. |
ESPN_MAX_CONNECTIONS | int | 100 | HTTP connection pool size. |
ESPN_TIMEOUT | int | 10 | Request timeout in seconds. |
ESPN_RETRY_COUNT | int | 3 | Number of retry attempts on failure. |
ESPN’s API has generous rate limits that are practically impossible to hit. Connection issues are almost always caused by local DNS or network constraints, not ESPN throttling.
Recommended settings for DNS-throttled environments (PiHole / AdGuard):
environment:
- ESPN_MAX_WORKERS=20
- ESPN_MAX_CONNECTIONS=20
- ESPN_TIMEOUT=15
MLB Stats API tuning
| Variable | Type | Default | Description |
|---|
MLBSTATS_MAX_CONNECTIONS | int | 20 | HTTP connection pool size. |
MLBSTATS_TIMEOUT | int | 15 | Request timeout in seconds. |
MLBSTATS_RETRY_COUNT | int | 3 | Number of retry attempts on failure. |
Volume mounts
All persistent data lives under /app/data inside the container. Mount a single host directory here:
volumes:
- ./data:/app/data
| Path inside container | Contents |
|---|
/app/data/teamarr.db | Database — all configuration, teams, templates, and history |
/app/data/logs/ | Auto-rotating log files |
/app/data/epg/ | Generated XMLTV output |
Never delete teamarr.db. It contains all your configuration. Schema upgrades are handled automatically via migrations on startup — deleting the file will cause data loss.
Port mapping
Teamarr listens on port 9195 inside the container.
ports:
- 9195:9195 # host:container
This matches the V1 port for drop-in compatibility. The Dispatcharr EPG source URL is:
http://<teamarr-host>:9195/api/v1/epg/xmltv
Docker Compose — full example
services:
teamarr:
image: ghcr.io/pharaoh-labs/teamarr:latest
container_name: teamarr
restart: unless-stopped
ports:
- 9195:9195
volumes:
- ./data:/app/data
environment:
# Required: set your local timezone
- TZ=America/Chicago
# Console log level (default: INFO)
# File logs always capture DEBUG regardless of this setting
# - LOG_LEVEL=INFO
# Log format: "text" or "json" (default: text)
# Use "json" for ELK, Loki, Splunk
# - LOG_FORMAT=text
# Log directory override (default: /app/data/logs in Docker)
# - LOG_DIR=/app/data/logs
# Skip cache refresh on startup for faster restarts
# - SKIP_CACHE_REFRESH=false
# ESPN API tuning — reduce if you have DNS throttling (PiHole, AdGuard)
# - ESPN_MAX_WORKERS=100
# - ESPN_MAX_CONNECTIONS=100
# - ESPN_TIMEOUT=10
# - ESPN_RETRY_COUNT=3
# MLB Stats API tuning
# - MLBSTATS_MAX_CONNECTIONS=20
# - MLBSTATS_TIMEOUT=15
# - MLBSTATS_RETRY_COUNT=3
Unraid template
For Unraid users, a Community Applications template is available. Search for Teamarr in the Apps tab. The template pre-fills the port (9195) and maps a host path for /app/data.
Key fields to configure:
| Field | Value |
|---|
| Repository | ghcr.io/pharaoh-labs/teamarr:latest |
| Container Port | 9195 |
| Host Port | 9195 |
| Data volume | /mnt/user/appdata/teamarr:/app/data |
| TZ | Your local timezone (e.g., America/Chicago) |
Logging
Teamarr writes to two rotating log files under the log directory:
| File | Contents | Rotation |
|---|
teamarr.log | All log messages (DEBUG and above) | 10 MB × 5 files |
teamarr_errors.log | Errors only | 10 MB × 3 files |
The console log level is controlled by LOG_LEVEL (default: INFO). File logs always capture DEBUG regardless of the console setting.
Log directory detection
The log directory is resolved in this priority order:
LOG_DIR environment variable (if set)
/app/data/logs (if /app/data exists — the Docker default)
<project_root>/logs (local development fallback)
Viewing logs
# Docker container stdout
docker logs --tail 100 teamarr
# Log file from inside the container
docker exec teamarr tail -n 100 /app/data/logs/teamarr.log
# Log file from the data volume on the host
tail -n 100 ./data/logs/teamarr.log
Health check
The health check endpoint is at GET /health (no /api/v1 prefix). The Docker image includes a built-in HEALTHCHECK:
Healthcheck interval: 30s
Timeout: 10s
Start period: 60s (allows time for startup cache refresh)
Retries: 3
A healthy response:
{
"status": "healthy",
"version": "2.3.1",
"startup": {
"phase": "READY",
"is_ready": true
}
}
During startup, status is "starting" and is_ready is false.
Images are published to the GitHub Container Registry at ghcr.io/pharaoh-labs/teamarr.
| Tag | Description |
|---|
latest | Latest stable release from the main branch |
dev | Latest development build from the dev branch |
vX.Y.Z | Specific release version |
Pin to a specific version tag in production to avoid unexpected changes on container restart.