feat: migrate frigate to containerised instance
This commit is contained in:
parent
dab6a5127a
commit
2684ec9b75
1 changed files with 103 additions and 80 deletions
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cameras = {
|
||||
"ulfried" = {
|
||||
|
|
@ -35,8 +35,7 @@ let
|
|||
};
|
||||
};
|
||||
|
||||
# Uppercase camera name for use as systemd credential / env var name
|
||||
varName = name: lib.toUpper (lib.replaceStrings [ "-" ] [ "_" ] name);
|
||||
varName = name: "FRIGATE_" + lib.toUpper (lib.replaceStrings [ "-" ] [ "_" ] name);
|
||||
|
||||
go2rtcCameraStreams =
|
||||
name: cam:
|
||||
|
|
@ -45,11 +44,11 @@ let
|
|||
in
|
||||
{
|
||||
"${name}" = [
|
||||
"\${${varName name}_URL}"
|
||||
"{${varName name}_URL}"
|
||||
"ffmpeg:${name}#audio=opus#audio=aac${video}"
|
||||
];
|
||||
"${name}_sub" = [
|
||||
"\${${varName name}_SUB_URL}"
|
||||
"{${varName name}_SUB_URL}"
|
||||
"ffmpeg:${name}_sub#audio=opus#audio=aac${video}"
|
||||
];
|
||||
};
|
||||
|
|
@ -63,95 +62,119 @@ let
|
|||
{
|
||||
path = "rtsp://127.0.0.1:8554/${name}_sub?timeout=30";
|
||||
input_args = "preset-rtsp-restream";
|
||||
roles = [
|
||||
"detect"
|
||||
"audio"
|
||||
];
|
||||
roles = [ "detect" "audio" ];
|
||||
}
|
||||
];
|
||||
|
||||
# Only cameras with a frigate key get a frigate camera entry
|
||||
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: [
|
||||
"${varName name}_URL:${config.age.secrets."camera-${name}-url".path}"
|
||||
"${varName name}_SUB_URL:${config.age.secrets."camera-${name}-sub-url".path}"
|
||||
]) (lib.attrNames cameras);
|
||||
|
||||
services.go2rtc = {
|
||||
enable = true;
|
||||
settings = {
|
||||
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;
|
||||
};
|
||||
|
||||
services.frigate = {
|
||||
enable = true;
|
||||
vaapiDriver = "iHD";
|
||||
hostname = "kameramann.lan.baubs.net";
|
||||
settings = {
|
||||
auth.enabled = false;
|
||||
go2rtc.streams = lib.foldl' lib.mergeAttrs { } (
|
||||
lib.mapAttrsToList (name: _: {
|
||||
"${name}" = [ ];
|
||||
"${name}_sub" = [ ];
|
||||
}) 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 = "${./models/yolov9-t-320.onnx}";
|
||||
labelmap_path = "${./models/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;
|
||||
proxy.default_role = "admin";
|
||||
objects.track = [
|
||||
"person"
|
||||
"bird"
|
||||
"car"
|
||||
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"
|
||||
];
|
||||
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 = [
|
||||
5000
|
||||
1984
|
||||
80
|
||||
8555
|
||||
8554
|
||||
];
|
||||
networking.firewall.allowedTCPPorts = [ 5000 1984 8554 8555 ];
|
||||
networking.firewall.allowedUDPPorts = [ 8555 8554 ];
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue