#
Cloudflare
#
Zero Trust & Tunnel Setup Guide
This guide documents the process of securely exposing a local Docker service (e.g., Jellyfin) to the internet using Cloudflare Tunnel, securing it with Cloudflare Access, and optimizing it for streaming.
#
📋 Prerequisites
- A domain name managed by Cloudflare (Nameservers pointed to Cloudflare).
- A Cloudflare account (Free plan is sufficient).
- A server/NAS running Docker.
#
🛠️ Phase 1: Install Cloudflare Tunnel (Docker)
We will deploy the cloudflared connector on your server. This creates a secure, outbound-only connection to Cloudflare's network.
Get the Tunnel Token:
- Go to the Cloudflare Zero Trust Dashboard.
- Navigate to Networks \rightarrow Tunnels.
- Click Create a Tunnel.
- Select Cloudflared (Connector).
- Name the tunnel (e.g.,
home-server) and click Save. - Under "Choose your environment", select Docker.
- Copy the long token string after
--token(it starts witheyJh...).
Deploy via Docker Compose: Add the following service to your
docker-compose.ymlstack:services: cloudflared: image: cloudflare/cloudflared:latest container_name: cloudflared-tunnel restart: always command: tunnel run environment: - TUNNEL_TOKEN=PASTE_YOUR_LONG_TOKEN_HEREStart the container.
- Return to the Cloudflare Dashboard. The tunnel status should turn "Connected" (Green) within a few seconds.
#
🗺️ Phase 2: Route the App (Subdomain)
Now we tell Cloudflare where to send traffic for a specific subdomain (e.g., media.yourdomain.com).
- In the Tunnel configuration screen (Zero Trust Dashboard), click Next (or "Public Hostname").
- Click Add a Public Hostname.
- Configuration:
- Subdomain:
media(orjellyfin) - Domain: Select
yourdomain.comfrom the list. - Path: (Leave empty)
- Service Type:
HTTP - URL:
192.168.1.X:8096 - Note: Use the LAN IP of your NAS/Server. Do NOT use
localhost.
- Subdomain:
- Click Save Hostname.
Your app is now accessible online at https://media.yourdomain.com.
#
🛡️ Phase 3: Secure with Cloudflare Access
This adds an authentication layer (Email Login, Google, etc.) before anyone reaches your app.
- Navigate to Access \rightarrow Applications in the Zero Trust Dashboard.
- Click Add an Application \rightarrow Self-hosted.
- Application Config:
- Application Name:
Jellyfin - Session Duration:
1 Month(Recommended for media apps) - Domain: Enter the same subdomain used in Phase 2 (
media.yourdomain.com).
- Application Name:
- Click Next to Configure Policy.
- Add Policy (The Guest List):
- Policy Name:
Allow Admin - Action:
Allow - Configure Rules:
- Selector:
Email - Value:
admin@yourdomain.com
- Selector:
- Policy Name:
- Click Next \rightarrow Add Application.
#
🚀 Phase 4: Performance Rules (Streaming Optimization)
Critical for Video: By default, Cloudflare tries to cache web content. This breaks video streaming (buffering/stuttering). We must disable caching for this specific subdomain.
- Go to the standard Cloudflare Dashboard (Not Zero Trust).
- Select your domain.
- Navigate to Rules \rightarrow Cache Rules (sidebar).
- Create Rule:
- Name:
Jellyfin Bypass - Field:
Hostnameequalsmedia.yourdomain.com - Cache Eligibility: Select Bypass cache.
- Click Deploy.
- Name:
- (Optional) Disable Rocket Loader:
- Navigate to Rules \rightarrow Configuration Rules.
- Create Rule:
- Name:
Disable Rocket Loader - Field:
Hostnameequalsmedia.yourdomain.com
- Name:
- Settings:
- Rocket Loader:
Off - Auto Minify: Uncheck all (HTML, CSS, JS)
- Rocket Loader:
- Click Deploy.
#
✅ Result
- Public URL:
https://media.yourdomain.com - Security: Only authorized emails can log in.
- Performance: Direct streaming without caching interference.
- Network: No ports opened on the router firewall.
