Skip to content

ggfevans/jellyfin-remote-access

Jellyfin Remote Access

License: MIT Docker Nginx Tailscale CodeRabbit Pull Request Reviews

A secure, production-ready Docker-based solution for remotely accessing your home Jellyfin media server without exposing your home network directly to the internet.

Architecture Diagram

πŸ“‹ Overview

This project provides a complete, production-ready implementation for securely exposing a Jellyfin media server to the internet. It solves common challenges faced by home media server enthusiasts:

  • Accessing your media when away from home
  • Sharing your media library with friends and family
  • Avoiding the security risks of direct port forwarding
  • Working around ISP restrictions (CGNAT, blocked ports, etc.)

πŸ—οΈ Architecture

The solution uses a VPS (Virtual Private Server) as a secure gateway to your home Jellyfin server:

Internet β†’ VPS (Nginx + Let's Encrypt) ↔ Tailscale VPN ↔ Home Network (Jellyfin)

Components

  • Nginx: Reverse proxy that handles HTTPS traffic and forwards requests to Jellyfin
  • Certbot: Automatically obtains and renews Let's Encrypt SSL certificates
  • Tailscale: Creates a secure private network between your VPS and home server
  • Jellyfin: Media server running on your home network

✨ Features

  • πŸ”’ End-to-end encryption via Tailscale and HTTPS
  • 🚫 No ports opened on your home network
  • πŸ“œ Automatic SSL certificate management
  • πŸ”„ Optimized Nginx configuration for media streaming
  • 🐳 Complete Docker Compose setup for easy deployment
  • πŸ›‘οΈ Security hardening out of the box

πŸ”§ Prerequisites

  • A VPS with a public IP address (DigitalOcean, Linode, etc.)
  • A domain name pointed to your VPS
  • Docker and Docker Compose installed on your VPS
  • Jellyfin installed on your home server
  • Tailscale account and configured tailnet
  • Basic familiarity with the command line and Docker

πŸš€ Quick Start

  1. Clone this repository to your VPS:

    git clone https://github.com/ggfevans/jellyfin-remote-access.git
    cd jellyfin-remote-access
  2. Copy the example configuration files:

    cp .env.example .env
    cp tailscale.env.example tailscale.env
    cp init-letsencrypt.sh.example init-letsencrypt.sh
    chmod +x init-letsencrypt.sh
  3. Set up your Tailscale network:

    • Create a Tailscale account at https://tailscale.com
    • Install Tailscale on your home Jellyfin server
    • Generate an auth key in the Tailscale admin console
    • Update tailscale.env with your hostname and auth key
  4. Configure your environment:

    • Edit .env with your domain and email
    • Update the Jellyfin Tailscale IP in .env
    • Edit init-letsencrypt.sh with your domain
  5. Initialize SSL certificates:

    ./init-letsencrypt.sh
  6. Start the services:

    docker compose up -d
  7. Visit your domain in a web browser to access Jellyfin!

πŸ“ Detailed Setup Guide

1. Domain Configuration

Update your domain settings in the following files:

  • init-letsencrypt.sh - Set domains array
  • data/nginx/app.conf - Replace yourdomain.com with your domain
  • nginx/jellyfin.conf - Replace your_domain.com with your domain

2. Tailscale Configuration

The Tailscale container creates a secure tunnel between your VPS and home network:

  1. Edit tailscale.env:

    TS_HOSTNAME=your_tailscale_hostname
    TS_AUTHKEY=tskey-auth-yourauthkeyhere
    
  2. Make sure Jellyfin on your home network is reachable via Tailscale:

    • Install Tailscale on your home Jellyfin server
    • Note the Tailscale IP address (e.g., 100.x.y.z)
  3. Update nginx/jellyfin.conf to point to your Jellyfin Tailscale IP:

    set $upstream_jellyfin "http://100.x.y.z:8096";
    

3. Nginx Configuration

The included configurations are already optimized for Jellyfin, but you may need to adjust:

  • moz_ssl - SSL parameters based on Mozilla's recommendations
  • proxy_params - Proxy settings for Jellyfin
  • website.conf - Main Nginx configuration for your domain

4. Certificate Initialization

Run the initialization script to set up Let's Encrypt:

chmod +x init-letsencrypt.sh
./init-letsencrypt.sh

This script will:

  • Create a temporary Nginx configuration
  • Obtain initial certificates from Let's Encrypt
  • Set up automatic renewal

5. Starting the Stack

Launch all services:

docker compose up -d

Verify all containers are running:

docker compose ps

πŸ” Troubleshooting

Certificate Issues

If Certbot fails to obtain certificates:

  • Ensure your domain is correctly pointed to your VPS
  • Check that ports 80 and 443 are open on your VPS
  • Examine Certbot logs: docker compose logs certbot

Connection Problems

If you can't connect to Jellyfin:

  • Verify Tailscale is connected on both the VPS and home server
  • Check Tailscale connectivity: tailscale ping your-jellyfin-hostname
  • Ensure Jellyfin is accessible directly via its Tailscale IP
  • Examine Nginx logs: docker compose logs nginx

Streaming Issues

If videos buffer or play poorly:

  • Check your home upload bandwidth
  • Adjust Jellyfin transcoding settings
  • Consider modifying Nginx buffer settings in proxy_params

πŸ›‘οΈ Security Considerations

This setup provides several security advantages:

  • No open ports on your home network
  • End-to-end encryption between VPS and home server
  • HTTPS encryption for all external traffic
  • Isolated containers with minimal permissions
  • Content Security Policy headers to prevent XSS attacks

Additional hardening you might consider:

  • Setting up SSH key-only authentication on your VPS
  • Configuring a firewall (UFW) on your VPS
  • Enabling rate limiting in Nginx for login attempts
  • Regular security updates for all components

πŸ“š Advanced Configuration

Custom Error Pages

Custom error pages are located in data/nginx/html/. You can modify:

  • 404.html - Not found errors
  • maintenance.html - Displayed during maintenance

Nginx Optimization

The included Nginx configuration is optimized for media streaming, with:

  • Efficient proxy buffering
  • Connection keep-alive settings
  • Browser caching for static assets
  • Gzip compression

Multiple Domains

To add additional domains:

  1. Update the domains array in init-letsencrypt.sh
  2. Add server blocks for each domain in data/nginx/website.conf
  3. Run the initialization script again

πŸ”„ Updating

To update the components:

docker compose pull
docker compose down
docker compose up -d

πŸ“Š Monitoring

Consider adding these monitoring solutions:

🀝 Contributing

Contributions are welcome! Please read our Contributing Guidelines and Code of Conduct before submitting a Pull Request.

Reporting Issues

  • Check existing issues before creating a new one
  • Use the issue templates provided
  • Include logs and configuration (without sensitive data)

Development

See CONTRIBUTING.md for development setup instructions.

πŸ”’ Security

For security concerns, please read our Security Policy.

πŸ“œ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgements

πŸ“ž Support

About

No description or website provided.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks