Nginx 推荐反向代理基础配置

#最好使用upstream来配置反向代理后端,因为可以使用keepalive,特别是对于nginx服务器和emby服务器之间延迟高的时候最有用
#此段配置在http模块内,而不是server模块内
upstream emby-backend {
     server  127.0.0.1:8096;
     keepalive 1024;
}

#此段配置在server模块内
client_body_buffer_size 512k;
client_max_body_size 20M;
add_header Strict-Transport-Security "max-age=15552000; preload" always;
add_header 'Referrer-Policy' 'origin-when-cross-origin';
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;

keepalive_timeout 120s;
keepalive_requests 10000;

proxy_hide_header X-Powered-By;
proxy_buffer_size 32k;
proxy_buffers 4 64k;
proxy_busy_buffers_size 128k;
proxy_temp_file_write_size 128k;
proxy_connect_timeout 1h;
proxy_send_timeout 1h;
proxy_read_timeout 1h;

location /swagger {
  return 404;
}

location =/ {
  return 302 web/index.html;
}

location / {
  proxy_pass http://emby-backend;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header X-Forwarded-Protocol $scheme;
  proxy_set_header X-Forwarded-Host $http_host;
  proxy_set_header REMOTE-HOST $remote_addr;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "";
  proxy_set_header Accept-Encoding "";
  proxy_http_version 1.1;
  proxy_cache off;
}

location /web/ {
  proxy_pass http://emby-backend;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header X-Forwarded-Protocol $scheme;
  proxy_set_header X-Forwarded-Host $http_host;
  proxy_set_header REMOTE-HOST $remote_addr;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "";
  proxy_set_header Accept-Encoding "";
  proxy_http_version 1.1;
  # 如果你使用cloudflare或其他缓存js|css文件,可取消下一行的注释来关闭本机缓存
  # proxy_cache off;
}

location = /embywebsocket {
  proxy_pass http://emby-backend;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header X-Forwarded-Protocol $scheme;
  proxy_set_header X-Forwarded-Host $http_host;
  proxy_set_header REMOTE-HOST $remote_addr;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
  proxy_set_header Accept-Encoding "";
  proxy_http_version 1.1;
  proxy_cache off;
}

location /emby/videos/ {
  proxy_pass http://emby-backend;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header X-Forwarded-Protocol $scheme;
  proxy_set_header X-Forwarded-Host $http_host;
  proxy_set_header REMOTE-HOST $remote_addr;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "";
  proxy_set_header Accept-Encoding "";
  proxy_http_version 1.1;
  proxy_cache off;
  proxy_buffering off;
}

开启Nginx缓存

Nginx开启视频流Slice缓存-视频拖动更加顺滑

准备工作

1.Nginx需要具备slice功能,运行nginx -V查看是否有 --with-http_slice_module ,如果没有需要添加 --with-http_slice_module 参数重新编译Nginx。

使用Slice的优点

  • 仅缓存正在观看的视频视频部分,看多少缓存多少,效率高,节省服务器存储压力

  • 如果你使用rclone网盘作为视频源,若已经缓存(即你已经看过视频的那一段)那么调视频进度将不会重新请求rclone api,对经常调视频进度的朋友非常有效

如果你的视频流开启了307重定向到未开启cdn的域名,则此配置只需配置在nginx中未开启cdn的域名里

直接上Nginx配置文件:

# 这段缓存目录的声明放在http模块里面,要提前创建缓存目录,并赋予nginx权限
proxy_cache_path  /var/cache/nginx/emby-videos levels=1:2 keys_zone=emby-videos:100m inactive=15d max_size=50g use_temp_path=off;
map $request_uri $h264Level { ~(h264-level=)(.+?)& $2; }
map $request_uri $h264Profile { ~(h264-profile=)(.+?)& $2; }

# 这段反向代理配置放http的server模块里面
location ~ ^/emby/videos/\d+/(?!live|\w+\.m3u8|hls1) {
  # 如果你emby使用的视频文件是本地文件,可以把 slice 大小设置小点,比如4m或者8m
  # 如果使用的是网络文件或者rclone挂载的网盘文件,建议设置为12m或者16m以上
  # 不建议设置太高
  slice 14m;

  proxy_pass http://emby-backend;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header X-Forwarded-Protocol $scheme;
  proxy_set_header X-Forwarded-Host $http_host;
  proxy_set_header REMOTE-HOST $remote_addr;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "";
  proxy_set_header Accept-Encoding "";
  proxy_set_header Range $slice_range;
  proxy_ignore_headers Expires Cache-Control Set-Cookie X-Accel-Expires;
  proxy_http_version 1.1;
  proxy_connect_timeout 15s;

  proxy_cache emby-videos;
  proxy_cache_valid 200 206 301 302 7d;
  proxy_cache_lock on;
  proxy_cache_lock_age 60s;
  proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
  proxy_cache_key "$uri?MediaSourceId=$arg_MediaSourceId&VideoCodec=$arg_VideoCodec&AudioCodec=$arg_AudioCodec&AudioStreamIndex=$arg_AudioStreamIndex&VideoStreamIndex=$arg_VideoStreamIndex&ManifestSubtitles=$arg_ManifestSubtitles&VideoBitrate=$arg_VideoBitrate&AudioBitrate=$arg_AudioBitrate&SubtitleMethod=$arg_SubtitleMethod&TranscodingMaxAudioChannels=$arg_TranscodingMaxAudioChannels&SegmentContainer=$arg_SegmentContainer&MinSegments=$arg_MinSegments&BreakOnNonKeyFrames=$arg_BreakOnNonKeyFrames&h264-profile=$h264Profile&h264-level=$h264Level&slicerange=$slice_range";
}

重启nginx后随便点开一个视频,然后查看设置的缓存目录是否有缓存文件,如果生成了缓存文件即为正常(不会缓存转码的视频)。

Nginx开启图片缓存

  • 如果你在Cloudflare上开启过图片缓存,则此段可以跳过

直接上Nginx配置文件:

# 这段缓存目录的声明放在http模块里面,要提前创建缓存目录,并赋予nginx权限
proxy_cache_path /var/cache/nginx/emby levels=1:2 keys_zone=emby:100m max_size=5g inactive=90d use_temp_path=off;

# 这段反向代理配置放http的server模块里面
location ~ ^/emby/Items/.*/Images/ {
  proxy_pass http://emby-backend;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header X-Forwarded-Protocol $scheme;
  proxy_set_header X-Forwarded-Host $http_host;
  proxy_set_header REMOTE-HOST $remote_addr;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "";
  proxy_set_header Accept-Encoding "";
  proxy_http_version 1.1;

  proxy_cache emby;
  proxy_cache_key $request_uri;
  proxy_cache_revalidate on;
  proxy_cache_lock on;
}

Nginx完整示例配置

proxy_cache_path  /var/cache/nginx/emby-videos levels=1:2 keys_zone=emby-videos:100m inactive=15d max_size=50g use_temp_path=off;
map $request_uri $h264Level { ~(h264-level=)(.+?)& $2; }
map $request_uri $h264Profile { ~(h264-profile=)(.+?)& $2; }

proxy_cache_path /var/cache/nginx/emby levels=1:2 keys_zone=emby:100m max_size=5g inactive=90d use_temp_path=off;

upstream emby-backend {
     server  127.0.0.1:8096;
     keepalive 1024;
}

server {
    listen 80;
    listen [::]:80;
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name emby.domain.com src-emby.domain.com;
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    error_page 497  https://$host$request_uri;

    client_body_buffer_size 512k;
    client_max_body_size 20M;
    add_header Strict-Transport-Security "max-age=15552000; preload" always;
    add_header 'Referrer-Policy' 'origin-when-cross-origin';
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;

    keepalive_timeout 120s;
    keepalive_requests 10000;

    proxy_hide_header X-Powered-By;
    proxy_buffer_size 32k;
    proxy_buffers 4 64k;
    proxy_busy_buffers_size 128k;
    proxy_temp_file_write_size 128k;
    proxy_connect_timeout 1h;
    proxy_send_timeout 1h;
    proxy_read_timeout 1h;

    location /swagger {
        return 404;
    }

    location = / {
        return 302 web/index.html;
    }

    location / {
        proxy_pass http://emby-backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Protocol $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header REMOTE-HOST $remote_addr;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "";
        proxy_set_header Accept-Encoding "";
        proxy_http_version 1.1;
        proxy_cache off;
    }

    location /web/ {
        proxy_pass http://emby-backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Protocol $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header REMOTE-HOST $remote_addr;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "";
        proxy_set_header Accept-Encoding "";
        proxy_http_version 1.1;
        # 如果你使用cloudflare或其他缓存js|css文件,可取消下一行的注释来关闭本机缓存
        # proxy_cache off;
    }

    location = /embywebsocket {
        proxy_pass http://emby-backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Protocol $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header REMOTE-HOST $remote_addr;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Accept-Encoding "";
        proxy_http_version 1.1;
        proxy_cache off;
    }

    location /emby/videos/ {
        proxy_pass http://emby-backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Protocol $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header REMOTE-HOST $remote_addr;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "";
        proxy_set_header Accept-Encoding "";
        proxy_http_version 1.1;
        proxy_cache off;
        proxy_buffering off;
    }

    location ~ ^/emby/videos/\d+/(?!live|\w+\.m3u8|hls1) {
        slice 14m;

        proxy_pass http://emby-backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Protocol $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header REMOTE-HOST $remote_addr;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "";
        proxy_set_header Accept-Encoding "";
        proxy_set_header Range $slice_range;
        proxy_ignore_headers Expires Cache-Control Set-Cookie X-Accel-Expires;
        proxy_http_version 1.1;
        proxy_connect_timeout 15s;

        proxy_cache emby-videos;
        proxy_cache_valid 200 206 301 302 7d;
        proxy_cache_lock on;
        proxy_cache_lock_age 60s;
        proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
        proxy_cache_key "$uri?MediaSourceId=$arg_MediaSourceId&VideoCodec=$arg_VideoCodec&AudioCodec=$arg_AudioCodec&AudioStreamIndex=$arg_AudioStreamIndex&VideoStreamIndex=$arg_VideoStreamIndex&ManifestSubtitles=$arg_ManifestSubtitles&VideoBitrate=$arg_VideoBitrate&AudioBitrate=$arg_AudioBitrate&SubtitleMethod=$arg_SubtitleMethod&TranscodingMaxAudioChannels=$arg_TranscodingMaxAudioChannels&SegmentContainer=$arg_SegmentContainer&MinSegments=$arg_MinSegments&BreakOnNonKeyFrames=$arg_BreakOnNonKeyFrames&h264-profile=$h264Profile&h264-level=$h264Level&slicerange=$slice_range";
    }

    location ~ ^/emby/Items/.*/Images/ {
        proxy_pass http://emby-backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Protocol $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header REMOTE-HOST $remote_addr;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "";
        proxy_set_header Accept-Encoding "";
        proxy_http_version 1.1;

        proxy_cache emby;
        proxy_cache_key $request_uri;
        proxy_cache_revalidate on;
        proxy_cache_lock on;
    }
}

使用Cloudflare缓存

众所周知,Cloudflare不允许你的视频流大量经过他们的服务器,即使你设置了绕过缓存,也算流量经过Cloudflare服务器:Section 2.8 of the Self-Serve Subscription Agreement (TOS)

但是我们希望html,css,js等文件经过Cloudflare的路由优化和缓存,那怎么办呢?

解决办法

我们可以使用两个域名,主域名开启CDN代理,次域名不开启代理,当使用主域名访问EMBY的视频流文件使,使用307重定向到次域名即可。

准备工作

  1. 主域名 emby.domain.com 开启cdn次域名 src-emby.domain.com 不开启cdn

  2. 主/次域名均已经使用Nginx反向代理到EMBY服务器

  3. Cloudflare的速度->优化->Auto Minify功能全部关闭,否则会导致各种意想不到的Bug

  4. Cloudflare的速度->优化->Rocket Loader™也要关掉,不然会导致很多js莫名其妙的Bug

  5. 反向代理Emby后如果启用了https,则需要在emby的 网络 -> 安全连接模式 选项中选择由反向代理处理

  6. 开启cdn后可正常访问emby服务器

使用Cloudflare的重定向规则实现重定向

打开Cloudflare规则->重定向规则,新建一个规则,规则名称随意

规则填写(替换域名即可),注意大小写

#表达式预览(可以复制粘贴到Cloudflare)
(http.host eq "emby.domain.com" and starts_with(http.request.uri.path, "/emby/videos")) or (http.host eq "emby.domain.com" and starts_with(http.request.uri.path, "/emby/Items") and ends_with(http.request.uri.path, "/Download"))

concat("https://src-", http.host, http.request.uri)

保存后,所有视频流的请求都会307重定向到直连源服务器的地址,就不用担心被Cloudflare查封了。

Cloudflare缓存配置:

进入Cloudflare 缓存 -> Cache Rules

创建一个规则,传入规则如下: