nightowl logo
PROJECT 001 Running at home

nightowl

A self-hosted family movie server. Jellyfin in containers, private remote access for relatives over Tailscale, and no router ports opened by default.

Role
Design, build, documentation
Started
October 2026
Stack
Jellyfin · Docker Compose · Tailscale
Host
Windows PC (WSL2) today, NAS next
Architecture

How it fits together

ClientsHome + family
TVs and phones At home, the official Jellyfin apps on Roku, Fire TV and Google TV. Relatives use a Google TV or Fire TV stick with Tailscale. → LAN, or a WireGuard tunnel
Network0 router ports
Tailscale sidecar Connects out, so it works behind CGNAT. Each relative's own account gets a share of one tagged node, which answers only on the Jellyfin port (plus HTTPS with the domain add-on). → jellyfin:8096
HostDocker Compose
One stack, opt-in add-ons
jellyfincore backupcore tailscaleopt-in proxyopt-in
→ media mounted read-only
StorageHost disks
Media and config Media is read-only to Jellyfin. The config is snapshotted every 24 hours to a separate backup folder, keeping the newest 7.
Fig. 1 · Request path, left to rightHardware transcoding (NVIDIA or Intel) is a per-host add-on
By the numbers

Small footprint, written down

0router ports opened by default
9architecture decision records
7config backups kept, one every 24 hours
~90 sto rehearse an upgrade and roll it back, once the images are pulled

Defaults and measurements from the project's docs, October 2026. Faster direct connections are an opt-in: they open one UDP port on the router.

Design choices

Decisions and trade-offs

ADR 0004

A Tailscale sidecar, not port forwarding

Remote access runs in its own container with userspace networking, so the host never joins the tailnet. Relatives accept a share from their own free account; nobody is invited into the owner's network.

TRADE-OFFEvery remote device needs Tailscale, so a TV without it needs a streaming stick.
ADR 0003

Backups without stopping Jellyfin

Each database is copied with SQLite's online backup and must pass an integrity check before it is archived. No Docker socket, no stop window.

TRADE-OFFConfig only: no media, no encryption, no off-site copy yet.
ADR 0009

Pinned images, upgraded by a person

Dependabot proposes bumps and a weekly job files an issue for each new Jellyfin advisory, but a person merges every image bump. Rollback means restore, then re-pin.

TRADE-OFFA few minutes of manual work per upgrade.
Timeline

From an empty repo to the living room

  1. Guardrails firstPersonal-info and secret checks, an issue board, and a design review of every issue (a council of AI role agents) before any server code.
  2. Baseline to remote accessJellyfin on the LAN, hardware transcoding, config backups and the Tailscale sidecar. First tests on the real host, at home and remotely.
  3. Household setupProfiles and parental controls, a branded Jellyfin, an intro before movies, and live TV support for an antenna tuner (still to be tested on real hardware).
  4. Private HTTPSA custom domain that points at the server's tailnet address, so it only works on the tailnet. Certificates come from a DNS challenge, with no inbound port.
  5. First security upgradeJellyfin moved to 12.x to close open advisories, using the rehearsed upgrade path.
  6. Now
    Running at homeOn a Windows PC for the proof of concept. Next: a tested move to a NAS.