Jellyfin and metadata privacy

I recently migrated my home media server to Jellyfin. One of the advantages of using it is that it can supplement your (mainstream) media collection with poster graphics and rich metadata pulled in from sources like The Movie Database (TMDb) and TheTVDB. As with everything that talks to someone else’s servers, this feature comes at a cost to privacy.

To gather more information about your media collection, Jellyfin needs to share what it already knows about it with the metadata provider. Typical data includes the title and release year (extracted from the file or its path) for movies, and the same plus parent and grandparent directory names for TV shows. In some situations, more data may be transmitted.

After a quick reading of TMDb and TheTVDb’s privacy policies, I know that they both reassure me that they care about my privacy and that they don’t sell my data. But they do share it with commercial partners for various purposes, including advertising. Presumably for a profit? So, … yeah.

Your media collection is probably unique, and thus make it a suitable source for digital fingerprinting. No one else has the exact same combination of movies and TV shows as you do. The bigger the collection, the more unique its fingerprint is. I’ve discussed this kind of fingerprinting in more detail in an earlier article in the context of feed readers.

Luckily, it’s possible to enjoy the metadata downloader feature and still preserve your privacy. Note that this won’t help if you’ve got family movies, unique media, or media files that contain personal information in your collection. Make sure these types of personal media files are kept in libraries where metadata plugins are disabled.

Instead of downloading metadata from your Internet Protocol (IP) address, you can obscure the source address (the IP) of the traffic through Tor. Tor is a free service for anonymizing the source of your network traffic. Routing Jellyfin’s metadata look-ups through it can help conceal your IP address and thus your location. This makes it more difficult to combine the data with your other online activities. You can of course adjust the example to use a commercial proxy service instead.

In this tutorial, I’ll assume you’re using a modern Linux distribution. I’ll assume you’ve already installed Jellyfin and Tor through your Linux distribution’s package manager and run them through systemd (this will be the case on most distributions). The concepts are applicable under other operating systems and in container environments (e.g. Docker or Podman), but the exact tools and procedures will differ.

You’ll first need to enable the HTTP proxy tunnel feature in Tor. By default, Tor only enables a socket proxy. To enable this feature, locate the torrc runtime configuration file (it’ll likely be located in /etc/torrc). Add the following option to the configuration file:

HTTPTunnelPort 9049

Enable and start the Tor service, or restart it if it’s already running:

systemctl enable --now tor.service
systemctl restart tor.service

Next, you’ll need to modify the Jellyfin service to route its traffic through the Tor proxy service. Additionally, we’ll use a systemd application firewall to block the Jellyfin server from communicating with the internet without going through the proxy. Jellyfin is written in .Net and uses the HttpClient Class to talk to the internet. On Unix-like operating systems (including FreeBSD, Linux, and MacOS), HttpClient reads the proxy configuration from the environmental variables HTTP_PROXY and HTTPS_PROXY (or ALL_PROXY).

Open a text editor with a systemd service override file (systemctl edit jellyfin.service), and paste the following configuration:

# set proxy env. var. to Tor
# block all network connections
# allow access to localhost (the Tor proxy)
# allow access to local net (inc. home NAS,
#   Chromecast, phone apps, etc.)

This configuration assumes your local network is in the 10/8 subnet. Your Jellyfin server won’t be able to connect directly to the internet, and it won’t be remotely reachable anymore. You’ll need to adjust the firewall options if you’re using a different subnet, or have other network requirements.

You can also remove the proxy configuration from the above example to prevent Jellyfin from connecting to the internet. This may be useful if you don’t need any remote internet services for your media server. Please note that the .Net HttpClass doesn’t support SOCKS proxies, only HTTP proxies.

Lastly, you’ll need to reload and restart the Jellyfin service to apply the changes.

systemctl daemon-reload
systemctl restart jellyfin.service

These instructions can easily be adapted for Plex, Emby, or other media servers. However, Jellyfin is more suited for this kind of setup as it doesn’t need to connect to a central server for premium or streaming features. Jellyfin also doesn’t collect any analytics or telemetry data, and might be the best choice for any privacy-minded users.