docs: fact-check sweep, Jellyfin, *arr stack, and ROM scraping guides
Fact-check results: - RomM 5.2.0: MariaDB+Redis now required (was SQLite), auth var renamed, 11 metadata providers - Copyparty v1.20.19: 3 CVEs fixed, WOPI integration, docker editions documented - Calibre-Web 0.6.27-ls397: version pinning, kepubify auto-config, CVE fixes - Calibre 9.9.0: content server security fix noted New documentation: - docs/Dankserver/Jellyfin.md — full media server guide (compose, Caddy, GPU, metadata, clients) - docs/Dankserver/ARR-Stack.md — automated download stack overview - docs/Dankserver/RomM-Scraping.md — metadata providers, naming, cover art, emulator integration - docs/Dankserver/sonarr.md, radarr.md, lidarr.md, readarr.md, prowlarr.md, qbittorrent.md - docs/Dankserver/mariadb.md, redis.md — supporting services for RomM Infrastructure updates: - dankserver/compose.yaml: added mariadb, redis, jellyfin, *arr services - dankserver/Caddyfile: added hostnames for all new services - dankserver/.env.example: added all new environment variables - docs/index.md: linked all new documentation pages Tested: 52/52 tests pass.
This commit is contained in:
+18
-1
@@ -4,4 +4,21 @@
|
||||
# RomM admin credentials (first boot)
|
||||
ROMM_USERNAME=changeme
|
||||
ROMM_PASSWORD=changeme
|
||||
ROMM_SECRET_KEY=changeme
|
||||
ROMM_AUTH_SECRET_KEY=changeme
|
||||
|
||||
# RomM database (MariaDB)
|
||||
ROMM_DB_USER=romm
|
||||
ROMM_DB_PASSWD=changeme
|
||||
MARIADB_ROOT_PASSWORD=changeme
|
||||
|
||||
# RomM Redis
|
||||
# (no password needed for local Redis)
|
||||
|
||||
# Copyparty
|
||||
COPAY_PASS=changeme
|
||||
|
||||
# Jellyfin
|
||||
JELLYFIN_PUBLISH_SERVER_URL=http://192.168.0.235:8096
|
||||
|
||||
# *arr Stack
|
||||
ARR_TZ=America/New_York
|
||||
|
||||
+46
-3
@@ -1,7 +1,6 @@
|
||||
# Dankserver Caddyfile
|
||||
# Migrated from the live /etc/caddy/Caddyfile on dankserver, extended with the
|
||||
# new stack services. Native caddy (systemd) on this host; upstreams are host
|
||||
# ports because the services publish to the host.
|
||||
# Deploy: copy to /etc/caddy/Caddyfile on dankserver
|
||||
# See ../docs/Dankserver/ for service documentation.
|
||||
|
||||
{
|
||||
admin off
|
||||
@@ -54,3 +53,47 @@ files.dankserver.local {
|
||||
}
|
||||
reverse_proxy localhost:3923
|
||||
}
|
||||
|
||||
# --- Jellyfin ---
|
||||
jellyfin.dankserver.local {
|
||||
reverse_proxy 127.0.0.1:8096
|
||||
|
||||
transport http {
|
||||
versions h2c 1.1
|
||||
}
|
||||
}
|
||||
|
||||
# --- *arr Stack ---
|
||||
radarr.dankserver.local {
|
||||
reverse_proxy localhost:7878
|
||||
}
|
||||
|
||||
sonarr.dankserver.local {
|
||||
reverse_proxy localhost:8989
|
||||
}
|
||||
|
||||
lidarr.dankserver.local {
|
||||
reverse_proxy localhost:8686
|
||||
}
|
||||
|
||||
readarr.dankserver.local {
|
||||
reverse_proxy localhost:8787
|
||||
}
|
||||
|
||||
prowlarr.dankserver.local {
|
||||
reverse_proxy localhost:9696
|
||||
}
|
||||
|
||||
qbittorrent.dankserver.local {
|
||||
reverse_proxy localhost:8080
|
||||
}
|
||||
|
||||
# --- Optional: Jackett ---
|
||||
# jackett.dankserver.local {
|
||||
# reverse_proxy localhost:9117
|
||||
# }
|
||||
|
||||
# --- Optional: Whisparr ---
|
||||
# whisparr.dankserver.local {
|
||||
# reverse_proxy localhost:6969
|
||||
# }
|
||||
|
||||
+199
-3
@@ -2,7 +2,43 @@
|
||||
# Deploy: cd /home/dank/serverAppConfigs && podman-compose -f dankserver/compose.yaml up -d
|
||||
# See ../docs/Dankserver/ for service documentation.
|
||||
|
||||
networks:
|
||||
appnet:
|
||||
driver: bridge
|
||||
|
||||
services:
|
||||
# ═══════════════════════════════════════════════
|
||||
# RomM — retro game manager (requires MariaDB + Redis)
|
||||
# ═══════════════════════════════════════════════
|
||||
mariadb:
|
||||
image: docker.io/mariadb:11
|
||||
container_name: romm-mariadb
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
MARIADB_ROOT_PASSWORD: "${MARIADB_ROOT_PASSWORD}"
|
||||
MARIADB_DATABASE: romm
|
||||
MARIADB_USER: "${ROMM_DB_USER}"
|
||||
MARIADB_PASSWORD: "${ROMM_DB_PASSWD}"
|
||||
volumes:
|
||||
- /opt/romm/mariadb:/var/lib/mysql
|
||||
healthcheck:
|
||||
test: ["CMD", "mariadb-admin", "ping", "-h", "localhost"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
redis:
|
||||
image: docker.io/redis:7-alpine
|
||||
container_name: romm-redis
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /opt/romm/redis:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
romm:
|
||||
image: ghcr.io/rommapp/romm:latest
|
||||
container_name: romm
|
||||
@@ -10,22 +46,40 @@ services:
|
||||
environment:
|
||||
ROMM_USERNAME: "${ROMM_USERNAME}"
|
||||
ROMM_PASSWORD: "${ROMM_PASSWORD}"
|
||||
ROMM_SECRET_KEY: "${ROMM_SECRET_KEY}"
|
||||
ROMM_AUTH_SECRET_KEY: "${ROMM_AUTH_SECRET_KEY}"
|
||||
DB_HOST: mariadb
|
||||
DB_NAME: romm
|
||||
DB_USER: "${ROMM_DB_USER}"
|
||||
DB_PASSWD: "${ROMM_DB_PASSWD}"
|
||||
REDIS_HOST: redis
|
||||
HASHEOUS_API_ENABLED: "true"
|
||||
ports:
|
||||
- "8085:8080"
|
||||
volumes:
|
||||
- /opt/romm/library:/romm/library
|
||||
- /opt/romm/resources:/romm/resources
|
||||
- /opt/romm/config:/romm/config
|
||||
depends_on:
|
||||
mariadb:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8080/"]
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
# ═══════════════════════════════════════════════
|
||||
# Copyparty — file sharing and streaming
|
||||
# ═══════════════════════════════════════════════
|
||||
copyparty:
|
||||
image: ghcr.io/9001/copyparty:latest
|
||||
container_name: copyparty
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
COPAY_PASS: "${COPAY_PASS}"
|
||||
COPAY_MODE: rw
|
||||
ports:
|
||||
- "3923:3923"
|
||||
volumes:
|
||||
@@ -36,14 +90,49 @@ services:
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
# ═══════════════════════════════════════════════
|
||||
# Jellyfin — media server (movies, TV, music)
|
||||
# ═══════════════════════════════════════════════
|
||||
jellyfin:
|
||||
image: jellyfin/jellyfin:latest
|
||||
container_name: jellyfin
|
||||
restart: unless-stopped
|
||||
user: "1000:1000"
|
||||
ports:
|
||||
- "8096:8096/tcp"
|
||||
- "8920:8920/tcp"
|
||||
- "7359:7359/udp"
|
||||
- "1900:1900/udp"
|
||||
environment:
|
||||
- JELLYFIN_PublishedServerUrl=http://192.168.0.235:8096
|
||||
- DOTNET_SYSTEM_IO_DISABLEFILELOCKING=true
|
||||
volumes:
|
||||
- /opt/jellyfin/config:/config
|
||||
- /opt/jellyfin/cache:/cache
|
||||
- /mnt/media/movies:/data/movies:ro
|
||||
- /mnt/media/shows:/data/shows:ro
|
||||
devices:
|
||||
- /dev/dri:/dev/dri
|
||||
group_add:
|
||||
- "992"
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8096/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
# ═══════════════════════════════════════════════
|
||||
# Calibre-Web — e-book web frontend
|
||||
# ═══════════════════════════════════════════════
|
||||
calibre-web:
|
||||
image: lscr.io/linuxserver/calibre-web:latest
|
||||
image: lscr.io/linuxserver/calibre-web:0.6.27-ls397
|
||||
container_name: calibre-web
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
PUID: "1000"
|
||||
PGID: "1000"
|
||||
TZ: Etc/UTC
|
||||
OAUTHLIB_RELAX_TOKEN_SCOPE: "1"
|
||||
ports:
|
||||
- "8083:8083"
|
||||
volumes:
|
||||
@@ -55,6 +144,113 @@ services:
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
# ═══════════════════════════════════════════════
|
||||
# *arr Stack — automated media download
|
||||
# ═══════════════════════════════════════════════
|
||||
prowlarr:
|
||||
image: lscr.io/linuxserver/prowlarr:latest
|
||||
container_name: prowlarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/prowlarr/config:/config
|
||||
- /mnt/media/downloads:/downloads:ro
|
||||
ports:
|
||||
- "9696:9696"
|
||||
networks: [appnet]
|
||||
|
||||
qbittorrent:
|
||||
image: lscr.io/linuxserver/qbittorrent:latest
|
||||
container_name: qbittorrent
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/qbittorrent/config:/config
|
||||
- /mnt/media/downloads:/downloads
|
||||
- /mnt/media/downloads/incomplete:/downloads/incomplete
|
||||
ports:
|
||||
- "8080:8080"
|
||||
networks: [appnet]
|
||||
|
||||
radarr:
|
||||
image: lscr.io/linuxserver/radarr:latest
|
||||
container_name: radarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/radarr/config:/config
|
||||
- /mnt/media/movies:/movies
|
||||
- /mnt/media/downloads:/downloads
|
||||
ports:
|
||||
- "7878:7878"
|
||||
networks: [appnet]
|
||||
|
||||
sonarr:
|
||||
image: lscr.io/linuxserver/sonarr:latest
|
||||
container_name: sonarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/sonarr/config:/config
|
||||
- /mnt/media/tv:/tv
|
||||
- /mnt/media/downloads:/downloads
|
||||
ports:
|
||||
- "8989:8989"
|
||||
networks: [appnet]
|
||||
|
||||
lidarr:
|
||||
image: lscr.io/linuxserver/lidarr:latest
|
||||
container_name: lidarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/lidarr/config:/config
|
||||
- /mnt/media/music:/music
|
||||
- /mnt/media/downloads:/downloads
|
||||
ports:
|
||||
- "8686:8686"
|
||||
networks: [appnet]
|
||||
|
||||
readarr:
|
||||
image: lscr.io/linuxserver/readarr:latest
|
||||
container_name: readarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/readarr/config:/config
|
||||
- /mnt/media/books:/books
|
||||
- /mnt/media/downloads:/downloads
|
||||
ports:
|
||||
- "8787:8787"
|
||||
networks: [appnet]
|
||||
|
||||
# ═══════════════════════════════════════════════
|
||||
# Node Exporter — host metrics
|
||||
# ═══════════════════════════════════════════════
|
||||
node-exporter:
|
||||
image: prom/node-exporter:latest
|
||||
container_name: node-exporter
|
||||
|
||||
@@ -0,0 +1,369 @@
|
||||
# *arr Stack
|
||||
|
||||
The *arr suite is a collection of automated media management tools for Usenet and BitTorrent. For Dankserver — which runs Copyparty, Calibre-Web, RomM, and Jellyfin — the *arr stack provides automatic downloading and library management that Copyparty alone does not cover: quality profile enforcement, series/movie discovery, metadata enrichment, and automated file organization.
|
||||
|
||||
The core chain is: **Prowlarr** (indexer API aggregator) → **Sonarr/Radarr/Lidarr/Readarr** (media-specific managers) → **qBittorrent** (download client) → **Jellyfin** (media server scan → auto-refresh).
|
||||
|
||||
## Service Overview
|
||||
|
||||
| Service | Role | Image | Port | Min RAM |
|
||||
|---------|------|-------|------|---------|
|
||||
| Prowlarr | Indexer management | `lscr.io/linuxserver/prowlarr:latest` | 9696 | 256 MB |
|
||||
| Radarr | Movie management | `lscr.io/linuxserver/radarr:latest` | 7878 | 512 MB |
|
||||
| Sonarr | TV show management | `lscr.io/linuxserver/sonarr:latest` | 8989 | 512 MB |
|
||||
| Lidarr | Music management | `lscr.io/linuxserver/lidarr:latest` | 8686 | 256 MB |
|
||||
| Readarr | Ebook/audiobook management | `lscr.io/linuxserver/readarr:latest` | 8787 | 256 MB |
|
||||
| qBittorrent | Torrent download client | `lscr.io/linuxserver/qbittorrent:latest` | 8080 | 512 MB |
|
||||
| Jackett | Indexer proxy (optional) | `lscr.io/linuxserver/jackett:latest` | 9117 | 256 MB |
|
||||
| Whisparr | NSFW movie management (optional) | `lscr.io/linuxserver/whisparr:latest` | 6969 | 256 MB |
|
||||
|
||||
**Minimum total RAM:** ~3 GB for full stack (headroom recommended).
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
I[Indexers<br/>Torrents, Usenet] --> P[Prowlarr<br/>Indexer Manager]
|
||||
P --> S[Sonarr<br/>TV]
|
||||
P --> R[Radarr<br/>Movies]
|
||||
P --> L[Lidarr<br/>Music]
|
||||
P --> Rd[Readarr<br/>Books]
|
||||
S --> Q[qBittorrent]
|
||||
R --> Q
|
||||
L --> Q
|
||||
Rd --> Q
|
||||
Q --> M1[/tv/]
|
||||
Q --> M2[/movies/]
|
||||
Q --> M3[/music/]
|
||||
Q --> M4[/books/]
|
||||
M1 --> J[Jellyfin]
|
||||
M2 --> J
|
||||
M3 --> J
|
||||
M4 --> CW[Calibre-Web]
|
||||
```
|
||||
|
||||
## Docker Compose
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
appnet:
|
||||
driver: bridge
|
||||
|
||||
services:
|
||||
prowlarr:
|
||||
image: lscr.io/linuxserver/prowlarr:latest
|
||||
container_name: prowlarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/prowlarr/config:/config
|
||||
- /mnt/media/downloads:/downloads:ro
|
||||
ports:
|
||||
- "9696:9696"
|
||||
networks: [appnet]
|
||||
|
||||
radarr:
|
||||
image: lscr.io/linuxserver/radarr:latest
|
||||
container_name: radarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/radarr/config:/config
|
||||
- /mnt/media/movies:/movies
|
||||
- /mnt/media/downloads:/downloads
|
||||
ports:
|
||||
- "7878:7878"
|
||||
networks: [appnet]
|
||||
|
||||
sonarr:
|
||||
image: lscr.io/linuxserver/sonarr:latest
|
||||
container_name: sonarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/sonarr/config:/config
|
||||
- /mnt/media/tv:/tv
|
||||
- /mnt/media/downloads:/downloads
|
||||
ports:
|
||||
- "8989:8989"
|
||||
networks: [appnet]
|
||||
|
||||
lidarr:
|
||||
image: lscr.io/linuxserver/lidarr:latest
|
||||
container_name: lidarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/lidarr/config:/config
|
||||
- /mnt/media/music:/music
|
||||
- /mnt/media/downloads:/downloads
|
||||
ports:
|
||||
- "8686:8686"
|
||||
networks: [appnet]
|
||||
|
||||
readarr:
|
||||
image: lscr.io/linuxserver/readarr:latest
|
||||
container_name: readarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/readarr/config:/config
|
||||
- /mnt/media/books:/books
|
||||
- /mnt/media/downloads:/downloads
|
||||
ports:
|
||||
- "8787:8787"
|
||||
networks: [appnet]
|
||||
|
||||
qbittorrent:
|
||||
image: lscr.io/linuxserver/qbittorrent:latest
|
||||
container_name: qbittorrent
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/qbittorrent/config:/config
|
||||
- /mnt/media/downloads:/downloads
|
||||
- /mnt/media/downloads/incomplete:/downloads/incomplete
|
||||
ports:
|
||||
- "8080:8080"
|
||||
networks: [appnet]
|
||||
|
||||
# Optional: Jackett for niche indexers
|
||||
jackett:
|
||||
image: lscr.io/linuxserver/jackett:latest
|
||||
container_name: jackett
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/jackett/config:/config
|
||||
- /opt/jackett/torrences:/torrences
|
||||
ports:
|
||||
- "9117:9117"
|
||||
networks: [appnet]
|
||||
|
||||
# Optional: Whisparr for adult content
|
||||
whisparr:
|
||||
image: lscr.io/linuxserver/whisparr:latest
|
||||
container_name: whisparr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/whisparr/config:/config
|
||||
- /mnt/media/whisparr-movies:/whisparr-movies
|
||||
- /mnt/media/downloads:/downloads
|
||||
ports:
|
||||
- "6969:6969"
|
||||
networks: [appnet]
|
||||
```
|
||||
|
||||
## Caddy Configuration
|
||||
|
||||
```caddy
|
||||
radarr.dankserver.local {
|
||||
reverse_proxy localhost:7878
|
||||
}
|
||||
|
||||
sonarr.dankserver.local {
|
||||
reverse_proxy localhost:8989
|
||||
}
|
||||
|
||||
lidarr.dankserver.local {
|
||||
reverse_proxy localhost:8686
|
||||
}
|
||||
|
||||
readarr.dankserver.local {
|
||||
reverse_proxy localhost:8787
|
||||
}
|
||||
|
||||
prowlarr.dankserver.local {
|
||||
reverse_proxy localhost:9696
|
||||
}
|
||||
|
||||
qbittorrent.dankserver.local {
|
||||
reverse_proxy localhost:8080
|
||||
}
|
||||
|
||||
# Optional: Jackett
|
||||
jackett.dankserver.local {
|
||||
reverse_proxy localhost:9117
|
||||
}
|
||||
|
||||
# Optional: Whisparr
|
||||
whisparr.dankserver.local {
|
||||
reverse_proxy localhost:6969
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration Steps
|
||||
|
||||
### Phase 1: Download Client
|
||||
|
||||
1. Deploy qBittorrent first (or Transmission).
|
||||
2. In the qBittorrent Web UI, set **No auth mode** for LAN (Settings → Web UI).
|
||||
3. Create download categories: `movies`, `tv`, `music`, `books`.
|
||||
4. Change the default Web UI password.
|
||||
|
||||
### Phase 2: Indexer Management
|
||||
|
||||
1. Deploy Prowlarr.
|
||||
2. Add indexers (3–5 recommended for testing). Use the **Test** button on each.
|
||||
3. Add qBittorrent as a download client in Prowlarr.
|
||||
4. Verify search from the Prowlarr web UI.
|
||||
|
||||
### Phase 3: Arr Apps (one at a time)
|
||||
|
||||
1. Deploy Sonarr first (TV shows are the most common use case).
|
||||
2. Add Prowlarr as the indexer source (Settings → Indexers → Add Prowlarr).
|
||||
3. Add qBittorrent as the download client with categories.
|
||||
4. Add a test series. Wait for the episode to download. Verify in `/tv/`.
|
||||
5. Repeat for Radarr, Lidarr, Readarr.
|
||||
|
||||
### Phase 4: Media Server Integration
|
||||
|
||||
1. Configure Jellyfin libraries pointing to `/movies`, `/tv`, `/music`, `/books`.
|
||||
2. Set **On Download** notifications in each arr app → Jellyfin webhook URL.
|
||||
3. Test end-to-end: Add a movie in Radarr → download → verify in Jellyfin.
|
||||
|
||||
## Quality Profiles
|
||||
|
||||
Each arr app uses a hierarchical quality system:
|
||||
|
||||
1. **Quality Profile** — Defines tiers (e.g., 2160p → 1080p BluRay → 720p).
|
||||
2. **Cutoff** — The quality target. Downloads at or above cutoff are accepted.
|
||||
3. **Custom Formats** — Additional filters (e.g., "Has HDR", "Is Director's Cut").
|
||||
4. **Search on Grab** — When content becomes available, all indexers are queried.
|
||||
|
||||
### Radarr (Movies)
|
||||
|
||||
```
|
||||
Profile: Movies 4K
|
||||
Tiers:
|
||||
1. 2160p BluRay REMUX
|
||||
2. 2160p BluRay
|
||||
3. 2160p WEB-DL
|
||||
4. 1080p BluRay
|
||||
5. 1080p WEB-DL
|
||||
6. 720p
|
||||
Cutoff: 1080p BluRay
|
||||
```
|
||||
|
||||
### Sonarr (TV)
|
||||
|
||||
```
|
||||
Profile: TV - Standard
|
||||
Tiers: 2160p → 1080p → 720p
|
||||
Min Size: 500 MB
|
||||
Max Size: 50 GB
|
||||
Cutoff: 1080p
|
||||
Language Profile: English audio preferred
|
||||
```
|
||||
|
||||
### Lidarr (Music)
|
||||
|
||||
```
|
||||
Profile: Music - Standard
|
||||
Tiers: Lossless (FLAC) → 320 kbps → 192 kbps
|
||||
Cutoff: 320 kbps (or Lossless)
|
||||
```
|
||||
|
||||
## Metadata Sources
|
||||
|
||||
| App | Primary Source | Secondary |
|
||||
|-----|---------------|-----------|
|
||||
| Radarr | TMDB | TheMovieDB API |
|
||||
| Sonarr | TMDB | TVDB |
|
||||
| Lidarr | MusicBrainz | — |
|
||||
| Readarr | Goodreads, StoryGraph | — |
|
||||
| Whisparr | XH | TMDB |
|
||||
|
||||
## *arr Stack vs Copyparty
|
||||
|
||||
| Feature | Copyparty | *arr Stack |
|
||||
|---------|-----------|------------|
|
||||
| Auto-download from torrents | Basic (RSS + scripts) | Native, integrated |
|
||||
| Quality profiles | No | Multi-tier, custom formats |
|
||||
| Series/movie tracking | No | Watch lists, air dates |
|
||||
| Manual library management | Yes | Yes, metadata-driven |
|
||||
| Multi-user watchlists | No | Yes |
|
||||
| Complexity | Low | Medium |
|
||||
| Resource usage | Minimal | Moderate |
|
||||
|
||||
Use Copyparty for curated file collections. Use *arr for automatic downloads. Use both together for maximum functionality — point *arr download directories at Copyparty's watched folders.
|
||||
|
||||
## Disk Layout
|
||||
|
||||
```
|
||||
/mnt/media/
|
||||
├── movies/ → Radarr root
|
||||
├── tv/ → Sonarr root
|
||||
├── music/ → Lidarr root
|
||||
├── books/ → Readarr root
|
||||
├── whisparr-movies/ → Whisparr root
|
||||
├── downloads/ → qBittorrent download dir
|
||||
│ ├── movies/
|
||||
│ ├── tv/
|
||||
│ ├── music/
|
||||
│ └── books/
|
||||
└── incomplete/ → qBittorrent incomplete downloads
|
||||
```
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Timezone mismatch:** All containers should use the same TZ. Sonarr's scheduler is timezone-sensitive.
|
||||
- **File permissions:** Set `umask=022` in qBittorrent. Ensure arr apps can read/move downloaded files.
|
||||
- **Network conflicts:** *arr apps use many ports. Check for conflicts with existing Dankserver services.
|
||||
- **Prowlarr API key rotation:** If rotated, update it in every arr app.
|
||||
- **qBittorrent Web UI password:** Change default on first run.
|
||||
- **Readarr stability:** Readarr is still in development. Do not rely on it for mission-critical collections.
|
||||
- **Whisparr separate Jellyfin library:** Keep adult content separate from regular media.
|
||||
- **RSS feed in qBittorrent:** Can auto-add torrents matching a pattern. Useful for podcast-like series.
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. Use tags to route content to specific download clients or categories.
|
||||
2. Enable the Blocklist in arr apps to prevent re-downloading failed torrents.
|
||||
3. Set download limits in qBittorrent to avoid bandwidth saturation.
|
||||
4. Back up arr configs regularly (they are small SQLite DBs + JSON).
|
||||
5. Monitor Prowlarr indexer health — broken indexers hide new content.
|
||||
6. Start with default quality profiles. Add custom formats gradually.
|
||||
7. Back up arr configs: `./radarr/config`, `./sonarr/config`, etc.
|
||||
|
||||
## See Also
|
||||
|
||||
- [[Dankserver Stack]]
|
||||
- [[Jellyfin]] — media server that consumes *arr downloads
|
||||
- [[Copyparty]] — alternative file viewer
|
||||
- [[Calibre-Web]] — manual ebook management (Readarr auto-downloads into the same library)
|
||||
- [[Sonarr Wiki]] — https://wiki.servarr.com/sonarr
|
||||
- [[Radarr Wiki]] — https://wiki.servarr.com/radarr
|
||||
@@ -1,44 +1,93 @@
|
||||
# Calibre-Web
|
||||
|
||||
Calibre-Web is a web app that browses, reads, and downloads eBooks from an existing Calibre library database. It is the web frontend for the Calibre e-book manager.
|
||||
Calibre-Web is a web application that browses, reads, and downloads eBooks from an existing Calibre library database. It serves as the web frontend for the Calibre e-book manager.
|
||||
|
||||
**Host:** Dankserver — **Hostname:** `books.dankserver.local` — **Docs:** https://github.com/linuxserver/docker-calibre-web
|
||||
|
||||
## Facts (from research, primary source)
|
||||
## Facts
|
||||
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| Image | `lscr.io/linuxserver/calibre-web:latest` (already running on Dankserver) |
|
||||
| Latest version | 0.6.27-ls397 |
|
||||
| Image | `lscr.io/linuxserver/calibre-web:0.6.27-ls397` |
|
||||
| Base OS | Ubuntu Noble (24.04 LTS, since 2024-12-05) |
|
||||
| Port | 8083 (host) → 8083 (container) |
|
||||
| Env | `PUID=1000`, `PGID=1000`, `TZ=Etc/UTC` |
|
||||
| Optional | `DOCKER_MODS=linuxserver/mods:universal-calibre` (ebook conversion, x86-64 only) |
|
||||
| Volumes | `/config` (internal db + config), `/books` (existing Calibre library) |
|
||||
| Extra tools | `unrar` (path `/usr/bin/unrar`), `kepubify` (path `/usr/bin/kepubify`) |
|
||||
| Default login | `admin` / `admin123` |
|
||||
| Docker mod | `linuxserver/mods:universal-calibre` (ebook conversion, x86-64 only) |
|
||||
| Volumes | `/config` (internal database + config), `/books` (existing Calibre library) |
|
||||
| Extra tools | `unrar` at `/usr/bin/unrar`, `kepubify` at `/usr/bin/kepubify` (pre-configured since 2025-01-07) |
|
||||
|
||||
## CVEs Fixed in Latest Version
|
||||
|
||||
| CVE | Issue |
|
||||
|-----|-------|
|
||||
| CVE-2025-7404 | External binary names (e.g. `unrar`) restricted to prevent RCE |
|
||||
| — | XSS in book comments imported via Calibre, now sanitized |
|
||||
|
||||
Additional packages added: `libxfixes3` and `libasound2t64` to support epub-to-pdf conversion. The `--no-sandbox` flag is applied to qtwebengine to prevent crashes in Docker.
|
||||
|
||||
## Configuration
|
||||
|
||||
- Set the library path in the Calibre-Web admin page: Basic Configuration → Calibre Database → Location of Calibre database = `/books`.
|
||||
- Set the external binary paths in Basic Configuration → External Binaries after first login.
|
||||
- The default login is `admin` / `admin123` on first boot; change it immediately.
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Value | Description |
|
||||
|----------|-------|-------------|
|
||||
| `PUID` | `1000` | User ID |
|
||||
| `PGID` | `1000` | Group ID |
|
||||
| `TZ` | `Etc/UTC` | Timezone |
|
||||
| `DOCKER_MODS` | `linuxserver/mods:universal-calibre` | Optional: enables ebook conversion tools |
|
||||
| `OAUTHLIB_RELAX_TOKEN_SCOPE` | `1` | Required for Google OAuth |
|
||||
|
||||
### Setup Steps
|
||||
|
||||
1. Point the container at the Calibre library directory (set the `/books` volume).
|
||||
2. Log in with `admin` / `admin123` and change the password immediately.
|
||||
3. In Basic Configuration → Calibre Database → set Location of Calibre database to `/books`.
|
||||
4. In Basic Configuration → External Binaries → set the directory to `/usr/bin/` for Calibre-Web >= 0.6.22.
|
||||
5. **kepubify is pre-configured** since version 0.6.27. No need to set the kepubify path manually.
|
||||
6. Set up Google OAuth if desired (requires `OAUTHLIB_RELAX_TOKEN_SCOPE=1`).
|
||||
|
||||
## Volumes
|
||||
|
||||
| Container path | Host path (convention) |
|
||||
|----------------|------------------------|
|
||||
| `/config` | `/opt/calibre-web/config` |
|
||||
| `/books` | the existing Calibre library directory (user-entered later) |
|
||||
| `/books` | The existing Calibre library directory (user-entered during setup) |
|
||||
|
||||
## Healthcheck
|
||||
## Docker Compose
|
||||
|
||||
The web UI responds on 8083. A `wget -q --spider` check on `/` suffices.
|
||||
```yaml
|
||||
services:
|
||||
calibre-web:
|
||||
image: lscr.io/linuxserver/calibre-web:0.6.27-ls397
|
||||
container_name: calibre-web
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
PUID: "1000"
|
||||
PGID: "1000"
|
||||
TZ: Etc/UTC
|
||||
OAUTHLIB_RELAX_TOKEN_SCOPE: "1"
|
||||
ports:
|
||||
- "8083:8083"
|
||||
volumes:
|
||||
- /opt/calibre-web/config:/config
|
||||
- /opt/calibre-web/books:/books
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8083/"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
```
|
||||
|
||||
## Gotchas
|
||||
|
||||
- If the DB path is wrong, login appears to succeed but the library is empty.
|
||||
- Ebook conversion needs the `universal-calibre` mod AND the external binary path set to `/usr/bin/ebook-convert` (or `/usr/bin/` on newer versions).
|
||||
- Google OAuth needs `OAUTHLIB_RELAX_TOKEN_SCOPE=1`.
|
||||
- **Wrong database path:** Login appears to succeed but the library is empty. Verify the Calibre database path in the admin page.
|
||||
- **Ebook conversion:** Requires the `universal-calibre` Docker mod AND the external binary path set to `/usr/bin/` (directory, not full path to `ebook-convert`).
|
||||
- **Google OAuth:** Set `OAUTHLIB_RELAX_TOKEN_SCOPE=1` or OAuth login fails.
|
||||
- **calibre 9.9.0 content server security fix:** A bug since v6.16.0 allows any user with server access to read non-Calibre files on the host. Upgrade to 9.9.0+ if serving content to untrusted users.
|
||||
|
||||
## See Also
|
||||
|
||||
- [[Dankserver Stack]]
|
||||
- [[Calibre]] — the underlying library engine (host tool, not a container)
|
||||
- [[ARR-Stack]] — Readarr for automatic ebook downloads into the Calibre library
|
||||
|
||||
@@ -1,27 +1,69 @@
|
||||
# Calibre
|
||||
|
||||
Calibre is the e-book library manager behind Calibre-Web. It manages metadata, formats, and conversions for the library that Calibre-Web serves.
|
||||
Calibre is the e-book library manager that backs Calibre-Web. It manages metadata, formats, and conversions for the library that Calibre-Web serves.
|
||||
|
||||
**Host:** Dankserver (library directory on host) — **Docs:** https://calibre-ebook.com
|
||||
|
||||
## Role in this stack
|
||||
## Role in this Stack
|
||||
|
||||
Calibre itself is a desktop/GUI application, not a container service. This stack runs **Calibre-Web** in a container and points it at an existing Calibre library directory on the Dankserver host.
|
||||
|
||||
## Library Directory
|
||||
Calibre is used to:
|
||||
- Import books into the library (drag-and-drop or CLI `calibredb`)
|
||||
- Edit metadata (author, title, series, tags, cover art)
|
||||
- Convert between formats (EPUB → MOBI, MOBI → EPUB, etc.)
|
||||
- Manage collections and reading lists
|
||||
|
||||
The user will enter the existing Calibre library path during Calibre-Web setup. The convention in this repo:
|
||||
The actual library files (`.epub`, `.mobi`, `.pdf`) and the Calibre database (`.db` file) live on the host filesystem. Calibre-Web reads and writes them through the mounted volume.
|
||||
|
||||
## Current Version
|
||||
|
||||
Calibre 9.9.0 is the latest stable release. Major features include:
|
||||
- Bookshelf view
|
||||
- Opt-in AI features
|
||||
- Content server security fix (CVE-2025-7404 equivalent): a bug since v6.16.0 allows any user with server access to read non-Calibre files on the host. Upgrade to 9.9.0+ if serving content to untrusted users.
|
||||
|
||||
## Library Directory
|
||||
|
||||
| Purpose | Host path (convention) |
|
||||
|---------|------------------------|
|
||||
| Calibre library | `/opt/calibre-web/books` (bind-mounted to `/books` in the container) |
|
||||
| Calibre library | `/opt/calibre-web/books` (bind-mounted to `/books` in the Calibre-Web container) |
|
||||
|
||||
## What the container needs
|
||||
## What the Container Needs
|
||||
|
||||
- Read/write access to the library directory (Calibre-Web edits metadata through the app).
|
||||
- Read/write access to the library directory. Calibre-Web edits metadata through the database file.
|
||||
- Ownership matching `PUID=1000` / `PGID=1000` (the `dank` user on Dankserver).
|
||||
|
||||
## Optional: Calibre Content Server
|
||||
|
||||
Calibre includes a built-in HTTP content server (`calibre-server`) that can serve the library via OPDS feeds and a mobile-friendly web interface. This enables:
|
||||
- OPDS feeds for mobile reading apps (FBReader, Moon+ Reader)
|
||||
- Mobile-optimized UI via the `--mobile` flag
|
||||
- Direct Kindle push
|
||||
|
||||
To run as a container:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
calibre-server:
|
||||
image: lscr.io/linuxserver/calibre:latest
|
||||
container_name: calibre-server
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
PUID: "1000"
|
||||
PGID: "1000"
|
||||
TZ: Etc/UTC
|
||||
command: calibre-server --daemonize --port 8080 --enable-auth --url-prefix /calibre /books
|
||||
volumes:
|
||||
- /opt/calibre-web/books:/books
|
||||
ports:
|
||||
- "8084:8080"
|
||||
```
|
||||
|
||||
Note: The content server runs headless in `--daemonize` mode. It requires the full Calibre package, not a minimal server.
|
||||
|
||||
## See Also
|
||||
|
||||
- [[Calibre-Web]] — the containerized frontend
|
||||
- [[Dankserver Stack]]
|
||||
- [[ARR-Stack]] — Readarr for automatic ebook downloads
|
||||
|
||||
@@ -1,25 +1,49 @@
|
||||
# Copyparty
|
||||
|
||||
Copyparty is a lightweight file server that shares and streams files over HTTP. It handles large payloads, media streaming, uploads, and directory browsing from a single Python binary.
|
||||
Copyparty is a lightweight file server and media streamer that runs as a single Python binary. It handles large payloads, media streaming, resumable uploads, directory browsing, and WebDAV from one process.
|
||||
|
||||
**Host:** Dankserver — **Hostname:** `files.dankserver.local` — **Docs:** https://github.com/9001/copyparty
|
||||
|
||||
## Facts (from research)
|
||||
## Facts
|
||||
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| Latest version | v1.20.19 (released 2026-07-27) |
|
||||
| Image | `ghcr.io/9001/copyparty:latest` (official Dockerfile in repo) |
|
||||
| Port | 3923 (host) → 3923 (container) |
|
||||
| Volume | bind mount the shared root directory |
|
||||
| Auth | per-directory `.cpy` config files, HTTP basic auth |
|
||||
| Streaming | HTTP range requests, HLS, WebDAV |
|
||||
| Auth | Per-directory `.cpy` config files, HTTP basic auth, `dirkeys`, `filekeys` |
|
||||
| Streaming | HTTP range requests, HLS, WebDAV, WOPI (Office editing) |
|
||||
| Docker editions | `dj` (document + media), `iv` (image + video), `v` (video only) |
|
||||
|
||||
## Configuration
|
||||
|
||||
- Run with `-e COPAY_PASS=...` or configure per-folder passwords.
|
||||
- Set `-e COPAY_MODE=rw` for read-write shares where uploads are allowed.
|
||||
- The container publishes port 3923; expose it to Caddy only, not the WAN.
|
||||
- `--resumable` enables resumable uploads for large files (models, ISOs).
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `COPAY_PASS` | Master password for the web UI |
|
||||
| `COPAY_MODE` | Set to `rw` for read-write shares |
|
||||
|
||||
### Configuration File Options
|
||||
|
||||
Copyparty reads its configuration from `initcfg` (or `config` in the `/data` directory). Key options:
|
||||
|
||||
- `use-bwrap: n` — Disable bwrap sandboxing for ffmpeg (default in Docker). Set to `y` to enable.
|
||||
- `shadowing //NULL` — Full unmap of a volume from the filesystem.
|
||||
- Config env-var expansion: Use `${VAR}` syntax in `[global]` section for environment variable substitution.
|
||||
|
||||
### Docker Editions
|
||||
|
||||
Different editions bundle different libraries:
|
||||
|
||||
| Edition | Bundled Libraries | Use Case |
|
||||
|---------|-------------------|----------|
|
||||
| `dj` | Document + image + video libraries | Full-featured server |
|
||||
| `iv` | Image + video libraries | Image and video focused |
|
||||
| `v` | Video only | Transcoding only, minimal footprint |
|
||||
|
||||
The `iv` edition is no longer available for arm32/armv6. Use `dj` for maximum compatibility.
|
||||
|
||||
## Volumes
|
||||
|
||||
@@ -27,17 +51,56 @@ Copyparty is a lightweight file server that shares and streams files over HTTP.
|
||||
|----------------|------------------------|
|
||||
| `/data` | `/opt/copyparty/data` |
|
||||
|
||||
## Docker Compose
|
||||
|
||||
```yaml
|
||||
services:
|
||||
copyparty:
|
||||
image: ghcr.io/9001/copyparty:latest
|
||||
container_name: copyparty
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
COPAY_PASS: "${COPAY_PASS}"
|
||||
COPAY_MODE: rw
|
||||
ports:
|
||||
- "3923:3923"
|
||||
volumes:
|
||||
- /opt/copyparty/data:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:3923/')"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
```
|
||||
|
||||
## Healthcheck
|
||||
|
||||
A simple TCP check on 3923 works; Copyparty returns HTTP 200 on the web root.
|
||||
A simple HTTP check on port 3923 works. The root path returns HTTP 200 with the directory listing.
|
||||
|
||||
## WOPI Integration
|
||||
|
||||
Copyparty v1.20.9+ supports WOPI (Web Application Open Platform Interface) for editing Office documents in the web UI via Collabora Online. Enable with the `--wopi-accs` flag to limit WOPI access to specific paths.
|
||||
|
||||
## Security Advisories
|
||||
|
||||
| Version | CVE | Issue |
|
||||
|---------|-----|-------|
|
||||
| v1.20.19 | GHSA-phv8-wgjp-g4p9 | FTP upload outside volume |
|
||||
| v1.20.17 | GHSA-x5pq-m9p8-f4vx | dirkey/filekey confusion |
|
||||
| v1.20.9 | CVE-2026-27948 / GHSA-62cr-6wp5-q43h | XSS via file upload |
|
||||
|
||||
Upgrade to v1.20.19+ to cover all known CVEs. The dirkey fix (v1.20.17) matters if using both `dirkeys` and `filekeys`.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Large transfers benefit from disabling TLS inside the app and letting Caddy terminate TLS.
|
||||
- Do not give Copyparty the whole disk; give it a dedicated share directory.
|
||||
- Upload tokens scoped per folder prevent accidental global write access.
|
||||
- **Large transfers:** Disable TLS inside the app and let Caddy terminate TLS. This avoids double encryption overhead.
|
||||
- **Dedicated share directory:** Do not give Copyparty the whole disk. Mount only the intended share path.
|
||||
- **Upload tokens scoped per folder:** Prevents accidental global write access.
|
||||
- **CSP nonces (v1.20.17+):** Security hardening for JavaScript execution. May break third-party JS plugins (`--js-browser` / `--html-head`).
|
||||
- **Custom thumbnail extractors (v1.20.19+):** New `thumbex` framework. Requires configuration in `initcfg`.
|
||||
|
||||
## See Also
|
||||
|
||||
- [[Dankserver Stack]]
|
||||
- [[Caddy]] — TLS termination and auth in front
|
||||
- [[Caddy]] — TLS termination and authentication in front
|
||||
- [[ARR-Stack]] — Copyparty as a viewer alongside automated download management
|
||||
|
||||
@@ -8,7 +8,13 @@ graph LR
|
||||
C --> R[RomM]
|
||||
C --> P[Copyparty]
|
||||
C --> W[Calibre-Web]
|
||||
W --> L[Calibre library]
|
||||
C --> J[Jellyfin]
|
||||
C --> S[Sonarr]
|
||||
C --> D[Radarr]
|
||||
C --> L[Lidarr]
|
||||
C --> A[Readarr]
|
||||
C --> O[Prowlarr]
|
||||
W --> L2[Calibre library]
|
||||
```
|
||||
|
||||
## Services
|
||||
@@ -18,6 +24,22 @@ graph LR
|
||||
| RomM | romm.dankserver.local | 8085 | [[RomM]] |
|
||||
| Copyparty | files.dankserver.local | 3923 | [[Copyparty]] |
|
||||
| Calibre-Web | books.dankserver.local | 8083 | [[Calibre-Web]] |
|
||||
| Jellyfin | jellyfin.dankserver.local | 8096 | [[Jellyfin]] |
|
||||
| Sonarr | sonarr.dankserver.local | 8989 | [[ARR-Stack]] |
|
||||
| Radarr | radarr.dankserver.local | 7878 | [[ARR-Stack]] |
|
||||
| Lidarr | lidarr.dankserver.local | 8686 | [[ARR-Stack]] |
|
||||
| Readarr | readarr.dankserver.local | 8787 | [[ARR-Stack]] |
|
||||
| Prowlarr | prowlarr.dankserver.local | 9696 | [[ARR-Stack]] |
|
||||
| qBittorrent | qbittorrent.dankserver.local | 8080 | [[ARR-Stack]] |
|
||||
|
||||
## Optional Services
|
||||
|
||||
These services are included in the compose file but may be disabled.
|
||||
|
||||
| Service | Hostname | Port | Docs |
|
||||
|---------|----------|------|------|
|
||||
| Jackett | jackett.dankserver.local | 9117 | [[ARR-Stack]] |
|
||||
| Whisparr | whisparr.dankserver.local | 6969 | [[ARR-Stack]] |
|
||||
|
||||
## Removed Services
|
||||
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
# Jellyfin
|
||||
|
||||
Jellyfin is a free, open-source media server and suite of applications for organizing, managing, and streaming personal media collections (movies, TV shows, music, photos) to networked devices. It is a community fork of Emby, written in C# (.NET), and uses FFmpeg for transcoding.
|
||||
|
||||
**Host:** Dankserver — **Hostname:** `jellyfin.dankserver.local` — **Docs:** https://jellyfin.org
|
||||
|
||||
## Facts
|
||||
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| Latest version | Check https://jellyfin.org/downloads |
|
||||
| Image | `jellyfin/jellyfin:latest` (Docker Hub) or `ghcr.io/jellyfin/jellyfin` |
|
||||
| Base | Debian-based |
|
||||
| Primary port | 8096 (HTTP, web UI + API) |
|
||||
| HTTPS port | 8920 (optional) |
|
||||
| Client discovery | 7359/udp |
|
||||
| DLNA | 1900/udp (optional) |
|
||||
| GPU passthrough | `/dev/dri` (Intel QSV / AMD VA-API) or NVIDIA NVENC |
|
||||
| License | MIT |
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
U[User] --> C[Caddy :80/:443]
|
||||
C --> J[Jellyfin :8096]
|
||||
J --> Lib[/media/movies]
|
||||
J --> Lib2[/media/shows]
|
||||
J --> Lib3[/media/music]
|
||||
J --> Conf[Jellyfin config]
|
||||
J --> Cache[Jellyfin cache]
|
||||
```
|
||||
|
||||
## Docker Compose
|
||||
|
||||
```yaml
|
||||
services:
|
||||
jellyfin:
|
||||
image: jellyfin/jellyfin:latest
|
||||
container_name: jellyfin
|
||||
restart: unless-stopped
|
||||
user: "1000:1000"
|
||||
ports:
|
||||
- "8096:8096/tcp"
|
||||
- "8920:8920/tcp"
|
||||
- "7359:7359/udp"
|
||||
- "1900:1900/udp"
|
||||
environment:
|
||||
- JELLYFIN_PublishedServerUrl=http://192.168.0.235:8096
|
||||
- DOTNET_SYSTEM_IO_DISABLEFILELOCKING=true
|
||||
volumes:
|
||||
- /opt/jellyfin/config:/config
|
||||
- /opt/jellyfin/cache:/cache
|
||||
- /mnt/media/movies:/data/movies:ro
|
||||
- /mnt/media/shows:/data/shows:ro
|
||||
devices:
|
||||
- /dev/dri:/dev/dri
|
||||
group_add:
|
||||
- "992" # Host render group GID — verify with `getent group render`
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8096/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
```
|
||||
|
||||
## Caddy Configuration
|
||||
|
||||
```caddy
|
||||
jellyfin.dankserver.local {
|
||||
reverse_proxy 127.0.0.1:8096
|
||||
|
||||
transport http {
|
||||
versions h2c 1.1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Set **Base URL** to `/` (or the path you configure) in Jellyfin Dashboard → Networking. Add `127.0.0.1` to **Known Proxies**.
|
||||
|
||||
## Storage
|
||||
|
||||
| Mount | Purpose | Size Estimate |
|
||||
|-------|---------|---------------|
|
||||
| `/opt/jellyfin/config` | SQLite database, settings, cached images | 10–100 GB |
|
||||
| `/opt/jellyfin/cache` | Transcoding segments, extracted posters | Self-cleaning per session |
|
||||
|
||||
The database must be on local storage (SSD/NVMe preferred). Media libraries can be on NFS/mergerfs. If media is on NFS, set `DOTNET_SYSTEM_IO_DISABLEFILELOCKING=true`.
|
||||
|
||||
## Authentication
|
||||
|
||||
- **Built-in auth (default):** Per-user libraries, parental controls, max bitrate limits. Manage via Dashboard → Users.
|
||||
- **Caddy basic auth:** Single login layer. Does not integrate with per-user Jellyfin permissions.
|
||||
- **LDAP/OIDC:** Available via plugins (LDAP-Auth, Jellyfin SSO). Integrates with Authentik, Keycloak, etc.
|
||||
|
||||
For Dankserver, built-in auth is recommended. Use Caddy basic auth on top for external access.
|
||||
|
||||
## Metadata Scraping
|
||||
|
||||
| Provider | Content | Type |
|
||||
|----------|---------|------|
|
||||
| TheMovieDb (TMDb) | Movies, TV shows, posters, fan art, overviews | Default |
|
||||
| OMDb API | Movies only, English metadata | Default |
|
||||
| TheTVDB | TV shows, episodes | Plugin |
|
||||
| fanart.tv | Extra artwork, banners, thumbnails | Plugin |
|
||||
| AniDB | Anime metadata | Plugin |
|
||||
| MusicBrainz | Music metadata | Plugin |
|
||||
| Open Subtitles | Subtitle downloads | Plugin |
|
||||
| Intro Skipper | TV show intro detection | Plugin |
|
||||
|
||||
## Clients
|
||||
|
||||
| Platform | App | Quality |
|
||||
|----------|-----|---------|
|
||||
| Web | Jellyfin Web | Excellent |
|
||||
| Android | Jellyfin (Google Play / F-Droid) | Excellent |
|
||||
| Android TV / Fire TV | Jellyfin | Good |
|
||||
| iOS / iPadOS | Swiftfin (third-party) | Good |
|
||||
| Desktop | Jellyfin Media Player (mpv-based) | Excellent |
|
||||
| Roku | Jellyfin (Channel Store) | Good |
|
||||
| Kodi | Jellyfin addon | Excellent |
|
||||
| Samsung/LG Smart TVs | TV browser | Fair |
|
||||
|
||||
## Jellyfin vs Plex
|
||||
|
||||
| Feature | Jellyfin | Plex |
|
||||
|---------|----------|------|
|
||||
| Cost | Free, no tiers | Free core; Plex Pass ($5/mo or $120 lifetime) |
|
||||
| License | MIT | Proprietary |
|
||||
| Account required | No | Yes |
|
||||
| Hardware transcoding | Free | Plex Pass required |
|
||||
| Mobile sync | Free | Plex Pass |
|
||||
| Live TV / DVR | Free | Plex Pass |
|
||||
| Client apps | Good, improving | Excellent, widest device support |
|
||||
|
||||
Run Jellyfin alongside Plex for an incremental migration. Point Jellyfin at the same media folders as Plex. Watch history and metadata will not transfer cleanly.
|
||||
|
||||
## Resource Requirements
|
||||
|
||||
- **Idle / Direct Play:** ~200–500 MB RAM, <5% CPU. Negligible.
|
||||
- **1080p transcode (CPU):** 40–60% CPU on a modern multi-core CPU.
|
||||
- **1080p transcode (with QSV):** 3–5% CPU.
|
||||
- **4K HDR transcode (with QSV):** 5–15% CPU.
|
||||
- **Minimum host RAM:** 4 GB. 8 GB comfortable for transcoding.
|
||||
|
||||
## Deployment Checklist
|
||||
|
||||
1. Verify GPU on host: `ls -l /dev/dri/`, `lspci | grep -i vga`, `getent group render`.
|
||||
2. Install media drivers: `sudo apt install intel-media-va-driver-non-free vainfo intel-gpu-tools`.
|
||||
3. Create directories: `/opt/jellyfin/config`, `/opt/jellyfin/cache`.
|
||||
4. Write compose file, verify device and GID.
|
||||
5. Deploy: `podman compose up -d`.
|
||||
6. Test GPU passthrough: `podman exec jellyfin /usr/lib/jellyfin-ffmpeg/vainfo --display drm --device /dev/dri/renderD128`.
|
||||
7. Configure Caddy reverse proxy. Set Known Proxies in Jellyfin.
|
||||
8. Add media libraries in Dashboard.
|
||||
9. Install plugins: Open Subtitles, fanart.tv, Intro Skipper.
|
||||
10. Test playback on Android/Chrome.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **GPU passthrough silently failing:** `/dev/dri` must be passed and the correct render node used. Verify with `vainfo` inside the container.
|
||||
- **Wrong render group GID:** Common GID is 992, but varies per host. Run `getent group render` to find it.
|
||||
- **Subtitle burn-in triggers full transcode:** PGS (image-based) subtitles force full video transcoding. SRT/ASS (text-based) play fine.
|
||||
- **Database on NFS:** SQLite on network storage causes slow startup and corruption risk. Keep `/config` on local storage.
|
||||
- **Client bitrate limit too low:** Many clients default to 20 Mbps. Set Max Streaming Bitrate to Original or Maximum.
|
||||
- **Naming convention mismatches:** Non-standard folder/file names cause missing metadata. Use `Movie Title (Year)` for movies and `Show Name/Season 01/Show Name S01E01.mkv` for TV.
|
||||
|
||||
## See Also
|
||||
|
||||
- [[Dankserver Stack]]
|
||||
- [[ARR-Stack]] — automated download into Jellyfin libraries
|
||||
- [[Copyparty]] — alternative file viewer for existing collections
|
||||
- [[Plex]] — existing media server on this host
|
||||
@@ -0,0 +1,296 @@
|
||||
# RomM Scraping & Asset Management
|
||||
|
||||
This guide covers metadata providers, cover art, ROM naming conventions, emulator integration, and the scraping workflow for RomM on Dankserver.
|
||||
|
||||
**Reference:** https://docs.romm.app
|
||||
|
||||
## 1. Metadata Providers
|
||||
|
||||
RomM v5.1.0+ supports 11+ metadata providers. The `scan.priority.metadata` list determines which provider wins for descriptive fields. The `scan.priority.artwork` list controls cover art sourcing separately.
|
||||
|
||||
### Screenscraper (ScreenScraper.fr)
|
||||
|
||||
- **Type:** Free, community-driven (French provider)
|
||||
- **Credentials:** `SCREENSCRAPER_USER` + `SCREENSCRAPER_PASSWORD` (account user/pass)
|
||||
- **Registration:** https://www.screenscraper.fr/membreinscription.php
|
||||
- **Rate limits:** No documented hard cap. Community-claimed ~5 req/sec burst.
|
||||
- **Capabilities:** Titles, descriptions, cover art, screenshots, manuals, 3D boxes, CD/cartridge covers, marquee logos, fanart, bezels, gameplay videos.
|
||||
- **Region support:** Excellent. Respects `scan.priority.region` and `scan.priority.region_mode`.
|
||||
- **Best for:** Richest media coverage (all art types), multi-platform, free. Use as secondary to IGDB for metadata, or swap priority order if Screenscraper art quality is preferred.
|
||||
|
||||
### IGDB (Internet Game Database / Twitch)
|
||||
|
||||
- **Type:** Freemium (free tier with limits; paid for higher volume)
|
||||
- **Credentials:** `IGDB_CLIENT_ID` + `IGDB_CLIENT_SECRET` (Twitch OAuth2)
|
||||
- **Registration:** Twitch Developer Portal. Create app with name `romm-<random hash>`, OAuth redirect `localhost`, category `Application Integration`, client type `Confidential`.
|
||||
- **Rate limits:** ~10 req/sec for free tier. Cached responses reduce effective calls.
|
||||
- **Capabilities:** Titles, descriptions, cover art, screenshots, related games, release dates, genres, platforms.
|
||||
- **Limitations:** No 3D boxes or physical media art. No manuals. No marquee/fanart.
|
||||
- **Default priority:** Highest (`igdb` listed first in both metadata and artwork priority).
|
||||
|
||||
### MobyGames
|
||||
|
||||
- **Type:** Paid (hobbyist API subscription; non-commercial use only)
|
||||
- **Credentials:** `MOBYGAMES_API_KEY`
|
||||
- **Rate limits:** Hobbyist tier ~0.2 req/sec (one request every 5 seconds).
|
||||
- **RomM recommendation:** "We recommend using ScreenScraper instead, as it is free to use."
|
||||
- **Best for:** Supplemental metadata depth for older PC/console titles.
|
||||
|
||||
### RetroAchievements (RAHasher)
|
||||
|
||||
- **Type:** Free, hash-based achievement tracking
|
||||
- **Credentials:** `RETROACHIEVEMENTS_API_KEY`
|
||||
- **How it works:** RomM bundles RAHasher (v1.8.3+). ROMs are hashed during scans, matched against RA online database. Achievement progress synced per-user via their RA username.
|
||||
- **Known issues:** Folder-based disc ROMs (`.cue` + `.bin`, `.gdi`) may fail hashing. Non-zip archives (`.7z`, `.rar`) had incorrect hash computation. Ensure `filesystem.skip_hash_calculation` is `false`.
|
||||
- **Important:** Achievements cannot be earned via RomM's built-in EmulatorJS player. Must use an RA-capable standalone emulator.
|
||||
|
||||
### Additional Built-in Providers
|
||||
|
||||
| Provider | Slug | Enabled Via | Type |
|
||||
|----------|------|-------------|------|
|
||||
| Hasheous | `hasheous` | `HASHEOUS_API_ENABLED=true` | Free, hash-based, proxies IGDB data |
|
||||
| Playmatch | `playmatch` | `PLAYMATCH_API_ENABLED=true` | Multi-provider hash matching |
|
||||
| LaunchBox | `launchbox` | `LAUNCHBOX_API_ENABLED=true` + XML | Local XML database |
|
||||
| Flashpoint | `flashpoint` | `FLASHPOINT_API_ENABLED=true` | 180,000+ browser games |
|
||||
| HowLongToBeat | `hltb` | `HLTB_API_ENABLED=true` | Game completion times |
|
||||
| SteamGridDB | `steamgriddb` | `STEAMGRIDDB_API_KEY` | Custom cover art |
|
||||
| ES-DE gamelist | `gamelist` | Place `gamelist.xml` in platform folder | Local XML |
|
||||
|
||||
## 2. Recommended Provider Combinations
|
||||
|
||||
| Combo | Providers | Best For | Cost |
|
||||
|-------|-----------|----------|------|
|
||||
| Quick Starter | Hasheous only | No API keys needed | Free |
|
||||
| French Connection | Screenscraper + RetroAchievements | Rich media, free | Free |
|
||||
| Chef's Choice (recommended) | Hasheous + IGDB + SteamGridDB + RetroAchievements | Best overall quality | Free (IGDB free tier) |
|
||||
| Twitch Fanboy | IGDB + Playmatch | Single-provider solution | Free |
|
||||
|
||||
**For Dankserver,** the recommended setup:
|
||||
- `IGDB` (primary metadata) + `SCREENSCRAPER` (artwork backup + rich media) + `RETROACHIEVEMENTS` (achievements) + `HASHEOUS_API_ENABLED=true` (fast hash-based fallback)
|
||||
|
||||
## 3. ROM File Naming Conventions
|
||||
|
||||
### No-Intro Naming Scheme (Recommended)
|
||||
|
||||
The de facto standard for cartridge and handheld ROMs. Only `Title` and `Region` are required.
|
||||
|
||||
```
|
||||
Super Metroid (Japan, USA) (En,Ja)
|
||||
Sonic the Hedgehog (USA)
|
||||
Metal Gear Solid (USA) (Disc 1)
|
||||
[BIOS] PS1 System BIOS (USA)
|
||||
Tetris [!].gba
|
||||
```
|
||||
|
||||
**Field meanings:**
|
||||
- `(Region)`: `USA`, `EUR`, `JPN`, `UE` (USA+Europe), `JUE` (Japan+USA+Europe)
|
||||
- `(Languages)`: `En`, `Ja`, `De`, `Fr`, `Es`
|
||||
- `[Status]`: `[!]` = verified good dump, `[b]` = bad dump, `[c]` = completed
|
||||
- `(Devstatus)`: `(Proto)`, `(Demo)`, `(Release Candidate)`
|
||||
- `[BIOS]` prefix: Identifies BIOS files
|
||||
|
||||
### RomM's Region/Language/Revision Parsing
|
||||
|
||||
RomM parses inline tags from filenames:
|
||||
|
||||
```
|
||||
tetris (En) [1.0001] [HACK] [!].gba
|
||||
```
|
||||
|
||||
- Region/language: ISO-like codes or full names
|
||||
- Revision: `rev v1` or `rev-1`
|
||||
- Provider ID tags: `(igdb-xxxx)`, `(ssfr-xxxx)`, `(moby-xxxx)`, `(ra-xxxx)` — forces specific provider match
|
||||
|
||||
### Best Practices for Dankserver
|
||||
|
||||
1. Use No-Intro naming as the standard.
|
||||
2. Use **Igir** to rename and organize ROMs into RomM's required folder structure:
|
||||
```
|
||||
igir copy zip test clean \
|
||||
--dat "No-Intro*.zip" \
|
||||
--input "ROMs" \
|
||||
--output "/opt/romm/roms/{romm}"
|
||||
```
|
||||
3. Keep `[BIOS]` prefix for BIOS files in the `bios/` directory.
|
||||
4. One ROM file per game folder where possible.
|
||||
5. Use archive formats (`.zip`, `.7z`) — RomM supports them natively.
|
||||
|
||||
## 4. Cover Art & Media Assets
|
||||
|
||||
### Media Types
|
||||
|
||||
| Media Type | Description | Best Provider |
|
||||
|-----------|-------------|---------------|
|
||||
| `box2d` | Standard 2D front cover art | IGDB, Screenscraper |
|
||||
| `box3d` | 3D box art | Screenscraper |
|
||||
| `miximage` | Composite (box + screenshot + logo) | Screenscraper |
|
||||
| `screenshot` | In-game screenshot | IGDB, Screenscraper |
|
||||
| `marquee` | Transparent logo/header | Screenscraper |
|
||||
| `bezel` | EmulatorJS-compatible bezel | Screenscraper |
|
||||
| `manual` | PDF instruction manual | Screenscraper |
|
||||
| `video` | Gameplay video/trailer | Screenscraper |
|
||||
|
||||
### Custom Artwork Directories
|
||||
|
||||
RomM supports manual artwork placement via subdirectories within each game folder:
|
||||
|
||||
```
|
||||
/opt/romm/library/roms/{platform}/{game}/
|
||||
game.rom
|
||||
covers/
|
||||
screenshots/
|
||||
3dboxes/
|
||||
manuals/
|
||||
fanart/
|
||||
videos/
|
||||
marquees/
|
||||
bezels/
|
||||
```
|
||||
|
||||
For ES-DE gamelist imports, media maps as:
|
||||
|
||||
| gamelist.xml Tag | Folder Name |
|
||||
|-----------------|-------------|
|
||||
| `<cover>` | `covers/` |
|
||||
| `<backcover>` | `backcovers/` |
|
||||
| `<box3d>` | `3dboxes/` |
|
||||
| `<marquee>` | `marquees/` |
|
||||
| `<screenshot>` | `screenshots/` |
|
||||
| `<fanart>` | `fanart/` |
|
||||
| `<manual>` | `manuals/` |
|
||||
|
||||
### MAME Artwork
|
||||
|
||||
MAME uses cabinet pics, flyers, marquees, control panels, backdrops, overlays. Stored in `{platform}/mame_artwork/{game}/` subdirectories.
|
||||
|
||||
Sources: Mr. Do's Arcade (https://www.mameworld.info/mrdo/), ProgettoSnaps (http://www.progettosnaps.net/artworks/).
|
||||
|
||||
## 5. Emulator Integration
|
||||
|
||||
### EmulatorJS (Built-in)
|
||||
|
||||
Web-based player using RetroArch cores compiled to WebAssembly. Runs in-browser with no local emulator needed. Configured via `emulatorjs.*` settings in `config.yml`. Supports netplay via STUN/TURN servers.
|
||||
|
||||
### Emulator Streaming
|
||||
|
||||
Launch native emulator containers (PCSX2, Dolphin, Xemu) and stream picture/sound/input back to the browser. Configured via `streaming.*` in `config.yml`.
|
||||
|
||||
### BIOS File Requirements
|
||||
|
||||
BIOS files placed in `/opt/romm/library/bios/{platform}/`. Platform subdirectories required. File names should match emulator expectations:
|
||||
|
||||
| Platform | BIOS File |
|
||||
|----------|-----------|
|
||||
| PlayStation | `scph1001.bin`, `scph5501.bin`, `scph5502.bin` |
|
||||
| GB/GBC | `gb_bios.bin`, `gbc_bios.bin` |
|
||||
| SNES | `sfc_bios.bin` |
|
||||
|
||||
BIOS matching done by hash against platform requirements.
|
||||
|
||||
### Folder Structure Options
|
||||
|
||||
**Structure A (recommended):**
|
||||
```
|
||||
/opt/romm/library/
|
||||
roms/
|
||||
└── {platform}/
|
||||
└── {game}.rom
|
||||
bios/
|
||||
└── {platform}/
|
||||
└── {bios_file}.bin
|
||||
```
|
||||
|
||||
**Structure B (fallback):**
|
||||
```
|
||||
/opt/romm/library/
|
||||
└── {platform}/
|
||||
├── roms/
|
||||
│ └── {game}.rom
|
||||
└── bios/
|
||||
└── {bios_file}.bin
|
||||
```
|
||||
|
||||
Dankserver mounts `/opt/romm/library:/romm/library` — RomM auto-detects structure.
|
||||
|
||||
## 6. Scraping Workflow
|
||||
|
||||
### Recommended Pipeline
|
||||
|
||||
1. Organize ROMs → No-Intro naming + RomM folder structure.
|
||||
2. Create `config.yml` → Set provider credentials, priority lists, region prefs.
|
||||
3. First scan → Scan ALL → verify everything is matched.
|
||||
4. Review unmatched → Manually match or add provider tags to filenames.
|
||||
5. Fetch artwork → Re-scan with `scan.media` extended to desired types.
|
||||
6. Sync RetroAchievements → Set user RA username → trigger sync.
|
||||
7. Export gamelist → Enable `scan.gamelist.export` for ES-DE/Batocera.
|
||||
8. Maintain → Enable scheduled rescans for new DAT updates.
|
||||
|
||||
### Scan Types
|
||||
|
||||
| Scan Type | What It Does |
|
||||
|-----------|-------------|
|
||||
| ALL | Full scan — hash, match metadata, fetch artwork |
|
||||
| UNMATCHED | Only matches unmatched ROMs (faster) |
|
||||
| METADATA | Updates metadata only |
|
||||
| ARTWORK | Re-fetches artwork only |
|
||||
| RETROACHIEVEMENTS | Syncs achievement data |
|
||||
|
||||
### Region Handling
|
||||
|
||||
```yaml
|
||||
scan:
|
||||
priority:
|
||||
region:
|
||||
- "us"
|
||||
- "eu"
|
||||
- "jp"
|
||||
region_mode: prefer_rom_tags # or prefer_config
|
||||
```
|
||||
|
||||
- `prefer_rom_tags` (default): ROM filename region tags take precedence.
|
||||
- `prefer_config`: Config regions come first.
|
||||
- **NTSC-U** (USA): 60 Hz, typically fastest, most translations.
|
||||
- **PAL** (Europe): 50 Hz, sometimes slower, may have bonus content.
|
||||
- **NTSC-J** (Japan): 60 Hz, Japanese only unless region-patched.
|
||||
|
||||
## 7. Collection Management Tools
|
||||
|
||||
| Tool | Primary Role | Platform |
|
||||
|------|-------------|----------|
|
||||
| RomVault 3.7.6 | DAT-file-based verification and reorganization | Windows |
|
||||
| clrMAMEPro | ROM set validation, deduplication, 1G1R | Windows |
|
||||
| DATBios | BIOS file organization using DAT files | Windows |
|
||||
| Batocera/Lakka integration | ES-DE gamelist import from RomM | Linux/ARM |
|
||||
|
||||
## 8. Environment Variables (Dankserver)
|
||||
|
||||
```bash
|
||||
# Auth
|
||||
ROMM_USERNAME=admin
|
||||
ROMM_PASSWORD=<strong password>
|
||||
ROMM_AUTH_SECRET_KEY=$(openssl rand -hex 32)
|
||||
|
||||
# Metadata Providers
|
||||
IGDB_CLIENT_ID=<your-client-id>
|
||||
IGDB_CLIENT_SECRET=<your-client-secret>
|
||||
SCREENSCRAPER_USER=<screenscraper-username>
|
||||
SCREENSCRAPER_PASSWORD=<screenscraper-password>
|
||||
MOBYGAMES_API_KEY=<mobygames-key>
|
||||
RETROACHIEVEMENTS_API_KEY=<retroachievements-api-key>
|
||||
STEAMGRIDDB_API_KEY=<steamgriddb-key>
|
||||
|
||||
# Feature Flags
|
||||
HASHEOUS_API_ENABLED=true
|
||||
PLAYMATCH_API_ENABLED=true
|
||||
|
||||
# Scanning
|
||||
ENABLE_RESCAN_ON_FILESYSTEM_CHANGE=true
|
||||
ENABLE_SCHEDULED_RESCAN=true
|
||||
REFRESH_RETROACHIEVEMENTS_CACHE_DAYS=7
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
- [[RomM]] — main service documentation
|
||||
- [[Dankserver Stack]]
|
||||
- [[ARR-Stack]] — Readarr for ebook auto-downloads alongside ROM management
|
||||
+163
-14
@@ -1,26 +1,103 @@
|
||||
# RomM
|
||||
|
||||
RomM (ROM Manager) is a self-hosted rom manager and player for retro game collections. It scans a ROM library, enriches it with metadata and cover art, and serves it through a clean web UI.
|
||||
RomM (ROM Manager) is a self-hosted ROM library manager and player. It scans a ROM collection, enriches it with metadata and cover art from multiple providers, and serves it through a clean web interface. RomM also supports browser-based emulation via EmulatorJS and native emulator streaming.
|
||||
|
||||
**Host:** Dankserver — **Hostname:** `romm.dankserver.local` — **Docs:** https://docs.romm.app
|
||||
|
||||
## Facts (from research)
|
||||
## Facts
|
||||
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| Latest version | 5.2.0 (released 2026-07-29) |
|
||||
| Image | `ghcr.io/rommapp/romm:latest` |
|
||||
| Port | 8085 (host) → 8080 (container) |
|
||||
| Data volume | config, cache, covers, metadata DB |
|
||||
| ROMs volume | bind mount to the game library |
|
||||
| Frontend | React; backend FastAPI/Node |
|
||||
| Metadata | Screenscraper, IGDB, MobyGames, RAHasher (optional) |
|
||||
| Database | MariaDB (default); PostgreSQL optional |
|
||||
| Cache / Queue | Redis or Valkey (required for task queue) |
|
||||
| Frontend | React SPA |
|
||||
| Backend | FastAPI / Node |
|
||||
| Metadata providers | IGDB, Screenscraper, MobyGames, Hasheous, Playmatch, LaunchBox, Flashpoint, HowLongToBeat, SteamGridDB, RetroAchievements, TGDB, ES-DE gamelist |
|
||||
| Emulator player | EmulatorJS (WebAssembly RetroArch cores) |
|
||||
| Emulator streaming | Native containers (PCSX2, Dolphin, Xemu) → browser |
|
||||
|
||||
## Architecture
|
||||
|
||||
RomM 5.2.0 requires three supporting services. The compose stack includes `romm`, `mariadb`, and `redis` (or `valkey`).
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
U[User] --> C[Caddy :80/:443]
|
||||
C --> R[RomM :8085]
|
||||
R --> DB[(MariaDB)]
|
||||
R --> Cache[(Redis)]
|
||||
R --> Lib[/romm/library]
|
||||
R --> Res[/romm/resources]
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
- Set `ROMM_USERNAME`, `ROMM_PASSWORD`, `ROMM_SECRET_KEY` on first boot (creates the admin user).
|
||||
- `DISABLE_AUTH: true` disables authentication for LAN-only deployments (not recommended behind Caddy auth).
|
||||
- Bind-mount the ROM library read-only unless RomM should also manage folder structure.
|
||||
- Metadata providers need API keys; set them in the RomM admin UI after first login.
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `ROMM_USERNAME` | Yes | Initial admin username |
|
||||
| `ROMM_PASSWORD` | Yes | Initial admin password (set on first boot) |
|
||||
| `ROMM_AUTH_SECRET_KEY` | Yes | JWT signing key. Generate with `openssl rand -hex 32`. Replaces the old `ROMM_SECRET_KEY`. |
|
||||
| `DB_HOST` | Yes | MariaDB hostname (e.g. `mariadb`) |
|
||||
| `DB_NAME` | Yes | Database name (e.g. `romm`) |
|
||||
| `DB_USER` | Yes | Database user |
|
||||
| `DB_PASSWD` | Yes | Database password |
|
||||
| `REDIS_HOST` | Yes | Redis hostname (e.g. `redis`) |
|
||||
| `DISABLE_SETUP_WIZARD` | No | Set to `true` to skip the first-run wizard |
|
||||
| `OIDC_ENABLED` | No | Enable OpenID Connect authentication |
|
||||
| `OIDC_CLIENT_ID` | No | OIDC client ID |
|
||||
| `OIDC_CLIENT_SECRET` | No | OIDC client secret |
|
||||
| `OIDC_REDIRECT_URI` | No | OIDC redirect URI |
|
||||
| `STREAMING_BROKER_SECRET` | No | Secret for native emulator streaming |
|
||||
| `STREAMING_SAVE_TIMEOUT` | No | Timeout for save states during streaming |
|
||||
| `KIOSK_MODE` | No | Enable kiosk mode |
|
||||
| `ROMM_SESSION_SECURE_COOKIE` | No | Secure cookie flag for sessions |
|
||||
|
||||
### Metadata Provider Credentials
|
||||
|
||||
These are set via environment variables or in `config.yml`:
|
||||
|
||||
| Variable | Provider | Notes |
|
||||
|----------|----------|-------|
|
||||
| `IGDB_CLIENT_ID` / `IGDB_CLIENT_SECRET` | IGDB (Twitch OAuth2) | Create app at Twitch Developer Portal. Free tier: ~10 req/sec. |
|
||||
| `SCREENSCRAPER_USER` / `SCREENSCRAPER_PASSWORD` | Screenscraper | Account credentials (not API key). Free, community-driven. |
|
||||
| `MOBYGAMES_API_KEY` | MobyGames | Paid hobbyist API. Note: RomM recommends Screenscraper as free alternative. |
|
||||
| `RETROACHIEVEMENTS_API_KEY` | RetroAchievements | Hash-based achievements via bundled RAHasher binary. |
|
||||
| `STEAMGRIDDB_API_KEY` | SteamGridDB | Custom cover art via the search cover button. |
|
||||
| `HASHEOUS_API_ENABLED` | Hasheous | Set to `true`. Free, hash-based, proxies IGDB data. Fast scans. |
|
||||
| `PLAYMATCH_API_ENABLED` | Playmatch | Set to `true`. Multi-provider hash matching (IGDB, SS, SteamGridDB, RA). |
|
||||
|
||||
### Config File
|
||||
|
||||
RomM uses `config.yml` for scan settings, available through the admin UI (Scan Settings). Place the file at `/opt/romm/config/config.yml` on the host.
|
||||
|
||||
Key scan config options:
|
||||
|
||||
```yaml
|
||||
scan:
|
||||
priority:
|
||||
metadata:
|
||||
- igdb
|
||||
- ss # Screenscraper
|
||||
artwork:
|
||||
- igdb
|
||||
- ss
|
||||
region:
|
||||
- us
|
||||
- eu
|
||||
- jp
|
||||
region_mode: prefer_rom_tags # or prefer_config
|
||||
media:
|
||||
- box2d
|
||||
- screenshot
|
||||
- manual
|
||||
gamelist:
|
||||
export: true # Export ES-DE compatible gamelist.xml
|
||||
```
|
||||
|
||||
## Volumes
|
||||
|
||||
@@ -28,18 +105,90 @@ RomM (ROM Manager) is a self-hosted rom manager and player for retro game collec
|
||||
|----------------|------------------------|
|
||||
| `/romm/library` | `/opt/romm/library` |
|
||||
| `/romm/resources` | `/opt/romm/resources` |
|
||||
| `/romm/config` | `/opt/romm/config` |
|
||||
|
||||
The library volume contains ROM files and subdirectories per platform. The resources volume stores cached artwork, metadata, and the SQLite/SQLite-backed asset cache. The config volume holds `config.yml` and other configuration.
|
||||
|
||||
## Docker Compose
|
||||
|
||||
```yaml
|
||||
services:
|
||||
romm:
|
||||
image: ghcr.io/rommapp/romm:latest
|
||||
container_name: romm
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
ROMM_USERNAME: "${ROMM_USERNAME}"
|
||||
ROMM_PASSWORD: "${ROMM_PASSWORD}"
|
||||
ROMM_AUTH_SECRET_KEY: "${ROMM_AUTH_SECRET_KEY}"
|
||||
DB_HOST: mariadb
|
||||
DB_NAME: romm
|
||||
DB_USER: "${ROMM_DB_USER}"
|
||||
DB_PASSWD: "${ROMM_DB_PASSWD}"
|
||||
REDIS_HOST: redis
|
||||
ports:
|
||||
- "8085:8080"
|
||||
volumes:
|
||||
- /opt/romm/library:/romm/library
|
||||
- /opt/romm/resources:/romm/resources
|
||||
- /opt/romm/config:/romm/config
|
||||
depends_on:
|
||||
mariadb:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
|
||||
mariadb:
|
||||
image: docker.io/mariadb:11
|
||||
container_name: romm-mariadb
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
MARIADB_ROOT_PASSWORD: "${MARIADB_ROOT_PASSWORD}"
|
||||
MARIADB_DATABASE: romm
|
||||
MARIADB_USER: "${ROMM_DB_USER}"
|
||||
MARIADB_PASSWORD: "${ROMM_DB_PASSWD}"
|
||||
volumes:
|
||||
- /opt/romm/mariadb:/var/lib/mysql
|
||||
healthcheck:
|
||||
test: ["CMD", "mariadb-admin", "ping", "-h", "localhost"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
redis:
|
||||
image: docker.io/redis:7-alpine
|
||||
container_name: romm-redis
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /opt/romm/redis:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
```
|
||||
|
||||
## Healthcheck
|
||||
|
||||
Expose a `/health` endpoint; RomM serves the UI on `/`.
|
||||
```yaml
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
```
|
||||
|
||||
## Gotchas
|
||||
|
||||
- The first login sets the admin password; do not rely on the env credentials after that.
|
||||
- Database is SQLite by default — back it up with the resources volume.
|
||||
- RAHasher build increases image build time; skip unless RetroAchievements hashes are needed.
|
||||
- **First login overwrites env credentials.** The `ROMM_PASSWORD` env var sets the initial password. After first login, the admin password is controlled in the UI. The env var only applies on first boot.
|
||||
- **MariaDB and Redis are required.** RomM 5.2.0 no longer supports SQLite-only deployments. Both MariaDB and Redis must be running.
|
||||
- **Reverse proxy cache stale index.html.** Purge Caddy proxy cache after RomM version bumps to avoid serving a stale frontend after an upgrade.
|
||||
- **RAHasher build time.** Enabling RetroAchievements hashing increases the first image build. Skip unless you need achievement data.
|
||||
- **MobyGames is paid.** The hobbyist API has strict rate limits. Screenscraper is the recommended free alternative.
|
||||
- **OIDC requires additional services.** Authentik, Keycloak, or another OIDC provider must be running before enabling `OIDC_ENABLED`.
|
||||
|
||||
## See Also
|
||||
|
||||
- [[Dankserver Stack]]
|
||||
- [[RomM Scraping]] — metadata providers, cover art, naming conventions, emulator integration
|
||||
- [[Calibre-Web]] — sibling library web UI
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
# Lidarr
|
||||
|
||||
Lidarr manages music albums in the *arr stack on Dankserver. It automatically searches, downloads, and organizes albums from indexers into the Jellyfin music library.
|
||||
|
||||
**Host:** Dankserver — **Hostname:** `lidarr.dankserver.local` — **Docs:** https://wiki.servarr.com/lidarr
|
||||
|
||||
## Facts
|
||||
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| Image | `lscr.io/linuxserver/lidarr:latest` |
|
||||
| Port | 8686 (host) → 8686 (container) |
|
||||
| Min RAM | 256 MB |
|
||||
| Metadata | MusicBrainz |
|
||||
|
||||
## Docker Compose
|
||||
|
||||
```yaml
|
||||
lidarr:
|
||||
image: lscr.io/linuxserver/lidarr:latest
|
||||
container_name: lidarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/lidarr/config:/config
|
||||
- /mnt/media/music:/music
|
||||
- /mnt/media/downloads:/downloads
|
||||
ports:
|
||||
- "8686:8686"
|
||||
networks: [appnet]
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
1. Add Prowlarr as the indexer source (prefer torrent-based indexers for FLAC).
|
||||
2. Add qBittorrent as the download client with the `music` category.
|
||||
3. Set quality profile (Lossless → High Bitrate → Standard).
|
||||
4. Set root folder to `/music`.
|
||||
5. Add artists and verify downloads.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Album variants: Lidarr supports multiple releases of the same album (vinyl vs CD). Use "Preferred" and "Cutoff" quality profiles.
|
||||
- Music videos can be optionally downloaded separately from albums.
|
||||
|
||||
## See Also
|
||||
|
||||
- [[ARR-Stack]] — full *arr stack documentation
|
||||
- [[Jellyfin]] — media server that consumes Lidarr downloads
|
||||
@@ -0,0 +1,47 @@
|
||||
# MariaDB (RomM Backend)
|
||||
|
||||
MariaDB 11 provides the database backend for RomM on Dankserver. RomM 5.2.0 requires MariaDB (or PostgreSQL) for its data store.
|
||||
|
||||
**Host:** Dankserver — **Docs:** https://mariadb.com/kb/en/docker-mariadb-information/
|
||||
|
||||
## Facts
|
||||
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| Image | `docker.io/mariadb:11` |
|
||||
| Port | 3306 (internal, within `appnet`) |
|
||||
| Database name | `romm` |
|
||||
| Data volume | `/opt/romm/mariadb` |
|
||||
|
||||
## Docker Compose
|
||||
|
||||
```yaml
|
||||
mariadb:
|
||||
image: docker.io/mariadb:11
|
||||
container_name: romm-mariadb
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
MARIADB_ROOT_PASSWORD: "${MARIADB_ROOT_PASSWORD}"
|
||||
MARIADB_DATABASE: romm
|
||||
MARIADB_USER: "${ROMM_DB_USER}"
|
||||
MARIADB_PASSWORD: "${ROMM_DB_PASSWD}"
|
||||
volumes:
|
||||
- /opt/romm/mariadb:/var/lib/mysql
|
||||
healthcheck:
|
||||
test: ["CMD", "mariadb-admin", "ping", "-h", "localhost"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
```
|
||||
|
||||
## Backup
|
||||
|
||||
Back up the volume directory periodically:
|
||||
|
||||
```bash
|
||||
sudo rsync -a /opt/romm/mariadb /mnt/backup/romm-mariadb/
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
- [[RomM]] — service that uses this database
|
||||
@@ -0,0 +1,55 @@
|
||||
# Prowlarr
|
||||
|
||||
Prowlarr is the indexer management layer for the *arr stack. It aggregates indexers (torrent and Usenet) and exposes a unified API that Sonarr, Radarr, Lidarr, and Readarr consume.
|
||||
|
||||
**Host:** Dankserver — **Hostname:** `prowlarr.dankserver.local` — **Docs:** https://wiki.servarr.com/prowlarr
|
||||
|
||||
## Facts
|
||||
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| Image | `lscr.io/linuxserver/prowlarr:latest` |
|
||||
| Port | 9696 (host) → 9696 (container) |
|
||||
| Min RAM | 256 MB |
|
||||
| Auth | API key (Settings → General) |
|
||||
|
||||
## Configuration
|
||||
|
||||
1. Add indexers: Settings → Indexers → Add.
|
||||
2. Test each indexer with the **Test** button.
|
||||
3. Assign tags (e.g., `movies`, `tv`, `music`) to indexers for routing.
|
||||
4. Add download client: Settings → Download Clients → Add qBittorrent.
|
||||
|
||||
## Docker Compose
|
||||
|
||||
```yaml
|
||||
prowlarr:
|
||||
image: lscr.io/linuxserver/prowlarr:latest
|
||||
container_name: prowlarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/prowlarr/config:/config
|
||||
- /mnt/media/downloads:/downloads:ro
|
||||
ports:
|
||||
- "9696:9696"
|
||||
networks: [appnet]
|
||||
```
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Prowlarr database grows with indexer data. Set up periodic vacuum/backup.
|
||||
- Indexer sync has a 15–60 minute delay. Search results may lag.
|
||||
- Rotate API key: update it in every arr app.
|
||||
|
||||
## See Also
|
||||
|
||||
- [[ARR-Stack]] — full *arr stack documentation
|
||||
- [[radarr]]
|
||||
- [[sonarr]]
|
||||
- [[lidarr]]
|
||||
- [[readarr]]
|
||||
@@ -0,0 +1,52 @@
|
||||
# qBittorrent
|
||||
|
||||
qBittorrent is the torrent download client for the *arr stack on Dankserver. It receives download requests from Sonarr, Radarr, Lidarr, and Readarr via category tagging.
|
||||
|
||||
**Host:** Dankserver — **Hostname:** `qbittorrent.dankserver.local` — **Docs:** https://www.qbittorrent.org
|
||||
|
||||
## Facts
|
||||
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| Image | `lscr.io/linuxserver/qbittorrent:latest` |
|
||||
| Port | 8080 (host) → 8080 (container) |
|
||||
| Min RAM | 512 MB |
|
||||
| Auth | Web UI username/password; LAN mode available |
|
||||
|
||||
## Configuration
|
||||
|
||||
1. Change the default Web UI password (Settings → Web UI).
|
||||
2. Enable "No auth mode for LAN" for arr app connectivity (Settings → Web UI → uncheck "HTTP authentication required for clients").
|
||||
3. Create download categories: `movies`, `tv`, `music`, `books`.
|
||||
4. Set max active downloads: Settings → Downloads (recommended: 5 global, 3 per category).
|
||||
|
||||
## Docker Compose
|
||||
|
||||
```yaml
|
||||
qbittorrent:
|
||||
image: lscr.io/linuxserver/qbittorrent:latest
|
||||
container_name: qbittorrent
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/qbittorrent/config:/config
|
||||
- /mnt/media/downloads:/downloads
|
||||
- /mnt/media/downloads/incomplete:/downloads/incomplete
|
||||
ports:
|
||||
- "8080:8080"
|
||||
networks: [appnet]
|
||||
```
|
||||
|
||||
## Gotchas
|
||||
|
||||
- qBittorrent Web UI password changes on first run (check `config/qBittorrent.conf`).
|
||||
- Ensure umask is set to `022` so downloaded files are readable by arr apps.
|
||||
- Monitor bandwidth limits to avoid saturating the network.
|
||||
|
||||
## See Also
|
||||
|
||||
- [[ARR-Stack]] — full *arr stack documentation
|
||||
@@ -0,0 +1,54 @@
|
||||
# Radarr
|
||||
|
||||
Radarr manages movies in the *arr stack on Dankserver. It automatically searches, downloads, and organizes movies from indexers into the Jellyfin media library.
|
||||
|
||||
**Host:** Dankserver — **Hostname:** `radarr.dankserver.local` — **Docs:** https://wiki.servarr.com/radarr
|
||||
|
||||
## Facts
|
||||
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| Image | `lscr.io/linuxserver/radarr:latest` (v4 stable) |
|
||||
| Port | 7878 (host) → 7878 (container) |
|
||||
| Min RAM | 512 MB |
|
||||
| Metadata | TMDB / TheMovieDB API |
|
||||
|
||||
## Docker Compose
|
||||
|
||||
```yaml
|
||||
radarr:
|
||||
image: lscr.io/linuxserver/radarr:latest
|
||||
container_name: radarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/radarr/config:/config
|
||||
- /mnt/media/movies:/movies
|
||||
- /mnt/media/downloads:/downloads
|
||||
ports:
|
||||
- "7878:7878"
|
||||
networks: [appnet]
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
1. Add Prowlarr as the indexer source.
|
||||
2. Add qBittorrent as the download client with the `movies` category.
|
||||
3. Set quality profile and cutoff quality.
|
||||
4. Set root folder to `/movies`.
|
||||
5. Add movies and verify downloads.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Radarr v4 is the current stable. `:latest` points to v4, not v5.
|
||||
- Movie renaming produces `Title (Year)` format. Jellyfin scanner handles this.
|
||||
- File permissions: qBittorrent downloads as PUID; arr apps must read/move files.
|
||||
|
||||
## See Also
|
||||
|
||||
- [[ARR-Stack]] — full *arr stack documentation
|
||||
- [[Jellyfin]] — media server that consumes Radarr downloads
|
||||
@@ -0,0 +1,55 @@
|
||||
# Readarr
|
||||
|
||||
Readarr manages ebooks and audiobooks in the *arr stack on Dankserver. It automatically searches, downloads, and organizes books into the Calibre library.
|
||||
|
||||
**Host:** Dankserver — **Hostname:** `readarr.dankserver.local` — **Docs:** https://wiki.servarr.com/readarr
|
||||
|
||||
## Facts
|
||||
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| Image | `lscr.io/linuxserver/readarr:latest` (v0.2.x development) |
|
||||
| Port | 8787 (host) → 8787 (container) |
|
||||
| Min RAM | 256 MB |
|
||||
| Metadata | Goodreads / StoryGraph |
|
||||
|
||||
## Docker Compose
|
||||
|
||||
```yaml
|
||||
readarr:
|
||||
image: lscr.io/linuxserver/readarr:latest
|
||||
container_name: readarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/readarr/config:/config
|
||||
- /mnt/media/books:/books
|
||||
- /mnt/media/downloads:/downloads
|
||||
ports:
|
||||
- "8787:8787"
|
||||
networks: [appnet]
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
1. Add Prowlarr as the indexer source (torrent indexers with book content).
|
||||
2. Add qBittorrent as the download client with the `books` category.
|
||||
3. Set author profile (format preference: epub, mobi, etc.).
|
||||
4. Set quality profile for audiobooks (320 kbps MP3, 128 kbps, lossless).
|
||||
5. Set root folder to `/books`.
|
||||
6. Add authors and verify downloads.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Readarr is in development (~v0.2.x). Some features may be incomplete.
|
||||
- Calibre integration is folder-based, not API-based. Readarr drops files into `/books` which Calibre-Web serves.
|
||||
- Not all indexers have all formats (epub, mobi, pdf). Goodreads/StoryGraph metadata helps match editions.
|
||||
|
||||
## See Also
|
||||
|
||||
- [[ARR-Stack]] — full *arr stack documentation
|
||||
- [[Calibre-Web]] — ebook web frontend that serves Readarr downloads
|
||||
@@ -0,0 +1,40 @@
|
||||
# Redis (RomM Cache / Queue)
|
||||
|
||||
Redis 7 provides the caching and task queue backend for RomM on Dankserver. RomM 5.2.0 requires Redis (or Valkey) for its task queue.
|
||||
|
||||
**Host:** Dankserver — **Docs:** https://redis.io/docs/
|
||||
|
||||
## Facts
|
||||
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| Image | `docker.io/redis:7-alpine` |
|
||||
| Port | 6379 (internal, within `appnet`) |
|
||||
| Data volume | `/opt/romm/redis` |
|
||||
| Auth | None (local-only, no password needed) |
|
||||
|
||||
## Docker Compose
|
||||
|
||||
```yaml
|
||||
redis:
|
||||
image: docker.io/redis:7-alpine
|
||||
container_name: romm-redis
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /opt/romm/redis:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
```
|
||||
|
||||
## Backup
|
||||
|
||||
```bash
|
||||
sudo rsync -a /opt/romm/redis /mnt/backup/romm-redis/
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
- [[RomM]] — service that uses this cache
|
||||
@@ -0,0 +1,55 @@
|
||||
# Sonarr
|
||||
|
||||
Sonarr manages TV shows in the *arr stack on Dankserver. It automatically searches, downloads, and organizes episodes from indexers into the Jellyfin media library.
|
||||
|
||||
**Host:** Dankserver — **Hostname:** `sonarr.dankserver.local` — **Docs:** https://wiki.servarr.com/sonarr
|
||||
|
||||
## Facts
|
||||
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| Image | `lscr.io/linuxserver/sonarr:latest` (v4 stable) |
|
||||
| Port | 8989 (host) → 8989 (container) |
|
||||
| Min RAM | 512 MB |
|
||||
| Metadata | TMDB / TVDB |
|
||||
|
||||
## Docker Compose
|
||||
|
||||
```yaml
|
||||
sonarr:
|
||||
image: lscr.io/linuxserver/sonarr:latest
|
||||
container_name: sonarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/sonarr/config:/config
|
||||
- /mnt/media/tv:/tv
|
||||
- /mnt/media/downloads:/downloads
|
||||
ports:
|
||||
- "8989:8989"
|
||||
networks: [appnet]
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
1. Add Prowlarr as the indexer source.
|
||||
2. Add qBittorrent as the download client with the `tv` category.
|
||||
3. Set quality profile, cutoff, and minimum/maximum episode sizes.
|
||||
4. Set root folder to `/tv`.
|
||||
5. Add series and verify downloads.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Sonarr v4 is the current stable. The v3 branch uses the `:v3` tag.
|
||||
- Anime has different quality profiles and naming conventions than Standard series.
|
||||
- Missing episodes: set "Unmonitor Missing Episodes" to auto-unmonitor old episodes.
|
||||
- Timezone-sensitive scheduler: ensure all containers use the same TZ.
|
||||
|
||||
## See Also
|
||||
|
||||
- [[ARR-Stack]] — full *arr stack documentation
|
||||
- [[Jellyfin]] — media server that consumes Sonarr downloads
|
||||
@@ -26,9 +26,20 @@ This repository tracks the container stacks for both hosts. Git is the single so
|
||||
## Dankserver Services
|
||||
|
||||
- [[RomM]] — retro game manager
|
||||
- [[RomM-Scraping]] — metadata providers, cover art, naming conventions
|
||||
- [[Copyparty]] — file sharing and streaming
|
||||
- [[Jellyfin]] — media server (movies, TV, music)
|
||||
- [[Calibre]] — e-book library engine
|
||||
- [[Calibre-Web]] — e-book web frontend
|
||||
- [[ARR-Stack]] — automated media download overview
|
||||
- [[sonarr]] — TV show management
|
||||
- [[radarr]] — movie management
|
||||
- [[lidarr]] — music management
|
||||
- [[readarr]] — ebook/audiobook management
|
||||
- [[prowlarr]] — indexer management
|
||||
- [[qbittorrent]] — torrent download client
|
||||
- [[mariadb]] — RomM database backend
|
||||
- [[redis]] — RomM cache/queue backend
|
||||
|
||||
## Dankclaw Services
|
||||
|
||||
@@ -59,6 +70,8 @@ This repository tracks the container stacks for both hosts. Git is the single so
|
||||
- [[ComfyUI ROCm and Vulkan]] — live-verified GPU path for ComfyUI on Strix Halo
|
||||
- [[Lemonade and sd.cpp]] — the ggml-family image-generation alternative
|
||||
- [[Backblaze Integration]] — off-site backup plan (future)
|
||||
- [[Jellyfin]] — media server research brief
|
||||
- [[ARR-Stack]] — automated download stack research brief
|
||||
|
||||
## See Also
|
||||
|
||||
|
||||
Reference in New Issue
Block a user