Edge Shield for Jellyfin — guide
Installation
You need Jellyfin Server 12.2 or newer and a MediaLab Works account with a license that covers the plugin (an active subscription, a lifetime license within its update window, the Jellyfin bundle or the free 30-day trial).
From your plugin repository (recommended). Jellyfin then installs and updates the plugin by itself.
- In your MediaLab Works account open Licenses → Jellyfin plugin repository and click Create address. Copy it: it is private (it contains a token), so do not share it; you can regenerate or revoke it at any time.
- In Jellyfin open Dashboard → Plugins → Repositories, click +, give it a name (for example MediaLab Works), paste the address and save.
- In Dashboard → Plugins → Catalog find Edge Shield by MediaLab, click Install, then restart Jellyfin.
The repository lists only the plugins your licenses cover, and only the versions they allow. Its download links are signed and expire after a few hours, so Jellyfin always reads a fresh list.
From the public catalog. https://medialab.works/jellyfin/manifest.json lists every released MediaLab Works plugin with its public build; medialab Server adds it by itself. You can add it the same way to install a plugin before you have a key: the plugin then asks for the license, or starts the trial, on its License page. With a lifetime license whose update window has ended, keep to your private repository, which offers only the versions your license allows.
Manually, from a zip file.
- In Account → Licenses download
jf-edgeshield_x.y.z.zip(the SHA-256 of the file is shown next to the button). - Extract it into a new folder
Edge Shield by MediaLab_x.y.z.0inside the Jellyfin plugins folder:- Linux (package):
/var/lib/jellyfin/plugins/ - Docker (official image):
/config/plugins/in the config volume - Windows:
%ProgramData%\Jellyfin\Server\plugins\
- Linux (package):
- Restart Jellyfin.
License activation
- Open the plugin page in Dashboard → Plugins → Edge Shield by MediaLab and click License.
- Paste your license key and click Activate with key. The plugin contacts the license server, binds the key to this Jellyfin server and shows the license as Active.
- No key yet? On the same page enter your e-mail and start the 30-day free trial (card needed, nothing to pay today) or buy a license; the plugin activates itself when the payment is done.
The license is checked once a day and at every Jellyfin start. Without internet the plugin keeps working for 7 days after the last successful check. Without a valid license the plugin stops its work and only its License page keeps working (trial, key, renewal); nothing is deleted, and everything resumes as soon as the license is valid again. Move license (release this server) on the same page frees the key for another server.
Updates and rollback
- From the repository: Jellyfin shows new versions in Dashboard → Plugins and can update the plugin automatically; restart Jellyfin to load the new version.
- From the plugin's License page: with a valid license, Install update installs the newest version your license allows and Roll back to x.y.z goes back to the previous version (for example if something stopped working after an update). Restart Jellyfin after either. Both packages are checked against the checksum published by the license server.
- A lifetime license receives the versions released during its update window; after it, the plugin keeps working on the last version it may use.
- After a rollback, if your plugin repository is added in Jellyfin, Jellyfin's scheduled task Update Plugins (at start-up and daily) installs the newest version again. To stay on the previous version for a while, remove the triggers of that task in Dashboard → Scheduled Tasks and add them back later.
Source code
The GPL-3.0 source code of each version is in Account → Licenses (Source code), next to the download, as a .tar.gz archive made from the exact commit of that version.
Configuration
- Connection: in Cloudflare create an API token (Create Token → Custom token), restricted to your zone, with the permissions the page lists: Zone · Zone · Read, Zone · DNS · Edit, Zone · Zone Settings · Edit, Zone · SSL and Certificates · Edit, Zone · Zone WAF · Edit, Zone · Single Redirect · Edit, Zone · Cache Rules · Edit, Zone · Origin Rules · Edit and Account · Account Filter Lists · Edit. Paste it, then pick the zone (your domain). The token is stored encrypted on the server and is never shown again; a missing permission is named on the status page.
- Mode:
- Recommended: UI through Cloudflare, video direct ("stream offload"). The app host goes through the Cloudflare proxy; video, audio and download requests are redirected (307) to the streaming host, which is "DNS only" and goes straight to your server.
- DNS only (no proxy): Cloudflare only for DNS, DDNS and the certificate. WAF rules and edge blocking do not apply, because traffic does not pass through Cloudflare.
- Names and ports: the app host (for example
media.example.com) with the HTTPS port your clients use (443, or one of the ports Cloudflare proxies: 2053, 2083, 2087, 2096, 8443), the external port your router forwards to the server (if it differs, Edge Shield adds an origin rule), and the streaming host (for exampledirect.example.com) with its external HTTPS port. The public IPv4 is detected when the field is empty; DDNS keeps the records up to date when it changes. - Server certificate: Let's Encrypt automatically (DNS-01, with the token) for both names, or one you manage yourself. Full (strict) needs a valid certificate on the server. The certificate is renewed 30 days before it expires.
- TLS: minimum TLS version and, optionally, HSTS on the app host (turn it on only once HTTPS works reliably; it is hard to undo).
- Protection: automatic blocking of IPs with failed sign-ins (5 in 10 minutes and 24 hours by default, ×4 on every repeat), the IPs or CIDR ranges never to block, the login rate limit (more than 10 requests in 10 s from one IP → 10 s block), blocking of client-sent IP headers, and the allowed countries (ISO codes; empty means all). The streaming host accepts media paths only (on by default): any other request on it gets 403.
- Save, then open Status and fixes and click Fix everything, so the settings and rules reach Cloudflare and Jellyfin. Restart Jellyfin when the page says so (HTTPS, the certificate and the Cloudflare ranges in Jellyfin's known proxies take effect after a restart; the ranges are refreshed daily and the page asks for a restart when they change).
Daily use
- The status page checks the token, the DNS records, the TLS settings, the certificate, the rules, the real client IP and HTTPS in Jellyfin; each problem has a Fix button.
- Blocked IPs: the list shows the address, the reason and the expiry; you can unblock an IP or block one by hand, with a note and a duration. Your LAN, the Cloudflare ranges and the allowlist are never blocked.
- Under Attack: turn it on for 30 minutes to 12 hours during an attack; it turns itself off. While it is on, native apps (Android TV, Roku, iOS, Kodi…) cannot connect.
- Port restriction (firewall): the page shows ready commands to let only Cloudflare reach the app host's port; Edge Shield never changes your firewall itself.
- Remove the Edge Shield rules deletes only the rules the plugin created; DNS and TLS settings stay as they are.
What it sends where
- To Cloudflare, with your token: zone settings, DNS records with your public IP, rules and the IPs to block. A block-list entry's comment holds only the expiry and the reason (the count of failed sign-ins, or "manual" with your note). Since 0.1.1 the attempted user name is not sent to Cloudflare; it stays in the block list and the log on your server.
https://www.cloudflare.com/cdn-cgi/traceto detect the public IP, and the public Cloudflare API for its IP ranges (daily).- To Let's Encrypt: the certificate request for your host names; the private key stays on your server.
- Nothing goes to medialab.works except the license check.
Troubleshooting
- "The token lacks the … permission": edit the token in Cloudflare, add the permission shown and click Fix again.
- "Video would flow through the Cloudflare CDN": the app host is proxied but no streaming host is set. Set a streaming host ("DNS only") or switch to DNS only mode.
- "The server's public IP could not be detected": enter the public IPv4 in the settings.
- The apps cannot connect: check that Under Attack is off, and that the streaming host's external port is forwarded to Jellyfin's HTTPS port.
- Changes do not show in Jellyfin: the status page says Restart needed; restart Jellyfin.