feat: migrate frigate to containerised instance

This commit is contained in:
Jan-Henrik 2026-04-19 23:31:07 +02:00
parent dab6a5127a
commit 2684ec9b75

View file

@ -1,4 +1,4 @@
{ config, lib, ... }: { config, lib, pkgs, ... }:
let let
cameras = { cameras = {
"ulfried" = { "ulfried" = {
@ -35,8 +35,7 @@ let
}; };
}; };
# Uppercase camera name for use as systemd credential / env var name varName = name: "FRIGATE_" + lib.toUpper (lib.replaceStrings [ "-" ] [ "_" ] name);
varName = name: lib.toUpper (lib.replaceStrings [ "-" ] [ "_" ] name);
go2rtcCameraStreams = go2rtcCameraStreams =
name: cam: name: cam:
@ -45,11 +44,11 @@ let
in in
{ {
"${name}" = [ "${name}" = [
"\${${varName name}_URL}" "{${varName name}_URL}"
"ffmpeg:${name}#audio=opus#audio=aac${video}" "ffmpeg:${name}#audio=opus#audio=aac${video}"
]; ];
"${name}_sub" = [ "${name}_sub" = [
"\${${varName name}_SUB_URL}" "{${varName name}_SUB_URL}"
"ffmpeg:${name}_sub#audio=opus#audio=aac${video}" "ffmpeg:${name}_sub#audio=opus#audio=aac${video}"
]; ];
}; };
@ -63,95 +62,119 @@ let
{ {
path = "rtsp://127.0.0.1:8554/${name}_sub?timeout=30"; path = "rtsp://127.0.0.1:8554/${name}_sub?timeout=30";
input_args = "preset-rtsp-restream"; input_args = "preset-rtsp-restream";
roles = [ roles = [ "detect" "audio" ];
"detect"
"audio"
];
} }
]; ];
# Only cameras with a frigate key get a frigate camera entry
frigCameras = lib.filterAttrs (_: cam: cam ? frigate) cameras; frigCameras = lib.filterAttrs (_: cam: cam ? frigate) cameras;
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
);
systemd.services.go2rtc.serviceConfig.LoadCredential = lib.concatMap (name: [ frigateConfig = {
"${varName name}_URL:${config.age.secrets."camera-${name}-url".path}" auth.enabled = false;
"${varName name}_SUB_URL:${config.age.secrets."camera-${name}-sub-url".path}" proxy.default_role = "admin";
]) (lib.attrNames cameras); go2rtc = {
services.go2rtc = {
enable = true;
settings = {
rtsp.listen = ":8554"; rtsp.listen = ":8554";
webrtc.listen = ":8555"; webrtc.listen = ":8555";
streams = lib.foldl' lib.mergeAttrs { } (lib.mapAttrsToList go2rtcCameraStreams cameras); 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;
}; };
services.frigate = { configFile = (pkgs.formats.yaml { }).generate "frigate-config.yml" frigateConfig;
enable = true; in
vaapiDriver = "iHD"; {
hostname = "kameramann.lan.baubs.net"; age.secrets = lib.mkMerge (
settings = { lib.mapAttrsToList (name: _: {
auth.enabled = false; "camera-${name}-url".file = ../../secrets/camera-${name}-url.age;
go2rtc.streams = lib.foldl' lib.mergeAttrs { } ( "camera-${name}-sub-url".file = ../../secrets/camera-${name}-sub-url.age;
lib.mapAttrsToList (name: _: { }) cameras
"${name}" = [ ]; );
"${name}_sub" = [ ];
}) cameras # Assemble env file from individual agenix secrets for the container
); systemd.services.frigate-env = {
mqtt = { description = "Generate Frigate environment file from secrets";
enabled = true; before = [ "podman-frigate.service" ];
host = "192.168.178.33"; requiredBy = [ "podman-frigate.service" ];
user = "frigate"; serviceConfig = {
password = "frigate"; Type = "oneshot";
}; RemainAfterExit = true;
ffmpeg.hwaccel_args = "preset-vaapi"; };
detectors.ov_0 = { script = ''
type = "openvino"; umask 077
device = "GPU"; {
}; ${lib.concatMapStringsSep "\n" (name: ''
model = { printf '%s=%s\n' "${varName name}_URL" "$(cat ${config.age.secrets."camera-${name}-url".path})"
model_type = "yolo-generic"; printf '%s=%s\n' "${varName name}_SUB_URL" "$(cat ${config.age.secrets."camera-${name}-sub-url".path})"
width = 320; '') (lib.attrNames cameras)}
height = 320; } > /run/frigate-env
input_tensor = "nchw"; '';
input_dtype = "float"; };
path = "${./models/yolov9-t-320.onnx}";
labelmap_path = "${./models/coco-80.txt}"; systemd.tmpfiles.rules = [
}; "d /var/lib/frigate 0755 root root -"
detect.enabled = true; "d /var/lib/frigate-media 0755 root root -"
snapshots.enabled = true; ];
semantic_search = { enabled = false; model_size = "small"; };
face_recognition = { enabled = true; model_size = "large"; }; virtualisation.podman.enable = true;
lpr.enabled = false; virtualisation.oci-containers = {
proxy.default_role = "admin"; backend = "podman";
objects.track = [ containers.frigate = {
"person" image = "ghcr.io/blakeblackshear/frigate:stable";
"bird" autoStart = true;
"car" 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"
]; ];
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;
}; };
}; };
networking.firewall.allowedTCPPorts = [ networking.firewall.allowedTCPPorts = [ 5000 1984 8554 8555 ];
5000
1984
80
8555
8554
];
networking.firewall.allowedUDPPorts = [ 8555 8554 ]; networking.firewall.allowedUDPPorts = [ 8555 8554 ];
} }