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; 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"'; 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 image/png image/gif image/jpeg image/jpg; 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; # 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; vod_segment_duration 10000; 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; # 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; location /vod/ { include auth_request.conf; aio threads; vod hls; secure_token $args; secure_token_types application/vnd.apple.mpegurl; add_header Cache-Control "no-store"; expires off; keepalive_disable safari; } location /stream/ { include auth_request.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; 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; } # frontend uses this to fetch the version location /api/go2rtc/api { include auth_request.conf; limit_except GET { deny all; } proxy_pass http://go2rtc/api; 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; add_header Cache-Control "no-store"; expires off; proxy_pass http://frigate_api/; include proxy.conf; proxy_cache api_cache; 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; client_max_body_size 10M; 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/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 add_header Cache-Control "no-store"; expires off; location /assets/ { access_log off; expires 1y; add_header Cache-Control "public"; } 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/monacoeditorwork/' '"$http_x_ingress_path/assets/'; sub_filter 'return"/BASE_PATH/"' 'return window.baseUrl'; sub_filter '' ''; sub_filter_types text/css application/javascript; sub_filter_once off; root /opt/frigate/web; try_files $uri $uri.html $uri/ /index.html; } } }