373 lines
22 KiB
Markdown
373 lines
22 KiB
Markdown
|
|
# 13 — Optimization Audit (Read-Only)
|
|||
|
|
|
|||
|
|
> Status: **read-only audit**, executed 2026-05-08 against
|
|||
|
|
> `https://arrflix.s8n.ru` (Jellyfin 10.10.3 on nullstone). Scope: scan
|
|||
|
|
> for performance, capacity, reliability, and ops-hygiene risks. **No
|
|||
|
|
> fixes applied. No state mutated. No container restarts.**
|
|||
|
|
|
|||
|
|
Audit ran ~25 minutes wall. Inputs: Jellyfin REST API (auth
|
|||
|
|
`X-Emby-Token: 76858153…f8b1`), `docker exec jellyfin`, `docker logs
|
|||
|
|
{traefik,jellyfin} --since 1h/6h/24h`, host `free`, `df`, `uptime`,
|
|||
|
|
`nvidia-smi`, on-disk Jellyfin XML configs.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Executive summary
|
|||
|
|
|
|||
|
|
1. **Host is under serious memory pressure right now.** `uptime` shows
|
|||
|
|
load average **11.40 / 9.59 / 6.19** on a 12-core box, **6.8 GiB of
|
|||
|
|
swap is in use** (out of 24 GiB), and `/home` is **90 % full
|
|||
|
|
(40 GiB free of 399 GiB)**. Jellyfin itself is fine
|
|||
|
|
(522 MiB / 31 GiB cap, no restarts), but the host it lives on is
|
|||
|
|
loaded enough that any media ingest at scale will start swap-thrashing.
|
|||
|
|
This is the single biggest risk to playback latency.
|
|||
|
|
2. **GPU transcode is dead and confirmed dead.** `nvidia-smi` fails on
|
|||
|
|
host, `lsmod | grep nvidia` returns empty, `/dev/nvidia*` does not
|
|||
|
|
exist. `EnableHardwareEncoding=true` and `HardwareAccelerationType=none`
|
|||
|
|
in `encoding.xml` is harmless but misleading — the toggle is on, but
|
|||
|
|
the type selector is `none`, so every transcode goes through ffmpeg
|
|||
|
|
software path. Two HLS segment requests this hour returned **499**
|
|||
|
|
(client cancelled mid-transcode at 6.4 s and 2.9 s wall) — that is
|
|||
|
|
the playback-stalls signature.
|
|||
|
|
3. **OpenSubtitles plugin is logging an error per file probed during
|
|||
|
|
library scan** (102 errors in last 6 h) because `Username` and
|
|||
|
|
`Password` are empty in the plugin XML. Every Scan Media Library run
|
|||
|
|
tries Open Subtitles, fails on auth, logs an `ERR`, retries on the
|
|||
|
|
next file. This is pure log noise + wasted RTT, not data loss, but
|
|||
|
|
it bloats `/config/log` and obscures real warnings.
|
|||
|
|
4. **Transcode throttling is OFF and `MaxMuxingQueueSize` is 2048** —
|
|||
|
|
on a CPU-only deploy that means a stalled client with high-bitrate
|
|||
|
|
AV1/HEVC source will keep ffmpeg burning a full core for up to
|
|||
|
|
`SegmentKeepSeconds=720`s after the client gives up. `EnableThrottling`
|
|||
|
|
should be on for a CPU deploy; this would have prevented the 499s
|
|||
|
|
seen above.
|
|||
|
|
5. **No automated backup of `/home/docker/jellyfin/config/`.** The
|
|||
|
|
Cineplex CSS, the 5 user accounts + permissions, the library
|
|||
|
|
metadata, and the Open Subtitles plugin install all live in one
|
|||
|
|
unprotected directory tree. The repo's `snapshots/` only captures the
|
|||
|
|
pre-ElegantFin migration baseline; nothing on disk is being rotated
|
|||
|
|
off-host.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Findings table
|
|||
|
|
|
|||
|
|
Severity legend: **R** = red (acute, fix this week), **Y** = yellow
|
|||
|
|
(deferred fix, document risk), **G** = green (audited, healthy, no
|
|||
|
|
action). Effort: **S** ≤ 30 min, **M** half-day, **L** > 1 day.
|
|||
|
|
|
|||
|
|
| # | Category | Severity | Evidence | Recommendation | Effort |
|
|||
|
|
|---|---|:-:|---|---|:-:|
|
|||
|
|
| 01 | Host capacity | **R** | `uptime` load 11.40 / 9.59 / 6.19 on 12 cores; swap 6.8 GiB used / 24 GiB; `/home` 90 % full | Identify swap hog (likely not Jellyfin — only 522 MiB RSS); reclaim space on `/home`; budget media additions against the 40 GiB headroom | M |
|
|||
|
|
| 02 | GPU transcode | **R** | `nvidia-smi` fails, no `/dev/nvidia*`, `lsmod` no nvidia mod; `HardwareAccelerationType=none` | Reinstall nvidia driver on nullstone host; once `nvidia-smi` works, add device reservation block to compose and flip `HardwareAccelerationType` to `nvenc` | L |
|
|||
|
|
| 03 | Transcode throttling | **R** | `EnableThrottling=false`, `ThrottleDelaySeconds=180`, `MaxMuxingQueueSize=2048`, **two 499 client-cancels** logged (6 439 ms / 2 890 ms) | Enable `EnableThrottling=true` and `EnableSegmentDeletion=true` for CPU-only era — caps wasted ffmpeg CPU after client disconnect | S |
|
|||
|
|
| 04 | OpenSubtitles auth | **R** | `Username`/`Password` empty in `Jellyfin.Plugin.OpenSubtitles.xml`; **102** `Error downloading subtitles from Open Subtitles` lines / 6 h | Set creds via UI, OR disable the provider on both libraries (`EnableInternetProviders=false` already; subtitle search still runs). Doc 03-subtitles.md already calls this out as pending | S |
|
|||
|
|
| 05 | Cache trash budget | **Y** | `EnableSegmentDeletion=false`, `SegmentKeepSeconds=720`; `/cache/transcodes` only 20 K right now (no live stream), but a 4K HEVC→h264 session will fill GiBs and not auto-prune | Enable `EnableSegmentDeletion=true` (default 720 s keep is fine) — pairs with finding 03 | S |
|
|||
|
|
| 06 | Backup posture | **R** | `/home/docker/jellyfin/config/` (104 MB) has no off-host rotation; `snapshots/` in repo only holds pre-ElegantFin baseline | Add a weekly `tar.zst` of `/config/` (excluding `log/`, `cache/`) to NAS or git-backed snapshot dir | M |
|
|||
|
|
| 07 | Disk pressure | **Y** | `/home` 90 % full, 40 GiB free of 399 GiB; `/home/user/media` only 189 files | Cap on media growth: at current free space + episode bitrate budget user has ~3–4 more series before disk fills | M |
|
|||
|
|
| 08 | DB WAL ratio | **Y** | `library.db`=3.3 MB, `library.db-wal`=4.4 MB (WAL > main, uncheckpointed). `Optimize database` last ran 2026-05-08T00:58 (OK) but a fresh scan completed 03:16 left WAL fat | Either trigger a manual `Optimize database` post-scan, or shorten its schedule to "after every full scan". WAL > main is normal during/after a scan but should checkpoint on idle | S |
|
|||
|
|
| 09 | Custom CSS bloat | **Y** | `CustomCss` in `branding.xml` is **25 225 bytes**, 17 `!important`, sole `@import` is `MRunkehl/cineplex@v1.0.6` (jsDelivr) | jsDelivr import adds 1 round-trip + ~50 KB on every cold cache load. Inline the import for offline-resilience and one-fewer DNS hop. Also doc 11 already flags this as the wrong theme (Cineplex, not NeutralFin) — resolve theme race first | M |
|
|||
|
|
| 10 | SPA shim cost | **G** | `web-overrides/index.html` 58 KB; runs **2× MutationObserver** + **1× setInterval(1000ms)** with `lockTitle/lockFavicon/nukeSettings`; cost ~1 ms per tick | Acceptable for a single-tab branding shim; would be a problem only on background tabs at scale. No action | — |
|
|||
|
|
| 11 | Service worker | **G** | `/web/serviceworker.js` 768 bytes, last modified 2024-11-19 (Jellyfin 10.10.3 ship date), serves with `cache-control: no-store` (HTTPS, etag set). Notification-only SW (per doc 10) | No action — it is small and not caching `index.html` so cannot pin stale branding | — |
|
|||
|
|
| 12 | Metrics endpoint | **G** | `EnableMetrics=false` | Off is correct for a single-server box. No action | — |
|
|||
|
|
| 13 | Slow-response warning | **Y** | `EnableSlowResponseWarning=true`, threshold **500 ms**. Two transcoding 499s above 2.8 s would normally trigger this warning, but I see 0 `slow` lines in 1 h logs | Either Jellyfin's slow log only fires on synchronous request handlers (not HLS segment GETs), or warning suppressed by another setting. Worth confirming threshold semantics | S |
|
|||
|
|
| 14 | Library scan concurrency | **Y** | `LibraryScanFanoutConcurrency=0`, `LibraryMetadataRefreshConcurrency=0`, `ParallelImageEncodingLimit=0` (all defaults — auto = `ProcessorCount`) | On a 12-core box already at load 11+, `0` (= 12) for all three is aggressive. Cap each at 4–6 to leave headroom for Forgejo/Traefik/etc | S |
|
|||
|
|
| 15 | Realtime monitor | **Y** | Both libraries have `EnableRealtimeMonitor=true`; only 189 files; `LibraryMonitorDelay=60` | Fine for current size, but inotify watches grow with file count. Re-evaluate at 10 k+ files | — |
|
|||
|
|
| 16 | Trickplay / chapter previews | **G** | `EnableTrickplayImageExtraction=false`, `ExtractChapterImagesDuringLibraryScan=false`, `EnableChapterImageExtraction=false`, `ExtractTrickplayImagesDuringLibraryScan=false` (all libs) | Disabled on both libraries — saves significant CPU. No action. (Note: scheduled task `Generate Trickplay Images` still ran 02:00 — check it is a no-op when libs say no) | — |
|
|||
|
|
| 17 | Photos library | **G** | `EnablePhotos=false` on both | Correct for a movies/TV deploy. No action | — |
|
|||
|
|
| 18 | Plugin set | **G** | 6 plugins active (AudioDB, MusicBrainz, OMDb, OpenSubtitles, StudioImages, TMDb). `Username/Password` empty for OMDb (= no key, falls back to anon rate limit) and TMDb (`TmdbApiKey` empty — falls back to bundled key) | Both tolerated. AudioDB + MusicBrainz unused (no music libs) but cost zero idle. Consider removing for minimalism, not perf | — |
|
|||
|
|
| 19 | Admin user policy | **R** | `s8n` admin has `EnableRemoteControlOfOtherUsers=true`, `EnableContentDeletion=true` (correct for admin) but **also `IsHidden=true`** | Hidden admin is non-standard; usually a hidden admin is reserved for automation. If `s8n` is the operator's daily account, `IsHidden=false` is the convention. Low risk, just unusual | S |
|
|||
|
|
| 20 | Non-admin policies | **Y** | All 4 non-admin users (`5`, `guest`, `house`, `marco`) have `EnableContentDownloading=true`, `EnableMediaConversion=true`, `EnableLiveTvManagement=true`, `EnableSharedDeviceControl=true`, `IsHidden=true` | LiveTvManagement on accounts with no Live TV is dead weight, no harm. ContentDownloading + MediaConversion let any user kick off transcodes — a foot-gun on a CPU-only host. Review desired stance | S |
|
|||
|
|
| 21 | Login disclaimer leak | **G** | `LoginDisclaimer` = "Welcome to ARRFLIX - Private invite only service" | Public-facing string is intentional per doc 09. No action | — |
|
|||
|
|
| 22 | Public WAN exposure | **Y** | `EnableRemoteAccess=true`, `no-guest@file` middleware **dropped** in compose (per doc 09 §1.2). 24 h log: 270 LAN reqs, **59 reqs from 157.143.84.87, 1 from 82.31.156.86** | Doc 09 confirms this is intentional. The 157.143.84.87 hits are bot-style asset-prober 404s — harmless but confirms the service is internet-reachable. No action; re-verify rate limit / fail2ban once router port-forward is active | — |
|
|||
|
|
| 23 | Splashscreen size | **Y** | `/config/data/splashscreen.png` is **3.0 MB** | A splash image of 3 MB is large for a PNG; lossless re-encode or downscale to ≤500 KB; saves on first-paint over WAN | S |
|
|||
|
|
| 24 | Log rotation | **G** | `LogFileRetentionDays=3`; `/config/log` 1.3 MB; rotation working | No action | — |
|
|||
|
|
| 25 | Splashscreen flag | **Y** | `SplashscreenEnabled=true` in `branding.xml` | Intentional for branding, no action — pairs with finding 23 (just shrink the file) | — |
|
|||
|
|
| 26 | Cache breakdown | **G** | `/cache/images` 15 MB (entire cache 15 MB); `/config/metadata` 92 MB; `/config/data` 12 MB; `/config/plugins` 128 KB | Healthy small footprint. No action | — |
|
|||
|
|
| 27 | Forgejo log noise | **Y** | Traefik logs show `forgejo@docker` returning **401** for `s8n/ARRFLIX.git/info/refs?service=git-receive-pack` 8× / hour from 192.168.0.10 | Out of scope for this deploy but indicates a stale `git push` retry loop on onyx — surfaces here only because we're scanning traefik logs. Mention to operator separately | — |
|
|||
|
|
| 28 | Path substitutions | **G** | `system.xml` empty `<PathSubstitutions />` and `<CorsHosts />` | Correct (no NFS/SMB indirection, no cross-origin clients). No action | — |
|
|||
|
|
| 29 | LiveTV residue | **G** | `DisableLiveTvChannelUserDataName=true`; no Live TV configured; per-user `EnableLiveTvAccess=true` is dead weight | Cosmetic; no perf cost. No action | — |
|
|||
|
|
| 30 | Container restart count | **G** | `docker inspect` `RestartCount=0`, `Status=running`, `StartedAt=2026-05-08T02:13:01` (~2 h uptime, healthy) | No action. (Boot was at 02:13, suggests the compose was applied for doc-09 WAN flip and ran clean since) | — |
|
|||
|
|
| 31 | Network XML hygiene | **Y** | `KnownProxies` empty, `LocalNetworkSubnets` empty, `LocalNetworkAddresses` empty | Jellyfin can't tell the Traefik 172.20.0.0/16 docker net from random WAN — every external IP is logged as remote, which inflates Jellyfin's geoIP/session bookkeeping. Set `KnownProxies=172.20.0.0/16` and `LocalNetworkSubnets=192.168.0.0/24` | S |
|
|||
|
|
| 32 | TLS cert | **G** | LE cert valid `2026-05-08 → 2026-08-06` (89 days remaining), issued by R13, Gandi DNS-01 resolver, in `acme.json` | Healthy. No action | — |
|
|||
|
|
| 33 | Request-rate posture | **G** | 81 req / hour total via traefik; 62 of those are `jellyfin@docker`. Top src 192.168.0.10 (LAN, the operator), then 157.143.84.87 (asset-prober 404s) | Low rate. No action — re-evaluate if WAN exposure draws more traffic | — |
|
|||
|
|
| 34 | Idle session count | **G** | `/Sessions` returns 2 idle (s8n + guest) on 192.168.0.10; no playback in flight at audit time | No action | — |
|
|||
|
|
| 35 | Item counts | **G** | 2 movies, 6 series, 169 episodes; matches `find /media -type f` (189 files, accounting for non-video extras) | Library scan is healthy; counts converged | — |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Recommended fix order (top 5 by impact-per-effort)
|
|||
|
|
|
|||
|
|
1. **Finding 03 — enable transcode throttling + segment deletion.**
|
|||
|
|
*Effort: S (two checkboxes in Playback settings).* Closes the
|
|||
|
|
highest-cost behaviour we have evidence of (the 499 ms wall events).
|
|||
|
|
Saves CPU cycles per stalled client.
|
|||
|
|
2. **Finding 04 — set OpenSubtitles credentials, OR disable
|
|||
|
|
provider.** *Effort: S.* Removes 102 ERR/6 h of log spam, fixes
|
|||
|
|
subtitle download, immediately restores log signal.
|
|||
|
|
3. **Finding 31 — populate `KnownProxies` + `LocalNetworkSubnets` in
|
|||
|
|
`network.xml`.** *Effort: S.* Restores accurate session origin
|
|||
|
|
reporting; needed before any rate-limiting or fail2ban work post-WAN.
|
|||
|
|
4. **Finding 14 — cap `LibraryScanFanoutConcurrency`,
|
|||
|
|
`LibraryMetadataRefreshConcurrency`, `ParallelImageEncodingLimit`
|
|||
|
|
to 4–6.** *Effort: S.* Stops a future scan piling on top of the
|
|||
|
|
existing host load (currently 11.4).
|
|||
|
|
5. **Finding 06 — automate `/config/` backup.** *Effort: M.* Single
|
|||
|
|
highest-blast-radius risk: a corrupt `library.db` or a `branding.xml`
|
|||
|
|
regression and you've lost the user accounts AND the theme work in
|
|||
|
|
one go. A weekly `tar.zst` to NAS closes this.
|
|||
|
|
|
|||
|
|
GPU re-enable (finding 02) would unlock more wins but is **L** effort
|
|||
|
|
and lives outside Jellyfin (host driver work). Throttling (#03) is the
|
|||
|
|
right CPU-era patch until then.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Out of scope (audited and found healthy)
|
|||
|
|
|
|||
|
|
- **Service worker** (`/web/serviceworker.js`, 768 B, notification-only,
|
|||
|
|
not caching index.html — finding 11).
|
|||
|
|
- **Container restart count** (0 — finding 30).
|
|||
|
|
- **TLS cert chain** (89 days valid — finding 32).
|
|||
|
|
- **Trickplay / chapter / photo extraction** (all disabled — findings
|
|||
|
|
16, 17).
|
|||
|
|
- **Log rotation** (3-day retention working, 1.3 MB /config/log —
|
|||
|
|
finding 24).
|
|||
|
|
- **Cache directory growth** (15 MB total, healthy — finding 26).
|
|||
|
|
- **Plugin set** (6 plugins, all idle-cheap — finding 18).
|
|||
|
|
- **Idle session footprint** (2 idle web sessions, no playback in
|
|||
|
|
flight — finding 34).
|
|||
|
|
- **Item count convergence** (Items/Counts matches filesystem —
|
|||
|
|
finding 35).
|
|||
|
|
- **Path substitution / CORS hygiene** (empty as expected — finding 28).
|
|||
|
|
- **Login disclaimer string** (per-doc-09 intentional public-facing
|
|||
|
|
text — finding 21).
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Appendix — raw evidence
|
|||
|
|
|
|||
|
|
### Host
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
uptime: 04:18:55 up 4 days, 4:36, 3 users, load average: 11.40, 9.59, 6.19
|
|||
|
|
nproc: 12
|
|||
|
|
free -h: total 31Gi, used 9.2Gi, free 5.8Gi, swap used 6.8Gi / 24Gi
|
|||
|
|
df -h /home: 399G total, 339G used, 40G avail (90 % full)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Container
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
docker stats jellyfin (no-stream):
|
|||
|
|
CPU 0.01 %, MEM 521.5 MiB / 31.27 GiB (1.63 %), PIDS 24, NET 83.8 MB / 361 MB
|
|||
|
|
docker inspect: Restarts=0, Started=2026-05-08T02:13:01Z, Status=running
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### GPU
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
nvidia-smi: NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver
|
|||
|
|
lsmod | grep nvidia: (no matches)
|
|||
|
|
ls /dev/nvidia*: No such file or directory
|
|||
|
|
encoding.xml: HardwareAccelerationType=none, EnableHardwareEncoding=true
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Disk
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
/config 104 M (data 12M, metadata 92M, log 1.3M, plugins 128K)
|
|||
|
|
/cache 15 M (images 15M, transcodes 20K, fontconfig 36K, omdb 84K)
|
|||
|
|
/home/docker/jellyfin: not visible (sudo blocked); inferred from container view
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Database
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
jellyfin.db 208 K (WAL 473 K, SHM 32 K)
|
|||
|
|
library.db 3.3 M (WAL 4.4 M, SHM 32 K) <- WAL > main
|
|||
|
|
keyframes/ 16 K
|
|||
|
|
splashscreen.png 3.0 M
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Traefik (last 1 h)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
total log lines: 279
|
|||
|
|
jellyfin@docker requests: 62
|
|||
|
|
status 499 (client cancel): 2 (HLS segments, 6439 ms + 2890 ms)
|
|||
|
|
status 5xx: 0
|
|||
|
|
top source IPs (jellyfin):
|
|||
|
|
82.31.156.86 123 (own WAN egress, hairpin)
|
|||
|
|
82.131.116.123 122 (external — likely friend / scanner)
|
|||
|
|
192.168.0.10 13 (operator LAN)
|
|||
|
|
173.244.58.11 2 (cloud scanner)
|
|||
|
|
35.203.85.72 1 (Google security scan)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Jellyfin (last 6 h)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
"Error downloading subtitles from Open Subtitles": 102
|
|||
|
|
"slow" / "throttl" matches: 1 (false positive, no real slow-warn)
|
|||
|
|
Container restart events: 0
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### TLS
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Subject: CN=arrflix.s8n.ru
|
|||
|
|
Issuer: C=US, O=Let's Encrypt, CN=R13
|
|||
|
|
Valid: 2026-05-08 00:58:11 GMT → 2026-08-06 00:58:10 GMT (89 d)
|
|||
|
|
Resolver: letsencrypt (Gandi DNS-01)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Service worker
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
URL: https://arrflix.s8n.ru/web/serviceworker.js
|
|||
|
|
HTTP: 200, content-type text/javascript
|
|||
|
|
Size: 768 bytes
|
|||
|
|
Last-Modified: Tue, 19 Nov 2024 03:43:48 GMT (Jellyfin 10.10.3 ship)
|
|||
|
|
Headers: HSTS preload + nosniff + frame=SAMEORIGIN + xss-protection
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### CSS / branding
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
/Branding/Configuration:
|
|||
|
|
CustomCss bytes: 25 225
|
|||
|
|
!important rules: 17
|
|||
|
|
sole @import: https://cdn.jsdelivr.net/gh/MRunkehl/cineplex@v1.0.6/cineplex.css
|
|||
|
|
LoginDisclaimer: "Welcome to ARRFLIX - Private invite only service"
|
|||
|
|
SplashscreenEnabled: True
|
|||
|
|
on disk:
|
|||
|
|
/config/config/branding.xml 25 584 bytes
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### SPA shim
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
/opt/docker/jellyfin/web-overrides/index.html 58 725 bytes
|
|||
|
|
MutationObserver count: 2 (one head/title-favicon, one body/nukeSettings)
|
|||
|
|
setInterval count: 1 (1000 ms — relocks title + favicon + nukeSettings)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Users
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
# users: 5
|
|||
|
|
admin (s8n): IsHidden=true, EnableRemoteControlOfOtherUsers=true, EnableContentDeletion=true
|
|||
|
|
non-admin (5, guest, house, marco): IsHidden=true, EnableContentDownloading=true,
|
|||
|
|
EnableMediaConversion=true, EnableLiveTvManagement=true
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Plugins
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
AudioDB 10.10.3.0 Active
|
|||
|
|
MusicBrainz 10.10.3.0 Active RateLimit=1, ReplaceArtistName=false
|
|||
|
|
OMDb 10.10.3.0 Active CastAndCrew=false
|
|||
|
|
Open Subtitles 20.0.0.0 Active Username/Password empty, CredentialsInvalid=false
|
|||
|
|
Studio Images 10.10.3.0 Active
|
|||
|
|
TMDb 10.10.3.0 Active TmdbApiKey empty
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Library options (both libs)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
EnableRealtimeMonitor = True
|
|||
|
|
ExtractChapterImagesDuringLibraryScan = False
|
|||
|
|
EnableTrickplayImageExtraction = False
|
|||
|
|
EnablePhotos = False
|
|||
|
|
SaveLocalMetadata = False
|
|||
|
|
EnableInternetProviders = False
|
|||
|
|
SkipSubtitlesIfAudioTrackMatches = True
|
|||
|
|
SaveSubtitlesWithMedia = True
|
|||
|
|
ExtractTrickplayImagesDuringLibraryScan= False
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Network XML
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
EnableHttps=false (TLS handled by Traefik) | EnableUPnP=false | EnableRemoteAccess=true
|
|||
|
|
KnownProxies=(empty) LocalNetworkSubnets=(empty) LocalNetworkAddresses=(empty)
|
|||
|
|
IgnoreVirtualInterfaces=true VirtualInterfaceNames=[veth]
|
|||
|
|
EnablePublishedServerUriByRequest=false
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### System config — performance knobs
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
LogFileRetentionDays = 3
|
|||
|
|
EnableMetrics = False
|
|||
|
|
EnableSlowResponseWarning = True (threshold 500 ms)
|
|||
|
|
RemoteClientBitrateLimit = 0 (no cap)
|
|||
|
|
LibraryScanFanoutConcurrency = 0 (auto = ProcessorCount = 12)
|
|||
|
|
LibraryMetadataRefreshConcurrency = 0 (auto = ProcessorCount = 12)
|
|||
|
|
ParallelImageEncodingLimit = 0 (auto = ProcessorCount = 12)
|
|||
|
|
EnableNormalizedItemByNameIds = True (correct for 10.10.x)
|
|||
|
|
QuickConnectAvailable = False
|
|||
|
|
EnableCaseSensitiveItemIds = True
|
|||
|
|
EnableFolderView = False
|
|||
|
|
EnableGroupingIntoCollections = False
|
|||
|
|
IsStartupWizardCompleted = True
|
|||
|
|
ChapterImageResolution = (default)
|
|||
|
|
DummyChapterDuration = (default)
|
|||
|
|
ImageExtractionTimeoutMs = (default)
|
|||
|
|
LibraryMonitorDelay = 60
|
|||
|
|
LibraryUpdateDuration = 30
|
|||
|
|
ActivityLogRetentionDays = (default)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Encoding config — full dump
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
EncodingThreadCount = -1 (auto)
|
|||
|
|
EnableAudioVbr = False
|
|||
|
|
MaxMuxingQueueSize = 2048
|
|||
|
|
EnableThrottling = False ← finding 03
|
|||
|
|
ThrottleDelaySeconds = 180
|
|||
|
|
EnableSegmentDeletion = False ← finding 05
|
|||
|
|
SegmentKeepSeconds = 720
|
|||
|
|
HardwareAccelerationType = none ← finding 02
|
|||
|
|
EncoderAppPathDisplay = /usr/lib/jellyfin-ffmpeg/ffmpeg
|
|||
|
|
VaapiDevice = /dev/dri/renderD128 (no Intel iGPU on host)
|
|||
|
|
H264Crf = 23
|
|||
|
|
H265Crf = 28
|
|||
|
|
EncoderPreset = (nil)
|
|||
|
|
EnableHardwareEncoding = True (no-op while type=none)
|
|||
|
|
AllowHevcEncoding = False
|
|||
|
|
AllowAv1Encoding = False
|
|||
|
|
EnableSubtitleExtraction = True
|
|||
|
|
HardwareDecodingCodecs = [h264, vc1]
|
|||
|
|
AllowOnDemandMetadataBasedKeyframeExtractionForExtensions = [mkv]
|
|||
|
|
PreferSystemNativeHwDecoder = True
|
|||
|
|
EnableEnhancedNvdecDecoder = True (no-op while no nvidia)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Scheduled tasks
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Audio Normalization Idle Completed 2026-05-08T00:58
|
|||
|
|
Clean Cache Directory Idle Completed 2026-05-08T00:58
|
|||
|
|
Clean Log Directory Idle Completed 2026-05-08T00:58
|
|||
|
|
Clean Transcode Directory Idle Completed 2026-05-08T02:13
|
|||
|
|
Download missing subtitles Idle Completed 2026-05-08T00:58
|
|||
|
|
Extract Chapter Images Idle Completed 2026-05-08T01:00
|
|||
|
|
Generate Trickplay Images Idle Completed 2026-05-08T02:00 (no-op?)
|
|||
|
|
Optimize database Idle Completed 2026-05-08T00:58
|
|||
|
|
Refresh People Idle Completed 2026-05-08T00:58
|
|||
|
|
Scan Media Library Idle Completed 2026-05-08T03:16
|
|||
|
|
Update Plugins Idle Completed 2026-05-08T02:13
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Sign-off
|
|||
|
|
|
|||
|
|
- Audit: 2026-05-08, read-only, ~25 min wall.
|
|||
|
|
- No fixes applied. No state mutated. No container restart.
|
|||
|
|
- Next audit due: **2026-08-08** (quarterly, before LE cert renewal
|
|||
|
|
window opens at 2026-08-06).
|