Skip to content

Integrate HTTPS Certificates from Tailscale

lwbt edited this page Nov 22, 2024 · 5 revisions

Integrate HTTPS Certificates from Tailscale

There is an easy way to generate a trusted certificate without exposing your computer or server on the Internet.

  1. First, you need to have Tailscale installed and configured for HTTPS certificates. It's just a few clicks. Then generate a certificate if you haven't already:

    TS_SELF_DNS_NAME="$(tailscale status -json | jq -r '.Self.DNSName[:-1]')"
    sudo tailscale cert "${TS_SELF_DNS_NAME}"
  2. Copy the certificate files to Jellyfin's configuration directory:

    cp -v "${TS_SELF_DNS_NAME}."{crt,key} "${HOME}/.var/app/org.jellyfin.JellyfinServer/config/jellyfin/"
  3. Stop and start Jellyfin as usual.

  4. Configure HTTPS in Jellyfin:

    • Go to: http://localhost:8096/
    • Go to: Home → Dashboard (Administration) → Networking
    • Add: /var/config/jellyfin/ts-web-certificate.pfx (you can browse to this directory in Jellyfin, if the file is not there, then there was an error converting it)
    • Activate:
        • Enable HTTPS
    • Go to: Home → Dashboard (Administration) → Restart
    • Go to: https://localhost:8920/ (or your Tailnet address with port number 8920)
    • Login with your username and password. If you don’t know it, go back to the HTTP URL and reset your password.
    • Optionally, when this worked, go to:
      Home → Dashboard (Administration) → Networking → activate:
        • Require HTTPS
  5. For the finishing touches you can set environment variables for the launcher. This only affects the host where Jellyfin runs on, but knowing that this either works or does not should help with troubleshooting when issues arise.

    You can do this from the command line by adding lines to the respective Flatpak overrides file:

    flatpak override --user \
      --env=TS_USE_MAGIC_DNS=true \
      --env=TS_SELF_DNS_NAME=$(tailscale status -json | jq -r '.Self.DNSName[:-1]') \
      org.jellyfin.JellyfinServer

    Or you can do it with a GUI like Flatseal: Screenshot from 2024-11-17 12-32-40

    When your encounter issues, for example when you forgot to renew the certificate, these variables might be the first you want to reset.

Important

What is your responsibility with this setup? To copy the certificate files to the right location and regularly refreshing them.

If you don't have any further automation in place yet, and you don't plan to do so, then you need to execute steps 1 to 3 every 85-90 days due to the short Let's Encrypt certificate lifetime.

Note

The path /var/config/jellyfin/ in Jellyfin maps to ${HOME}/.var/app/org.jellyfin.JellyfinServer/config/jellyfin/ on your computer or server. The file network.xml is in the same folder and can be edited by hand if necessary. However you should make a backup before editing it.

Note

This solution has some limitations. Devices that don't run Tailscale, appliances like Smart TVs, are not part of your Tailscale network unless you put in some extra work. Such devices have to use the IP of any other (local) DNS name you have set up and you will still receive warnings on these clients because the domain name in the certificate does not match with the domain name in the URL you use to access Jellyfin.

I chose to go with this route, using Tailscale, for the most basic setup that the Flatpak version is intended cover. I had plans for generating long lived self-signed certificates, but I found that some clients (Apple) refuse to connect under such circumstances.

Additional configuration when running as a Systemd service

Replace ${HOME}/path_to_my_folder_with_certificate_files in SOURCE_DIR with the appropriate path for your setup and run the commands below.

SOURCE_DIR="${HOME}/path_to_my_folder_with_certificate_files"

mkdir -pv "${HOME}/.local/share/systemd/user/jellyfin.service.d/"

cat > "${HOME}/.local/share/systemd/user/jellyfin.service.d/tailscale.conf" << EOF
[Service]
ExecStartPre=/bin/cp -v ${SOURCE_DIR}/$(tailscale status -json | jq -r '.Self.DNSName[:-1]').key %h/.var/app/org.jellyfin.JellyfinServer/config/jellyfin/
ExecStartPre=/bin/cp -v ${SOURCE_DIR}/$(tailscale status -json | jq -r '.Self.DNSName[:-1]').crt %h/.var/app/org.jellyfin.JellyfinServer/config/jellyfin/
# Use OpenSSL from Flatpak.
#ExecStartPre=/usr/bin/flatpak run --command=openssl org.jellyfin.JellyfinServer pkcs12 \\
#    -export \\
#    -out /var/config/jellyfin/ts-web-certificate.pfx \\
#    -inkey /var/config/jellyfin/$(tailscale status -json | jq -r '.Self.DNSName[:-1]').key \\
#    -in /var/config/jellyfin/$(tailscale status -json | jq -r '.Self.DNSName[:-1]').crt \\
#    -passout pass: 
# Use OpenSSL on the host.
ExecStartPre=/usr/bin/openssl pkcs12 \\
    -export \\
    -out %h/.var/app/org.jellyfin.JellyfinServer/config/jellyfin/ts-web-certificate.pfx \\
    -inkey %h/.var/app/org.jellyfin.JellyfinServer/config/jellyfin/$(tailscale status -json | jq -r '.Self.DNSName[:-1]').key \\
    -in %h/.var/app/org.jellyfin.JellyfinServer/config/jellyfin/$(tailscale status -json | jq -r '.Self.DNSName[:-1]').crt \\
    -passout pass:
EOF

systemctl --user daemon-reload
systemctl --user --no-pager restart jellyfin.service
systemctl --user --no-pager status jellyfin.service

Note

  • %h expands to your home directory like ${HOME} in Bash.
  • Ensure that certificate files are readable by the user. Current instructions for issuing a certificate with tailscale run the program as root and therefore create files owned by root.