daemon off; user root; worker_processes 1; error_log /usr/local/nginx/logs/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { 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 /usr/local/nginx/logs/access.log main; 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; 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; } server { listen 5000; # 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 caches vod_metadata_cache metadata_cache 512m; vod_mapping_cache mapping_cache 5m 10m; # gzip manifests gzip on; gzip_types application/vnd.apple.mpegurl; # 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; location /vod/ { vod hls; secure_token $args; secure_token_types application/vnd.apple.mpegurl; add_header Access-Control-Allow-Headers '*'; add_header Access-Control-Expose-Headers 'Server,range,Content-Length,Content-Range'; add_header Access-Control-Allow-Methods 'GET, HEAD, OPTIONS'; add_header Access-Control-Allow-Origin '*'; add_header Cache-Control "no-store"; expires off; } location /stream/ { add_header Cache-Control "no-store"; expires off; add_header 'Access-Control-Allow-Origin' "$http_origin" always; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Expose-Headers' 'Content-Length'; if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' "$http_origin"; add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain charset=UTF-8'; add_header 'Content-Length' 0; return 204; } types { application/dash+xml mpd; application/vnd.apple.mpegurl m3u8; video/mp2t ts; image/jpeg jpg; } root /tmp; } location /clips/ { add_header 'Access-Control-Allow-Origin' "$http_origin" always; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Expose-Headers' 'Content-Length'; if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' "$http_origin"; add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain charset=UTF-8'; add_header 'Content-Length' 0; return 204; } types { video/mp4 mp4; image/jpeg jpg; } autoindex on; root /media/frigate; } location /cache/ { internal; # This tells nginx it's not accessible from the outside alias /tmp/cache/; } location /recordings/ { add_header 'Access-Control-Allow-Origin' "$http_origin" always; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Expose-Headers' 'Content-Length'; if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' "$http_origin"; add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain charset=UTF-8'; add_header 'Content-Length' 0; return 204; } types { video/mp4 mp4; } autoindex on; autoindex_format json; root /media/frigate; } location /ws { proxy_pass http://mqtt_ws/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header Host $host; } location /live/ { proxy_pass http://jsmpeg/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header Host $host; } location ~* /api/(.*\.(jpg|jpeg|png)$) { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; proxy_pass http://frigate_api/$1$is_args$args; proxy_pass_request_headers on; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location /api/ { add_header Cache-Control "no-store"; expires off; add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; proxy_pass http://frigate_api/; proxy_pass_request_headers on; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location / { add_header Cache-Control "no-store"; expires off; location /assets/ { access_log off; expires 1y; add_header Cache-Control "public"; } sub_filter 'href="/' 'href="$http_x_ingress_path/'; sub_filter 'url(/' 'url($http_x_ingress_path/'; sub_filter '"/dist/' '"$http_x_ingress_path/dist/'; sub_filter '"/js/' '"$http_x_ingress_path/js/'; sub_filter '' ''; sub_filter_types text/css application/javascript; sub_filter_once off; root /opt/frigate/web; try_files $uri $uri/ /index.html; } } } rtmp { server { listen 1935; chunk_size 4096; allow publish 127.0.0.1; deny publish all; allow play all; application live { live on; record off; meta copy; } } }