Installation
JellyWatchParty has two parts to install: the session server (a small standalone process that manages rooms) and the Jellyfin plugin (which serves the UI and talks to the session server). Both are required.
Prerequisites
- Jellyfin Server 12.x (10.11.x is no longer supported — install an older JellyWatchParty release if you’re still on it)
- Port 3000 available for the session server (or any port you choose)
- Admin access to Jellyfin
Quick Start (Docker Compose)
The fastest way to get running. The admin panel
and the Discord bot are optional:
the panel only starts when ADMIN_PASSWORD is set, and the bot only with the
discord profile.
# docker-compose.yml
services:
jwp-session:
image: ghcr.io/tigamingtv/jwp-session-server:${JWP_TAG:-latest}
container_name: jwp-session
restart: unless-stopped
ports:
- "3000:3000"
# Admin panel; only starts when ADMIN_PASSWORD is set.
- "127.0.0.1:3001:3001"
# Never publish 3002 (integration API for the Discord bot).
environment:
- ALLOWED_ORIGINS=http://your-jellyfin:8096
- JWT_SECRET=${JWT_SECRET:-} # same value as in the plugin settings
- ADMIN_PASSWORD=${ADMIN_PASSWORD:-}
# Jellyfin devices (TV apps, Fladder, ...) in the admin panel and the bot
- JELLYFIN_URL=${JELLYFIN_URL:-} # as seen from this container
- JELLYFIN_API_KEY=${JELLYFIN_API_KEY:-}
# Discord bot: settings and link codes are kept in /data
- DATA_DIR=/data
- INTEGRATION_HOST=0.0.0.0
- DISCORD_INTEGRATION_TOKEN=${DISCORD_INTEGRATION_TOKEN:-}
volumes:
- jwp-data:/data
# Optional: docker compose --profile discord up -d
jwp-discord-bot:
image: ghcr.io/tigamingtv/jwp-discord-bot:${JWP_TAG:-latest}
container_name: jwp-discord-bot
restart: unless-stopped
profiles: [discord]
depends_on: [jwp-session]
environment:
- DISCORD_BOT_TOKEN=${DISCORD_BOT_TOKEN:-}
- JWP_INTEGRATION_TOKEN=${DISCORD_INTEGRATION_TOKEN:-}
- JWP_INTEGRATION_URL=http://jwp-session:3002
volumes:
jwp-data:
# .env next to docker-compose.yml
JWT_SECRET=<openssl rand -base64 32>
ADMIN_PASSWORD=<openssl rand -base64 18>
JELLYFIN_URL=http://your-jellyfin:8096
JELLYFIN_API_KEY=<Dashboard > API Keys>
# Only for the Discord bot:
DISCORD_INTEGRATION_TOKEN=<openssl rand -hex 32>
DISCORD_BOT_TOKEN=<Discord Developer Portal > Bot > Reset Token>
# Image channel for both containers: latest (default), dev, beta or 1.2.3
# JWP_TAG=latest
docker compose up -d # session server only
docker compose --profile discord up -d # session server + Discord bot
Then install the plugin via the repository method below, and enable the client script.
Session Server Install Options
Pick whichever fits your environment. All options end up running the same server; only how you get it running differs.
Docker: Pre-built Image (Recommended)
# Latest stable release
docker run -d \
--name jwp-session \
-p 3000:3000 \
-e ALLOWED_ORIGINS="http://localhost:8096" \
ghcr.io/tigamingtv/jwp-session-server:latest
# Or a specific version (release v0.1.0)
docker run -d --name jwp-session -p 3000:3000 \
ghcr.io/tigamingtv/jwp-session-server:0.1.0
# Or the beta channel (latest build from main)
docker run -d --name jwp-session -p 3000:3000 \
ghcr.io/tigamingtv/jwp-session-server:beta
# Or the develop channel (latest build from develop, for testing)
docker run -d --name jwp-session -p 3000:3000 \
ghcr.io/tigamingtv/jwp-session-server:dev
The Discord bot is published the same way as
ghcr.io/tigamingtv/jwp-discord-bot, with the same tags. Run it on the same
tag as the server.
Docker: Build from Source
docker build -f infra/docker/server.Dockerfile --build-arg BUILD_MODE=release \
-t jwp-session-server ./src/server
docker run -d \
--name jwp-session \
-p 3000:3000 \
-e ALLOWED_ORIGINS="http://localhost:8096" \
jwp-session-server
Native Linux (Build from Source)
Requires Rust 1.83+:
cd src/server
cargo build --release
./target/release/session-server
Windows Server (Prebuilt Binary, No Install Required)
No Docker, no Rust, nothing to install — download a ready-to-run binary:
- Go to Releases
and download
jwp-session-server-windows-vX.Y.Z.zipfrom the latest release - Extract it anywhere on the Windows Server host
- (Optional) Set configuration via environment variables before launching,
e.g. in PowerShell:
$env:PORT = "3000" $env:ALLOWED_ORIGINS = "http://your-jellyfin:8096" $env:JWT_SECRET = "<32+ char secret, must match the Jellyfin plugin config>" - Run
session-server.exe - Allow it through Windows Firewall when prompted so Jellyfin and clients
can reach it on the configured port (default
3000)
To keep it running in the background as a Windows service, wrap it with
NSSM or Task Scheduler pointed at session-server.exe.
Enable the Client Script
The session server alone doesn’t do anything — Jellyfin’s web UI needs a small script injected so the Watch Party button and panel appear.
Option A: Automatic Injection (Recommended)
Install jellyfin-plugin-file-transformation
and restart Jellyfin. JellyWatchParty automatically registers a transformation
that injects the client script into index.html — no configuration needed.
Option B: Manual (Custom HTML)
- Log in to Jellyfin as an administrator
- Go to Dashboard > General
- Scroll to Custom HTML (Branding section)
- Add this line to the “Custom HTML body” field:
<script src="../JellyWatchParty/ClientScript"></script> - Click Save
- Hard refresh your browser (Ctrl+F5)
Plugin Install
Option A: Via Jellyfin Plugin Repository (Recommended)
- Go to Dashboard > Plugins > Repositories
- Click Add and enter:
https://tigamingtv.github.io/JellyWatchParty/jellyfin-plugin-repo/manifest.json - Go to the Catalog tab
- Find JellyWatchParty and click Install
- Restart Jellyfin
- Enable the client script if you haven’t already
This method provides automatic update notifications when new versions are
released. Testers who want the develop/beta channel instead can use
manifest-dev.json in the same way — see Release: Develop Plugin
Channel.
Option B: Manual Download
- Download the latest release zip (
JellyWatchParty-vX.Y.Z.zip) from the releases page - Extract it to your Jellyfin plugins directory:
# Linux (Docker) unzip JellyWatchParty-v0.1.0.zip -d /tmp/jwp docker cp /tmp/jwp/. jellyfin:/config/plugins/JellyWatchParty/ # Linux (native) sudo unzip JellyWatchParty-v0.1.0.zip -d /var/lib/jellyfin/plugins/JellyWatchParty/ # Windows # Extract to: C:\ProgramData\Jellyfin\Server\plugins\JellyWatchParty\ - Restart Jellyfin (
docker restart jellyfinorsudo systemctl restart jellyfin) - Enable the client script
Configure the Plugin (Optional)
- Go to Dashboard > Plugins > JellyWatchParty
- Set a JWT Secret (min 32 characters) for authentication
- Click Save
See Configuration for the full settings reference.
Verification
Check the session server:
curl http://localhost:3000/health
# Expected: 200 OK with "OK"
Check the plugin:
- Go to Dashboard > Plugins — “JellyWatchParty” should appear in the list
- Check the logs for a startup message:
[JellyWatchParty] JWT authentication is enabled.or
[JellyWatchParty] JwtSecret is not configured. Authentication is DISABLED.
Test the UI:
- Open any video in Jellyfin
- Look for the Watch Party button (group icon) in the top header
- Click it to open the panel
Environment Variables
This is the core list. The admin panel and Jellyfin device variables are in
the Admin Panel reference, the Discord bot
variables are in the Discord Bot guide, and
.env.example lists all of them.
| Variable | Default | Description |
|---|---|---|
PORT |
3000 |
Server port |
HOST |
0.0.0.0 |
Bind address |
ALLOWED_ORIGINS |
* |
CORS allowed origins (comma-separated) |
JWT_SECRET |
(none) | JWT secret for authentication |
RUST_LOG |
info |
Logging level |
docker run -d \
-p 3000:3000 \
-e ALLOWED_ORIGINS="https://jellyfin.example.com" \
-e JWT_SECRET="your-32-character-secret-key-here" \
-e RUST_LOG="debug" \
ghcr.io/tigamingtv/jwp-session-server:latest
Firewall Configuration
| Port | Service | Direction |
|---|---|---|
| 8096 | Jellyfin HTTP | Inbound |
| 8920 | Jellyfin HTTPS | Inbound (if using SSL) |
| 3000 | Session Server | Inbound |
| 3001 | Admin panel | Only if you use it; keep it private (see Admin Panel) |
| 3002 | Discord integration API | Never publish. Stays inside the Docker network |
# UFW (Ubuntu)
sudo ufw allow 8096/tcp
sudo ufw allow 3000/tcp
# firewalld (Fedora/CentOS)
sudo firewall-cmd --permanent --add-port=8096/tcp
sudo firewall-cmd --permanent --add-port=3000/tcp
sudo firewall-cmd --reload
Next Steps
- Configuration - Configure JWT, CORS, and sync tuning
- Security - Set up authentication and hardening
- Deployment - Production deployment behind a reverse proxy
- Troubleshooting & FAQ - If something isn’t working