daemon off;
user root;
worker_processes auto;

error_log /dev/stdout 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 /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;

    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;
    }

    upstream go2rtc {
        server 127.0.0.1:1984;
        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_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;

        location /vod/ {
            aio threads;
            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 /exports/ {
            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/jsmpeg/ {
            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 /live/mse/ {
            proxy_pass http://go2rtc/;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
            proxy_set_header Host $host;
        }

        location /live/webrtc/ {
            proxy_pass http://go2rtc/;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
            proxy_set_header Host $host;
        }

        location ~* /api/go2rtc([/]?.*)$ {
            proxy_pass http://go2rtc;
            rewrite ^/api/go2rtc(.*)$ /api$1 break;
            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';
            rewrite ^/api/(.*)$ $1 break;
            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 /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';
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
            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="/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 '<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/ /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;
        }
    }
}