{ config, lib, pkgs, ... }: let cameras = { "ulfried" = { frigate.record = { enabled = true; continuous.days = 0; alerts.retain = { days = 30; mode = "motion"; }; }; }; "gnisbert" = { }; "taubis" = { frigate = { detect.enabled = false; record = { enabled = true; continuous.days = 1; detections.retain.days = 7; }; }; }; "foeff" = { videoPassthrough = true; frigate.record = { enabled = true; continuous.days = 0; alerts.retain = { days = 30; mode = "motion"; }; }; }; }; varName = name: "FRIGATE_" + lib.toUpper (lib.replaceStrings [ "-" ] [ "_" ] name); go2rtcCameraStreams = name: cam: let video = lib.optionalString (cam.videoPassthrough or false) "#video=copy"; in { "${name}" = [ "{${varName name}_URL}" "ffmpeg:${name}#audio=opus#audio=aac${video}" ]; "${name}_sub" = [ "{${varName name}_SUB_URL}" "ffmpeg:${name}_sub#audio=opus#audio=aac${video}" ]; }; frigateInputs = name: [ { path = "rtsp://127.0.0.1:8554/${name}?timeout=30"; input_args = "preset-rtsp-generic"; roles = [ "record" ]; } { path = "rtsp://127.0.0.1:8554/${name}_sub?timeout=30"; input_args = "preset-rtsp-restream"; roles = [ "detect" "audio" ]; } ]; frigCameras = lib.filterAttrs (_: cam: cam ? frigate) cameras; frigateConfig = { auth.enabled = false; proxy.default_role = "admin"; go2rtc = { rtsp.listen = ":8554"; webrtc.listen = ":8555"; streams = lib.foldl' lib.mergeAttrs { } (lib.mapAttrsToList go2rtcCameraStreams cameras); }; mqtt = { enabled = true; host = "192.168.178.33"; user = "frigate"; password = "frigate"; }; ffmpeg.hwaccel_args = "preset-vaapi"; detectors.ov_0 = { type = "openvino"; device = "GPU"; }; model = { model_type = "yolo-generic"; width = 320; height = 320; input_tensor = "nchw"; input_dtype = "float"; path = "/config/model_cache/yolov9-t-320.onnx"; labelmap_path = "/labelmap/coco-80.txt"; }; detect.enabled = true; snapshots.enabled = true; semantic_search = { enabled = false; model_size = "small"; }; face_recognition = { enabled = true; model_size = "large"; }; lpr.enabled = false; objects.track = [ "person" "bird" "car" ]; telemetry.stats.intel_gpu_device = "sys:/sys/devices/pci0000:00/0000:00:02.0"; classification.bird.enabled = true; cameras = lib.mapAttrs ( name: cam: cam.frigate // { ffmpeg.inputs = frigateInputs name; } ) frigCameras; }; configFile = (pkgs.formats.yaml { }).generate "frigate-config.yml" frigateConfig; in { age.secrets = lib.mkMerge ( lib.mapAttrsToList (name: _: { "camera-${name}-url".file = ../../secrets/camera-${name}-url.age; "camera-${name}-sub-url".file = ../../secrets/camera-${name}-sub-url.age; }) cameras ); # Assemble env file from individual agenix secrets for the container systemd.services.frigate-env = { description = "Generate Frigate environment file from secrets"; before = [ "podman-frigate.service" ]; requiredBy = [ "podman-frigate.service" ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; }; script = '' umask 077 { ${lib.concatMapStringsSep "\n" (name: '' printf '%s=%s\n' "${varName name}_URL" "$(cat ${config.age.secrets."camera-${name}-url".path})" printf '%s=%s\n' "${varName name}_SUB_URL" "$(cat ${config.age.secrets."camera-${name}-sub-url".path})" '') (lib.attrNames cameras)} } > /run/frigate-env ''; }; systemd.tmpfiles.rules = [ "d /var/lib/frigate 0755 root root -" "d /var/lib/frigate-media 0755 root root -" ]; virtualisation.podman.enable = true; virtualisation.oci-containers = { backend = "podman"; containers.frigate = { image = "ghcr.io/blakeblackshear/frigate:stable"; autoStart = true; volumes = [ "/var/lib/frigate:/config" "${configFile}:/config/config.yml:ro" "${./models/yolov9-t-320.onnx}:/config/model_cache/yolov9-t-320.onnx:ro" "${./models/coco-80.txt}:/labelmap/coco-80.txt:ro" "/var/lib/frigate-media:/media/frigate" ]; environment.LIBVA_DRIVER_NAME = "iHD"; environmentFiles = [ /run/frigate-env ]; ports = [ "5000:5000" #"8971:8971" "1984:1984" "8554:8554" "8555:8555/tcp" "8555:8555/udp" ]; extraOptions = [ "--shm-size=512m" "--mount=type=tmpfs,target=/tmp/cache,tmpfs-size=1000000000" "--device=/dev/dri/renderD128:/dev/dri/renderD128" ]; }; }; networking.firewall.allowedTCPPorts = [ 5000 1984 8554 8555 ]; networking.firewall.allowedUDPPorts = [ 8555 8554 ]; }