NAS Docker Audit: 23 Containers to 10

claude-codesynologydockerhomelab

NAS Docker Audit: 23 Containers to 10

This session was supposed to take five minutes. Check if Seerr was running on the Synology NAS, restart it if not, move on. Three hours later I’d audited every Docker container, cut the stack in half, deobfuscated NZB downloads, organized TV show libraries, and rewritten four documentation files.


It Started with Seerr

Seerr (the Overseerr replacement) was down at :5055. Quick SSH in, docker start seerr, verified the web UI loaded. Done. Should have stopped there.

But I noticed SABnzbd had some weird-looking downloads for Invincible Season 4.

The Deobfuscation Detour

SABnzbd had downloaded episodes E01 through E05, but every file was hash-named — a8f3e2d1b4c7 instead of Invincible.S04E01.mkv. This is NZB obfuscation: uploaders hash filenames to avoid DMCA bots. SABnzbd is supposed to rename them automatically. It hadn’t.

The fix was manual but methodical: find the largest file in each episode folder (it’s the video), verify the Matroska magic bytes (1a45 dfa3), rename to .mkv, delete the par2/nfo junk, flatten the subfolder. Did this for E01-E05 and added E08 which had landed in the meantime.

Then I added Invincible to Sonarr (it wasn’t being tracked), fixed a path mismatch between TVDB’s title casing and the filesystem, and triggered searches for E06 and E07.

Twin Peaks Gets Organized

While I was in the media library, Twin Peaks was a mess — all episodes dumped in a flat directory. Created Season 01/02/03 subfolders, moved everything, triggered Sonarr searches for missing episodes. Season 2 found 758 releases. The d3g BluRay release group was consistently reliable while other groups kept failing quality checks.

The Real Discovery: Everything Is Broken

Checking container logs to figure out why Seerr had stopped led to the actual finding. Every container on the NAS had restart: no (Docker’s default). Synology’s auto-start mechanism — SYNO.Docker.Container_1_start — was returning error 500 with “Resource temporarily unavailable” and not retrying. So after any reboot or memory pressure event, containers just stayed down.

Exit codes told the rest of the story:

  • Several containers had exit code 137 (SIGKILL) — the kernel OOM killer or Synology’s resource manager was terminating them
  • Others had exit code 143 (SIGTERM) — clean shutdowns from DSM
  • The NAS has 3.7 GB usable RAM and was using 1.9 GB of swap with 23 containers running

This was a swap death spiral. Every container start triggered page faults, which stalled other containers, which got killed, which freed memory temporarily, which let other containers start, which consumed memory again.

The Purge

I went through every container and asked one question: does this justify its memory footprint on a 4 GB box?

Cut (13 containers):

  • Whisparr — unused
  • Tautulli — Plex analytics I never actually look at
  • Homepage — replaced by bythewei.dev
  • nas-node-exporter + 6 exportarrs — monitoring overhead exceeded the value of the metrics
  • libraryofbabel-grafana + libraryofbabel-prometheus — monitoring stack moved to the Mac mini
  • synology_docviewer x2 — Synology system containers, not needed

Kept (10 containers): Sonarr, Prowlarr, Readarr, SABnzbd, Seerr, Recyclarr, Calibre-Web, Komga, Kavita, Audiobookshelf

Results: memory usage dropped from 2.4 GB to 1.8 GB. Available memory jumped from 839 MB to 1.6 GB. Swap dropped to near zero.

The Over-Correction

I accidentally removed the four ebook services (Calibre-Web, Komga, Kavita, Audiobookshelf) during the cleanup. Had to recreate them from the existing docker-compose files and config volumes, which were thankfully still intact on disk. Lesson: audit before you purge, not during.

Set restart: unless-stopped on Everything

Applied restart: unless-stopped to all 10 remaining containers. This operates at the Docker daemon level, completely bypassing Synology’s broken API. The daemon handles retries and backoff natively. DSM’s auto-start becomes irrelevant.

Docs Overhaul

Updated everything to reflect the new 10-container state:

  • README.md — container inventory, ports, architecture
  • KANBAN.md — current sprint status
  • prometheus.yml — removed scrape targets for dead exportarrs
  • ports.yml — cleaned up port assignments
  • Memory files for cross-session context

What Shipped

  • Seerr back online
  • Invincible S04 E01-E05, E08 deobfuscated and properly named
  • Invincible added to Sonarr, E06/E07 searches triggered
  • Twin Peaks organized into seasons, missing episodes searching
  • Container count: 23 to 10
  • Memory reclaimed: ~800 MB
  • All containers: restart: unless-stopped
  • Four documentation files updated

The scope creep counter resets to zero. Again. A five-minute Seerr check became a full infrastructure audit. But the NAS is healthier than it’s been in months, and the next reboot won’t leave everything silently dead.