Preface

In today’s internet landscape, it’s common for third-party Emby services to be placed behind Cloudflare’s CDN. While this strategy effectively defends against DDoS attacks and mitigates potential source IP leaks, it creates a significant performance issue for users in mainland China.

For the vast majority of these users, Cloudflare’s CDN effectively functions as a bottleneck rather than an accelerator. This is because their traffic is rarely routed to nearby nodes in Hong Kong or Japan; instead, it is almost always directed to nodes located in the United States. For a service category like streaming media, this latency is nothing short of crippling.

Caddy Example

Below, I will use a Caddyfile configuration to set up a reverse proxy for the Zox Emby domain.

embyrp.shaynewong.xyz {
    encode zstd gzip

    reverse_proxy https://entry.zox.show {
        header_up Host entry.zox.show
        header_up X-Forwarded-Host {host}
        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Proto {scheme}

        transport http {
            tls_server_name entry.zox.show
        }
    }
}

Naturally, you will need to replace the domain in the Caddyfile configuration with your own and ensure that domain’s DNS records point to your server. This is a simple but mandatory prerequisite, so it won’t be detailed further here. Aside from the domain name, no other content needs to be altered.

Additionally, if you are not using the Zox Emby service, you must update the reverse proxy domain and its corresponding response headers. Other response headers generally do not require modification, unless the official provider of that specific Emby service instructs otherwise.

Detialed Explanation

This is a Caddy reverse proxy configuration. Here is a detailed explanation of each component:

Domain Declaration

embyrp.shaynewong.xyz {

This directive specifies that the configuration block applies to all requests directed to embyrp.shaynewong.xyz.

Response Compression

encode zstd gzip

This directive enables compression of response content. Caddy will prioritize the zstd algorithm (a modern, high-efficiency compression method) and fall back to gzip if the client does not support zstd.

Reverse Proxy Core

reverse_proxy https://entry.zox.show {

This directive forwards all incoming requests to the upstream server entry.zox.show via HTTPS.

Request Header Configuration

  • header_up Host entry.zox.show — Modifies the Host header to the upstream server address, informing the backend server of the request origin.
  • header_up X-Forwarded-Host {host} — Preserves the original request domain name (embyrp.shaynewong.xyz) by passing it to the upstream server.
  • header_up X-Real-IP {remote_host} — Passes the client’s actual IP address to the upstream server.
  • header_up X-Forwarded-For {remote_host} — Records the client’s IP address using the standard proxy header convention.
  • header_up X-Forwarded-Proto {scheme} — Indicates the protocol scheme (http or https) of the original client request.

Transport Layer Configuration

transport http {
    tls_server_name entry.zox.show
}

This specifies that communication with the upstream server uses HTTP, while setting the TLS Server Name Indication (SNI) to entry.zox.show. This is essential when the upstream server uses self-signed certificates or certificates for multiple domains.

Overall Function This configuration transparently proxies user requests to embyrp.shaynewong.xyz to the upstream server entry.zox.show, while preserving the original request metadata for use by the backend application.

Nginx Demo

# /etc/nginx/conf.d/embyrp.shaynewong.xyz.conf
server {
    listen 443 ssl;
    server_name embyrp.shaynewong.xyz;

    # TLS certs (replace with your actual paths)
    ssl_certificate     /etc/ssl/nginx/embyrp.shaynewong.xyz.crt;
    ssl_certificate_key /etc/ssl/nginx/embyrp.shaynewong.xyz.key;

    # --- Compression (Caddy's `encode zstd gzip`) ---
    # Nginx has gzip built in; zstd needs extra modules, so we do gzip here.
    gzip on;
    gzip_types text/plain text/css application/json application/javascript application/xml text/xml;
    gzip_vary on;

    location / {
        # This is the Caddy `reverse_proxy https://entry.zox.show`
        proxy_pass https://entry.zox.show;

        # Match Caddy's header_up lines:
        proxy_set_header Host               entry.zox.show;   # header_up Host entry.zox.show
        proxy_set_header X-Forwarded-Host   $host;            # header_up X-Forwarded-Host {host}
        proxy_set_header X-Real-IP          $remote_addr;     # header_up X-Real-IP {remote_host}
        proxy_set_header X-Forwarded-For    $remote_addr;     # header_up X-Forwarded-For {remote_host}
        proxy_set_header X-Forwarded-Proto  $scheme;          # header_up X-Forwarded-Proto {scheme}

        # --- TLS to upstream (Caddy's `transport http { tls_server_name ... }`) ---
        proxy_ssl_server_name on;
        proxy_ssl_name entry.zox.show;

        # Sensible proxy timeouts (optional but good for media-ish backends)
        proxy_connect_timeout 10s;
        proxy_send_timeout    60s;
        proxy_read_timeout    60s;
    }
}

# If you also need HTTP -> HTTPS redirect:
server {
    listen 80;
    server_name embyrp.shaynewong.xyz;
    return 301 https://$host$request_uri;
}

Detailed Explanation

This is an Nginx configuration that functionally replicates the previously discussed Caddy configuration. Here is a comprehensive explanation:

HTTPS Server Block

server {
    listen 443 ssl;
    server_name embyrp.shaynewong.xyz;

Declares an Nginx server block that listens on port 443 (HTTPS) and responds to requests for embyrp.shaynewong.xyz.

TLS Certificate Configuration

ssl_certificate     /etc/ssl/nginx/embyrp.shaynewong.xyz.crt;
ssl_certificate_key /etc/ssl/nginx/embyrp.shaynewong.xyz.key;

Specifies the paths to the SSL certificate and private key files required for TLS encryption.

Response Compression

gzip on;
gzip_types text/plain text/css application/json application/javascript application/xml text/xml;
gzip_vary on;

Enables gzip compression for responses. The gzip_types directive specifies which MIME types should be compressed. The gzip_vary on directive ensures the Vary: Accept-Encoding header is included in responses, enabling proper caching behavior. Note: Nginx does not natively support zstd compression; only gzip is employed here.

Reverse Proxy Location Block

location / {
    proxy_pass https://entry.zox.show;

Routes all requests to the upstream server entry.zox.show via HTTPS.

Request Header Mapping

proxy_set_header Host               entry.zox.show;
proxy_set_header X-Forwarded-Host   $host;
proxy_set_header X-Real-IP          $remote_addr;
proxy_set_header X-Forwarded-For    $remote_addr;
proxy_set_header X-Forwarded-Proto  $scheme;

These directives map request headers to pass client metadata to the upstream server:

  • Host is set to the upstream domain
  • X-Forwarded-Host retains the original request domain (embyrp.shaynewong.xyz)
  • X-Real-IP and X-Forwarded-For preserve the client’s IP address
  • X-Forwarded-Proto indicates the client request protocol (http or https)

Upstream TLS Configuration

proxy_ssl_server_name on;
proxy_ssl_name entry.zox.show;

These directives enable SNI (Server Name Indication) for connections to the upstream server. proxy_ssl_server_name on activates SNI, and proxy_ssl_name specifies the hostname to be sent during the TLS handshake. This is necessary when the upstream server uses self-signed or multi-domain certificates.

Proxy Timeouts

proxy_connect_timeout 10s;
proxy_send_timeout    60s;
proxy_read_timeout    60s;

These directives configure connection and communication timeouts:

  • proxy_connect_timeout: Maximum time to establish a connection to the upstream server
  • proxy_send_timeout: Maximum time to send a request to the upstream server
  • proxy_read_timeout: Maximum time to receive a response from the upstream server

HTTP to HTTPS Redirect

server {
    listen 80;
    server_name embyrp.shaynewong.xyz;
    return 301 https://$host$request_uri;
}

This secondary server block listens on port 80 (HTTP) and redirects all requests to their HTTPS equivalents using a permanent 301 redirect. This ensures clients are automatically upgraded to secure connections.

Overall Function This Nginx configuration provides equivalent functionality to the Caddy configuration, proxying requests from embyrp.shaynewong.xyz to entry.zox.show while preserving client metadata and enabling HTTPS encryption for both client-to-proxy and proxy-to-upstream communications.

Emby's Reverse Proxy

Author

Shayne Wong

Publish Date

11 - 07 - 2025

License

Shayne Wong

Avatar
Shayne Wong

All time is no time when it is past.