Skip to content

Repository files navigation

Movie Night

A tiny cinema for you and your friends, running on your own server.

CI Release License: MIT

Movie Night is a small, self-hosted watch-together service for media you own in Plex. You send your friends one link. They open it — no account, no signup, no app — and land in the room. When you press play, everyone's player follows a single authoritative server clock, so the jump scare hits all of your friends at the same moment even though every browser is playing its own independent HLS stream. There is one room, no chat (that's what your voice call is for), and no public account system.

The viewer between shows: a dark theater-style page reading "Waiting for something to start — when the room is ready, the movie will appear here"

This runs my weekly movie nights. I'd love for it to run yours. It is tested with Docker Compose on linux/amd64, Plex and Authelia behind Traefik, and current Safari, Chromium, and Firefox. Other setups probably work; please tell me what breaks.

How a movie night works

Whoever is running the night signs in through your reverse proxy and opens the projection booth. Take control, search your Plex library, start the show — three steps, designed for one person driving while everyone else is in the voice call:

The projection booth: a three-step broadcaster console for taking control, picking a title from Plex, and playing the room, with pause, resume, stop, and seek controls

Behind the scenes, Movie Night asks Plex for the media, packages one adaptive HLS ladder shared by every viewer (there is deliberately no per-viewer transcode), and publishes segments atomically so a playlist never references a half-written file. Viewers pick their own quality, audio track, and subtitles — the broadcaster never forces subtitles on anyone. Latecomers join mid-film at the right moment; reconnects and refreshes converge back to the shared clock.

Features

  • Anonymous, account-free viewing of the current room.
  • Plex-backed catalog search for authorized broadcasters.
  • Shared play, pause, resume, seek, and stop against a server-owned clock.
  • One packaged adaptive HLS ladder shared by every viewer.
  • A separate compatible Original presentation when available.
  • Per-viewer quality, audio, and subtitle selection.
  • Persistent room, principal, lease, and audit state in SQLite.
  • Server-side control authorization behind an identity-aware reverse proxy.
  • Bounded preparation, cache, subprocess, and media-delivery behavior.

Deliberate limitations

Knowing what a project refuses to do is as useful as knowing what it does:

  • Authentication is not bundled. The documented deployment uses Authelia ForwardAuth, trusted identity headers, and Movie Night's own role database.
  • There is no chat, public signup, password reset, or viewer account system.
  • There is no arbitrary upload, URL-fetch, or live-ingest endpoint.
  • Live seek is not guaranteed for a progressively prepared presentation.
  • Bitmap subtitles such as PGS and VobSub are not personal viewer tracks.
  • The launch configuration is tested on linux/amd64; arm64 is not yet tested.

Running on Saltbox

If you run Saltbox, Movie Night fits your existing shape with no changes to Plex and no new host port: Plex is already your catalog, Traefik your router, and Authelia your login. The Saltbox guide is a step-by-step recipe from empty directory to running room.

Quick start (generic Docker Compose)

You need Docker Compose, a reachable Plex server, and an identity-aware reverse proxy for the protected routes. Start with:

Review every REQUIRED_ or REPLACE_ value, create the documented owner-only secret files, install the preflight script at a trusted absolute path, and run:

./deploy/saltbox/preflight.sh host
docker compose --env-file deploy.env -f compose.yaml config --quiet
docker compose --env-file deploy.env -f compose.yaml up -d

The examples intentionally do not provide a working public origin, image digest, secret, Plex section ID, cache budget, middleware name, or TLS setting — an incomplete deployment should fail loudly at preflight, not quietly serve your library to the internet.

Security model

The viewer page, sanitized room state, room WebSocket, subtitles, and authorized media are public. Catalog browsing, preparation, playback control, seeking, and role management require authentication and server-side authorization. Control mutations also require a host-only session, trusted proxy hop, Origin check, CSRF token, and the appropriate Movie Night role.

The Plex token stays in a server-side file. Browser-visible responses and URLs never contain it or a private media path. A loopback source gateway gives FFmpeg access only to the Plex part bound to the active preparation job.

See SECURITY.md for reporting vulnerabilities and the architecture specification for the full trust-boundary design.

Local development

A supported Go toolchain and Node.js are required for the ordinary checks. Run npm ci once to install the pinned browser-acceptance dependencies. FFmpeg, Plex, and installed browsers are required only for the explicitly named integration suites.

npm ci
make run
make check
make build

make run creates ignored development state under .local/dev/, listens on http://127.0.0.1:8080, and keeps protected routes protected. Build output is written to bin/movienightd and bin/movienightctl.

Both binaries report the version, Git revision, and build date embedded by the build. Ordinary local builds identify each field as dev:

./bin/movienightd --version
./bin/movienightctl version

Principal operations

movienightctl changes Movie Night's authorization rows; it does not create or reset accounts in the upstream identity provider.

./bin/movienightctl --database /absolute/path/movienight.db principal add operator --role admin
./bin/movienightctl --database /absolute/path/movienight.db principal add broadcaster --role broadcaster
./bin/movienightctl --database /absolute/path/movienight.db principal list
./bin/movienightctl --database /absolute/path/movienight.db backup /absolute/path/movienight.backup.db

The runtime image includes both movienightd and movienightctl. Use the control tool only from a trusted operator environment with explicit database access; it has no HTTP route.

Documentation

Guide What it covers
Saltbox guide Step-by-step install on a Saltbox host
Deployment examples Security envelope, inputs, preflight, route boundary
Configuration and secrets Every environment variable and config file
Architecture specification The full product, synchronization, and trust-boundary design
Security policy Reporting vulnerabilities privately
Release notes What v0.1.0 contains and its known limits
Third-party notices Licenses for hls.js, FFmpeg, and Go dependencies

Project posture

This is a code drop with care, not a support contract: it exists because my friends and I wanted movie nights, and it is published because yours might too. Issues and careful bug reports are genuinely welcome — I read them, and I want this to be good — but responses are best effort. Pull requests should preserve the two boundaries everything else hangs on: viewing stays anonymous, and control stays authenticated.

Movie Night is available under the MIT License.

About

Self-hosted watch-together for your Plex library: one link, no accounts, one room in sync. Saltbox-friendly.

Topics

Resources

Security policy

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages