On a host that has never run the service, the mounted data volume is
empty. Ownership was being corrected for a subdirectory that did not
exist yet, which aborted the entrypoint before the application started
— exactly the situation a fresh deployment creates, and the reason the
container came up on the existing Pi but would not have elsewhere.
Creating the directory has to happen at runtime rather than during the
build, because the volume mount hides whatever the image places there.
Instagram and TikTok extraction silently breaks whenever yt-dlp falls
behind upstream API changes, and fixing it required a manual image
rebuild each time. Updating at container start ties the fix to the Pi's
weekly reboot instead, so the extractor stays current without operator
intervention. A failed update never blocks startup, because the network
may not be up yet right after boot.
.gitattributes pins LF for shell scripts: a CRLF checkout on Windows
would make the entrypoint unrunnable inside the Linux container.
Claude-Session: https://claude.ai/code/session_01QkiLqAtFamcbFXDnCtZSPm