Plex baseline · Mac
Get the consumer surface working
Plex on a Mac with library pointed at empty folders. The consumption surface comes first, without a working Plex, nothing else has anywhere to feed.
A private streaming service and a photo backup that live on my own hardware. Family asks for a movie; it appears in the living room an hour later, no streaming-service hopping required.
A small home server that does two things. One: replaces the streaming-service shuffle with a single Plex library that pulls in whatever the family asks for. Two: replaces Google Photos with a photo backup that lives on my hardware, not someone else's cloud, and that I can reach from anywhere via a private VPN.
Households tired of paying four streaming subscriptions to watch three shows, and anyone uneasy about a single company holding their entire photo history. This isn't an AI project, but it's the same operator pattern: chain best-in-class open-source tools together so the household never sees the plumbing.
Plex on a Mac with library pointed at empty folders. The consumption surface comes first, without a working Plex, nothing else has anywhere to feed.
All three deployed via Docker Compose on the UGREEN
NAS. Each gets its own port and root folder
(/movies, /tv). qBittorrent
gets credentials and a download category mapping so
Radarr and Sonarr don't step on each other.
Overseerr on port 5055 talks to Radarr, Sonarr, and Plex via API keys. The end-user surface is "search → request", they never see the *arr UIs, never touch a torrent client, never rename a file.
Tailscale on the NAS as ugreen-nas. All
services reachable from any device on my Tailnet
without opening a single port to the internet.
iPhone gets full home-network access remotely;
security model stays tight.
Compose deployed at :2283. Plan: iPhone
app for automatic backup, Google Takeout dump as an
External Library (no duplication), eventual full
Google Photos exit.
I wanted to leave Google Photos and stop renting media from streaming services that lose titles every quarter. The requirements: request → automatic download → in Plex with metadata, no terminal touches; photo backup from iPhone with the Google Photos UX but on my hardware; remote access from outside the house without exposing anything to the public internet.
This isn't an AI project per se, but it's the same operator pattern as everything else I build: chain together best-in-class open-source pieces, keep them inspectable, automate the boring work, and only pay for the thin layer that makes them feel cohesive.
The user surface is exactly one tap. Open Overseerr (locally or via Tailscale), search for a movie or show, hit Request. Behind the scenes:
Overseerr (request)
↓
Radarr / Sonarr (find + queue)
↓
qBittorrent (download)
↓
Radarr / Sonarr (rename + move to /movies or /tv)
↓
Plex (auto-scan + metadata)
↓
You watch it on the TV.
Plex on a Mac at 192.168.4.53, library pointed
at empty folders on the NAS. The consumption surface comes
first, without a working Plex, the rest of the stack has
nothing to feed.
All three deployed via Docker Compose on the UGREEN NAS.
Each gets its own port and its own root folder
(/movies, /tv). qBittorrent
gets credentials and a download category mapping so
Radarr and Sonarr can hand work off without stepping
on each other.
Overseerr on port 5055 talks to Radarr, Sonarr, and Plex via API keys. End-user surface is "search → request" , they never see the *arr UIs, never touch a torrent client, never rename a file.
Tailscale on the NAS as ugreen-nas. Now
all services are reachable from any device on my Tailnet
without opening a single port to the internet. iPhone
gets full home-network access remotely. Security model
stays tight.
Compose deployed at :2283. Plan: iPhone app
for automatic backup, Google Takeout dump added as an
External Library (no duplication), eventual full Google
Photos exit.
I tried to mount a volume from /home/ShadoWing1128/Photos for Immich. Container couldn't see it, UGREEN's Docker can't access personal user home folders.
All Docker volume mounts must use /volume1/ paths. Corrected Immich's upload path to /volume1/Photos/Immich. Lesson: every NAS vendor has its own Docker filesystem quirks; check before assuming Linux conventions hold.
Spent 20 minutes looking for the Plex media-deletion toggle under Settings → Troubleshooting (where it used to be).
In newer Plex versions the toggle moved to Settings → Library. Wrote it down in the project notes so it doesn't bite me again, and so the same thing doesn't slow down anyone else trying to stand up a similar stack.
The native iPhone OverseerrTV app couldn't connect to my server, wanted an API key I didn't know existed.
Pulled the key from Overseerr's Settings → General → API Key, then connected. Now I can request from my phone like any streaming app. The lesson: every self-hosted service has at least one "obvious in retrospect" config step that isn't in the README.
Overseerr threw a yellow Language Profile deprecation warning every time I requested a TV show. Looked like a real failure.
Pure cosmetic, Sonarr removed Language Profiles in a recent version, Overseerr hasn't caught up. Ignored. The lesson: not every red-or-yellow string is a real problem; treat warnings as data, not commands.
Verify http://192.168.4.61:2283 is up after the /volume1/ path fix. Install iPhone app, enable automatic backup.
Add the historical Google Photos dump to Immich as an External Library, no duplication, no re-import, just indexed.
Caddy or Traefik in front of the stack. Replace bare IPs and ports with plex.home.lan, overseerr.home.lan, etc. Nicer URLs, free TLS, easier to share with family.
Encrypted Backblaze B2 nightly snapshot of /volume1/Photos. Belt-and-suspenders for the irreplaceable data.
Same Docker host, same Tailscale exit. Smart-home control rolls into the same operator surface.
An Ollama container on the NAS for always-on local inference, queryable from any device on the Tailnet.