mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-09-28 10:56:52 +03:00
The `v1.x` line is the same muxed fMP4 code as Kaltura's 1.31 with fixes backported, so the mapping JSON, manifest routes, and ffmpeg consumers are unchanged. The `MAX_CLIPS` patch applies as-is and the HEVC workaround is rewritten for the fork's reformatted source. `vod_hls_version 6` is now explicit because the fork replaced Kaltura's automatic version calculation with a directive that defaults to 4 and only warns when fmp4 needs 6, so playlists were being stamped `EXT-X-VERSION:4` while carrying `EXT-X-MAP`. The `error_page 502 =404` hack is gone: https://github.com/kaltura/nginx-vod-module/issues/468 is a `vod_mode remote` bug and we're `mapped`, so those 502s were really `_vod_response` returning 404 upstream. The fork maps that through now, and the hack was also turning real 5xx into "no recordings".
377 lines
11 KiB
Nginx Configuration File
377 lines
11 KiB
Nginx Configuration File
daemon off;
|
|
user root;
|
|
worker_processes auto;
|
|
|
|
error_log /dev/stdout warn;
|
|
pid /var/run/nginx.pid;
|
|
|
|
events {
|
|
worker_connections 1024;
|
|
}
|
|
|
|
http {
|
|
map_hash_bucket_size 256;
|
|
server_tokens off;
|
|
|
|
include mime.types;
|
|
default_type application/octet-stream;
|
|
|
|
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
|
'$status $body_bytes_sent "$http_referer" '
|
|
'"$http_user_agent" "$http_x_forwarded_for" '
|
|
'request_time="$request_time" upstream_response_time="$upstream_response_time"';
|
|
|
|
|
|
access_log /dev/stdout main;
|
|
|
|
# send headers in one piece, it is better than sending them one by one
|
|
tcp_nopush on;
|
|
|
|
sendfile on;
|
|
|
|
keepalive_timeout 65;
|
|
|
|
gzip on;
|
|
gzip_comp_level 6;
|
|
gzip_types text/plain text/css application/json application/x-javascript application/javascript text/javascript image/svg+xml image/x-icon image/bmp;
|
|
gzip_proxied no-cache no-store private expired auth;
|
|
gzip_vary on;
|
|
|
|
proxy_cache_path /dev/shm/nginx_cache levels=1:2 keys_zone=api_cache:10m max_size=10m inactive=1m use_temp_path=off;
|
|
|
|
map $sent_http_content_type $should_not_cache {
|
|
'application/json' 0;
|
|
default 1;
|
|
}
|
|
|
|
upstream frigate_api {
|
|
server 127.0.0.1:5001;
|
|
keepalive 1024;
|
|
}
|
|
|
|
upstream mqtt_ws {
|
|
server 127.0.0.1:5002;
|
|
keepalive 1024;
|
|
}
|
|
|
|
upstream jsmpeg {
|
|
server 127.0.0.1:8082;
|
|
keepalive 1024;
|
|
}
|
|
|
|
include go2rtc_upstream.conf;
|
|
|
|
server {
|
|
include listen.conf;
|
|
include security_headers.conf;
|
|
|
|
# enable HTTP/2 for TLS connections to eliminate browser 6-connection limit
|
|
http2 on;
|
|
|
|
# vod settings
|
|
vod_base_url '';
|
|
vod_segments_base_url '';
|
|
vod_mode mapped;
|
|
vod_max_mapping_response_size 1m;
|
|
vod_upstream_location /api;
|
|
vod_align_segments_to_key_frames on;
|
|
vod_manifest_segment_durations_mode accurate;
|
|
vod_ignore_edit_list on;
|
|
# short leading segments at each playlist start; sources start at
|
|
# the seek target, so the ladder applies to every seek. Only
|
|
# effective when clips declare real keyFrameDurations
|
|
vod_bootstrap_segment_durations 1000;
|
|
vod_bootstrap_segment_durations 2000;
|
|
vod_bootstrap_segment_durations 4000;
|
|
vod_segment_duration 10000;
|
|
|
|
# MPEG-TS settings (not used when fMP4 is enabled, kept for reference)
|
|
vod_hls_mpegts_align_frames off;
|
|
vod_hls_mpegts_interleave_frames on;
|
|
|
|
# file handle caching / aio
|
|
open_file_cache max=1000 inactive=5m;
|
|
open_file_cache_valid 2m;
|
|
open_file_cache_min_uses 1;
|
|
open_file_cache_errors on;
|
|
aio on;
|
|
|
|
# file upload size
|
|
client_max_body_size 20M;
|
|
|
|
# https://github.com/kaltura/nginx-vod-module#vod_open_file_thread_pool
|
|
vod_open_file_thread_pool default;
|
|
|
|
# vod caches
|
|
vod_metadata_cache metadata_cache 512m;
|
|
vod_mapping_cache mapping_cache 5m 10m;
|
|
|
|
# gzip manifests
|
|
gzip on;
|
|
gzip_types application/vnd.apple.mpegurl;
|
|
|
|
include auth_location.conf;
|
|
include base_path.conf;
|
|
|
|
location /vod/ {
|
|
include auth_request.conf;
|
|
aio threads;
|
|
vod hls;
|
|
|
|
# Use fMP4 (fragmented MP4) instead of MPEG-TS for better performance
|
|
# Smaller segments, faster generation, better browser compatibility
|
|
vod_hls_container_format fmp4;
|
|
|
|
# fMP4 playlists use EXT-X-MAP, which requires HLS protocol
|
|
# version 6 (RFC 8216 section 7); the module default is 4
|
|
vod_hls_version 6;
|
|
|
|
secure_token $args;
|
|
secure_token_types application/vnd.apple.mpegurl;
|
|
|
|
include security_headers.conf;
|
|
add_header Cache-Control "no-store";
|
|
expires off;
|
|
|
|
keepalive_disable safari;
|
|
}
|
|
|
|
location /stream/ {
|
|
include auth_request.conf;
|
|
include security_headers.conf;
|
|
add_header Cache-Control "no-store";
|
|
expires off;
|
|
|
|
types {
|
|
application/dash+xml mpd;
|
|
application/vnd.apple.mpegurl m3u8;
|
|
video/mp2t ts;
|
|
image/jpeg jpg;
|
|
}
|
|
|
|
root /tmp;
|
|
}
|
|
|
|
location /clips/ {
|
|
include auth_request.conf;
|
|
types {
|
|
video/mp4 mp4;
|
|
image/jpeg jpg;
|
|
}
|
|
|
|
expires 7d;
|
|
include security_headers.conf;
|
|
add_header Cache-Control "public";
|
|
autoindex on;
|
|
root /media/frigate;
|
|
}
|
|
|
|
location /cache/ {
|
|
internal; # This tells nginx it's not accessible from the outside
|
|
alias /tmp/cache/;
|
|
}
|
|
|
|
location /recordings/ {
|
|
include auth_request.conf;
|
|
types {
|
|
video/mp4 mp4;
|
|
}
|
|
|
|
autoindex on;
|
|
autoindex_format json;
|
|
root /media/frigate;
|
|
}
|
|
|
|
location /exports/ {
|
|
include auth_request.conf;
|
|
types {
|
|
video/mp4 mp4;
|
|
}
|
|
|
|
autoindex on;
|
|
autoindex_format json;
|
|
root /media/frigate;
|
|
}
|
|
|
|
location /ws {
|
|
include auth_request.conf;
|
|
proxy_pass http://mqtt_ws/;
|
|
include proxy.conf;
|
|
}
|
|
|
|
location /live/jsmpeg/ {
|
|
include auth_request.conf;
|
|
proxy_pass http://jsmpeg/;
|
|
include proxy.conf;
|
|
}
|
|
|
|
# frigate lovelace card uses this path
|
|
location /live/mse/api/ws {
|
|
include auth_request.conf;
|
|
limit_except GET {
|
|
deny all;
|
|
}
|
|
proxy_pass http://go2rtc/api/ws;
|
|
include proxy.conf;
|
|
}
|
|
|
|
location /live/webrtc/api/ws {
|
|
include auth_request.conf;
|
|
limit_except GET {
|
|
deny all;
|
|
}
|
|
proxy_pass http://go2rtc/api/ws;
|
|
include proxy.conf;
|
|
}
|
|
|
|
# pass through go2rtc player
|
|
location /live/webrtc/webrtc.html {
|
|
include auth_request.conf;
|
|
limit_except GET {
|
|
deny all;
|
|
}
|
|
proxy_pass http://go2rtc/webrtc.html;
|
|
include proxy.conf;
|
|
}
|
|
|
|
# integration uses this to add webrtc candidate
|
|
location /api/go2rtc/webrtc {
|
|
include auth_request.conf;
|
|
limit_except POST {
|
|
deny all;
|
|
}
|
|
proxy_pass http://go2rtc/api/webrtc;
|
|
include proxy.conf;
|
|
}
|
|
|
|
location ~* /api/.*\.(jpg|jpeg|png|webp|gif)$ {
|
|
include auth_request.conf;
|
|
rewrite ^/api/(.*)$ /$1 break;
|
|
proxy_pass http://frigate_api;
|
|
include proxy.conf;
|
|
}
|
|
|
|
location /api/ {
|
|
include auth_request.conf;
|
|
include security_headers.conf;
|
|
add_header Cache-Control "no-store";
|
|
expires off;
|
|
proxy_pass http://frigate_api/;
|
|
include proxy.conf;
|
|
|
|
proxy_cache api_cache;
|
|
proxy_cache_key "$scheme$proxy_host$request_uri|$role|$groups|$user";
|
|
proxy_cache_lock on;
|
|
proxy_cache_use_stale updating;
|
|
proxy_cache_valid 200 5s;
|
|
proxy_cache_bypass $http_x_cache_bypass;
|
|
proxy_no_cache $should_not_cache;
|
|
add_header X-Cache-Status $upstream_cache_status;
|
|
|
|
location /api/vod/ {
|
|
include auth_request.conf;
|
|
proxy_pass http://frigate_api/vod/;
|
|
include proxy.conf;
|
|
proxy_cache off;
|
|
}
|
|
|
|
location /api/login {
|
|
auth_request off;
|
|
rewrite ^/api(/.*)$ $1 break;
|
|
proxy_pass http://frigate_api;
|
|
include proxy.conf;
|
|
}
|
|
|
|
location /api/logout {
|
|
auth_request off;
|
|
rewrite ^/api(/.*)$ $1 break;
|
|
proxy_pass http://frigate_api;
|
|
include proxy.conf;
|
|
}
|
|
|
|
# Allow unauthenticated access to the first_time_login endpoint
|
|
# so the login page can load help text before authentication.
|
|
location /api/auth/first_time_login {
|
|
auth_request off;
|
|
limit_except GET {
|
|
deny all;
|
|
}
|
|
rewrite ^/api(/.*)$ $1 break;
|
|
proxy_pass http://frigate_api;
|
|
include proxy.conf;
|
|
}
|
|
|
|
location /api/stats {
|
|
include auth_request.conf;
|
|
access_log off;
|
|
rewrite ^/api(/.*)$ $1 break;
|
|
proxy_pass http://frigate_api;
|
|
include proxy.conf;
|
|
}
|
|
|
|
location /api/version {
|
|
include auth_request.conf;
|
|
access_log off;
|
|
rewrite ^/api(/.*)$ $1 break;
|
|
proxy_pass http://frigate_api;
|
|
include proxy.conf;
|
|
}
|
|
}
|
|
|
|
location / {
|
|
# do not require auth for static assets
|
|
include security_headers.conf;
|
|
add_header Cache-Control "no-store";
|
|
expires off;
|
|
|
|
location /assets/ {
|
|
access_log off;
|
|
expires 1y;
|
|
include security_headers.conf;
|
|
add_header Cache-Control "public";
|
|
}
|
|
|
|
location /fonts/ {
|
|
access_log off;
|
|
expires 1y;
|
|
include security_headers.conf;
|
|
add_header Cache-Control "public";
|
|
}
|
|
|
|
location /locales/ {
|
|
access_log off;
|
|
include security_headers.conf;
|
|
add_header Cache-Control "public";
|
|
}
|
|
|
|
location ~ ^/.*-([A-Za-z0-9]+)\.webmanifest$ {
|
|
access_log off;
|
|
expires 1y;
|
|
include security_headers.conf;
|
|
add_header Cache-Control "public";
|
|
default_type application/json;
|
|
proxy_set_header Accept-Encoding "";
|
|
sub_filter_once off;
|
|
sub_filter_types application/json;
|
|
sub_filter '"start_url": "/BASE_PATH/"' '"start_url" : "$http_x_ingress_path/"';
|
|
sub_filter '"src": "/BASE_PATH/' '"src": "$http_x_ingress_path/';
|
|
}
|
|
|
|
sub_filter 'href="/BASE_PATH/' 'href="$http_x_ingress_path/';
|
|
sub_filter 'url(/BASE_PATH/' 'url($http_x_ingress_path/';
|
|
sub_filter '"/BASE_PATH/dist/' '"$http_x_ingress_path/dist/';
|
|
sub_filter '"/BASE_PATH/js/' '"$http_x_ingress_path/js/';
|
|
sub_filter '"/BASE_PATH/assets/' '"$http_x_ingress_path/assets/';
|
|
sub_filter '"/BASE_PATH/locales/' '"$http_x_ingress_path/locales/';
|
|
sub_filter '"/BASE_PATH/monacoeditorwork/' '"$http_x_ingress_path/assets/';
|
|
sub_filter 'return"/BASE_PATH/"' 'return window.baseUrl';
|
|
sub_filter '<body>' '<body><script>window.baseUrl="$http_x_ingress_path/";</script>';
|
|
sub_filter_types text/css application/javascript;
|
|
sub_filter_once off;
|
|
|
|
root /opt/frigate/web;
|
|
try_files $uri $uri.html $uri/ /index.html;
|
|
}
|
|
}
|
|
}
|