CrOS/modules/services/frigate/default.nix
2025-09-16 11:18:37 -04:00

207 lines
5.3 KiB
Nix

let
volumePath = "/overseer/services";
in
{
pkgs,
lib,
config,
...
}: let
frigateConfig = pkgs.writeText "config.yaml" (lib.generators.toYAML {} {
auth.reset_admin_password = true; # roll the admin password every restart, depend on user accounts for long-lived access
tls.enabled = false; # off because we're doing ssl through the proxy
mqtt = {
enabled = true;
host = "host.containers.internal";
port = 1883;
};
notifications = {
enabled = true;
email = "frigate@wanderingcrow.net";
};
###################
# go2rtc restream #
###################
go2rtc = {
streams = {
wce-0001 = [
"rtsp://thingino:thingino@192.168.150.1:554/ch0"
];
wce-0001_sub = [
"rtsp://thingino:thingino@192.168.150.1:554/ch1"
];
wce-0002 = [
"rtsp://thingino:thingino@192.168.150.2:554/ch0"
];
wce-0002_sub = [
"rtsp://thingino:thingino@192.168.150.2:554/ch1"
];
wce-0003 = [
"rtsp://thingino:thingino@192.168.150.3:554/ch0"
];
wce-0003_sub = [
"rtsp://thingino:thingino@192.168.150.3:554/ch1"
];
};
};
#############
# Detectors #
#############
detectors = {
coral = {
type = "edgetpu";
device = "usb";
};
};
objects = {
track = [
"person"
"cat"
"dog"
];
};
review = {
alerts = {
labels = [
"person"
"cat"
];
};
};
####################
# Data Persistence #
####################
record = {
enabled = true;
retain.days = 0; # as per official documentation
alerts = {
retain.days = 14;
};
detections = {
retain.days = 14;
};
};
#################
# Camera config #
#################
cameras = {
wce-0001 = {
ffmpeg = {
inputs = [
{
path = "rtsp://127.0.0.1:8554/wce-0001";
roles = ["record"];
}
{
path = "rtsp://127.0.0.1:8554/wce-0001_sub";
roles = ["detect"];
}
];
};
live.stream_name = "wce-0001_sub";
motion = {
enabled = true;
mask = [
"0,0,0.196,0.002,0.195,0.045,0,0.043" # timestamp
"0.898,0,0.896,0.045,1,0.048,0.999,0.002" # uptime
];
};
detect.enabled = true;
};
wce-0002 = {
ffmpeg = {
inputs = [
{
path = "rtsp://127.0.0.1:8554/wce-0002";
roles = ["record"];
}
{
path = "rtsp://127.0.0.1:8554/wce-0002_sub";
roles = ["detect"];
}
];
};
live.stream_name = "wce-0002_sub";
motion = {
enabled = true;
mask = [
"0,0,0.196,0.002,0.195,0.045,0,0.043" # timestamp
"0.898,0,0.896,0.045,1,0.048,0.999,0.002" # uptime
];
};
detect.enabled = true;
};
wce-0003 = {
ffmpeg = {
inputs = [
{
path = "rtsp://127.0.0.1:8554/wce-0003";
roles = ["record"];
}
{
path = "rtsp://127.0.0.1:8554/wce-0003_sub";
roles = ["detect"];
}
];
};
live.stream_name = "wce-0003_sub";
motion = {
enabled = true;
mask = [
"0,0,0.196,0.002,0.195,0.045,0,0.043" # timestamp
"0.898,0,0.896,0.045,1,0.048,0.999,0.002" # uptime
];
};
detect.enabled = true;
};
};
});
in {
sops = {
templates."frigate_env".content = ''
FRIGATE_JWT_SECRET=${config.sops.placeholder."frigate/jwt"}
'';
secrets = {
"frigate/jwt" = {};
};
};
systemd.tmpfiles.rules = [
"d ${volumePath}/frigate"
"d ${volumePath}/frigate/media/frigate"
"d ${volumePath}/frigate/db"
"f ${volumePath}/frigate/db/frigate.db"
];
###########
# Service #
###########
virtualisation.oci-containers = {
backend = "podman";
containers = {
"frigate" = {
image = "ghcr.io/blakeblackshear/frigate:stable";
environmentFiles = [config.sops.templates."frigate_env".path];
volumes = [
"/etc/localtime:/etc/localtime:ro"
"${volumePath}/frigate/media/frigate:/media/frigate"
"${frigateConfig}:/config/config.yaml:ro"
"${volumePath}/frigate/db/frigate.db:/config/frigate.db"
];
extraOptions = [
"--shm-size=612m"
"--ip=10.88.0.10"
];
devices = [
"/dev/bus/usb:/dev/bus/usb"
];
};
};
};
services.caddy = {
enable = true;
virtualHosts."frigate.wanderingcrow.net".extraConfig = ''
reverse_proxy http://10.88.0.10:8971
'';
};
}