config

NixOS config
Log | Files | Refs | README | LICENSE

default.nix (6793B) - Raw


      1 {
      2   lib,
      3   pkgs,
      4   config,
      5   ...
      6 }:
      7 let
      8   cfg = config.mj.services.frigate;
      9   sklypas = "0.312,1,0.311,0.269,0.354,0.172,0.396,0.154,0.431,0.102,0.495,0.044,0.61,0.039,0.774,0.097,0.837,0.219,0.758,0.995";
     10 
     11   proberScript = pkgs.writeShellApplication {
     12     name = "go2rtc-prober";
     13     runtimeInputs = with pkgs; [
     14       systemd
     15       ffmpeg_7-headless
     16     ];
     17     text = ''
     18       set -x
     19       while true; do
     20         FAILED=0
     21 
     22         for input in vno4-dome-{panorama,ptz}-{orig,high,low}; do
     23           timeout 30s \
     24             ffprobe -hide_banner "rtsp://localhost:8554/''${input}" || FAILED=1
     25         done
     26 
     27         [[ "$FAILED" == 1 ]] && systemctl restart --no-block go2rtc.service
     28 
     29         sleep 5m
     30       done
     31     '';
     32   };
     33 in
     34 {
     35   options.mj.services.frigate = with lib.types; {
     36     enable = lib.mkEnableOption "enable frigate";
     37     secretsEnv = lib.mkOption { type = path; };
     38   };
     39 
     40   config = lib.mkIf cfg.enable {
     41     mj.base.unitstatus.units = [
     42       "go2rtc"
     43       "frigate"
     44     ];
     45 
     46     systemd.services = {
     47       go2rtc-prober = {
     48         wantedBy = [ "multi-user.target" ];
     49         serviceConfig = {
     50           ExecStart = lib.getExe proberScript;
     51           RestartSec = 300;
     52           Restart = "always";
     53         };
     54       };
     55       go2rtc = {
     56         preStart = "ln -sf $CREDENTIALS_DIRECTORY/secrets.env /run/go2rtc/secrets.env";
     57         environment = {
     58           # Set HOME so Mesa can find cache directory
     59           HOME = "/var/cache/go2rtc";
     60           # Force AMD VAAPI driver
     61           LIBVA_DRIVER_NAME = "radeonsi";
     62         };
     63         serviceConfig = {
     64           EnvironmentFile = [ "-/run/go2rtc/secrets.env" ];
     65           RuntimeDirectory = "go2rtc";
     66           CacheDirectory = "go2rtc"; # Mesa shader cache at /var/cache/go2rtc
     67           LoadCredential = [ "secrets.env:${cfg.secretsEnv}" ];
     68           # Ensure access to GPU devices
     69           SupplementaryGroups = [
     70             "render"
     71             "video"
     72           ];
     73         };
     74       };
     75     };
     76 
     77     services.go2rtc = {
     78       enable = true;
     79       settings = {
     80         # Pin to FFmpeg 7 due to FFmpeg 8 RTSP issues in NixOS 25.11
     81         # https://github.com/NixOS/nixpkgs/blob/master/doc/release-notes/rl-2511.section.md#L351
     82         ffmpeg.bin = lib.getExe pkgs.ffmpeg_7-headless;
     83 
     84         # https://github.com/AlexxIT/go2rtc/issues/831
     85         #log = {
     86         #  format = "text";
     87         #  level = "trace";
     88         #};
     89         streams = {
     90           "vno4-dome-panorama-orig" = [
     91             "ffmpeg:rtsp://frigate:\${FRIGATE_RTSP_PASSWORD}@192.168.188.10/cam/realmonitor?channel=1&subtype=2"
     92           ];
     93           "vno4-dome-panorama-high" = [
     94             "ffmpeg:rtsp://localhost:8554/vno4-dome-panorama-orig#hardware=vaapi#video=h264"
     95           ];
     96           "vno4-dome-panorama-low" = [
     97             "ffmpeg:rtsp://localhost:8554/vno4-dome-panorama-orig#hardware=vaapi#video=h264#width=1280"
     98           ];
     99           "vno4-dome-ptz-orig" = [
    100             "ffmpeg:rtsp://frigate:\${FRIGATE_RTSP_PASSWORD}@192.168.188.10/cam/realmonitor?channel=2&subtype=2#video=copy#audio=copy"
    101           ];
    102           "vno4-dome-ptz-high" = [
    103             "ffmpeg:rtsp://localhost:8554/vno4-dome-ptz-orig#hardware=vaapi#video=h264#audio=copy"
    104           ];
    105           "vno4-dome-ptz-low" = [
    106             "ffmpeg:rtsp://localhost:8554/vno4-dome-ptz-orig#hardware=vaapi#video=h264#width=1280#audio=copy"
    107           ];
    108         };
    109       };
    110     };
    111 
    112     services.frigate = {
    113       enable = true;
    114       hostname = "r1.jakstys.lt";
    115       vaapiDriver = "radeonsi"; # AMD GPU VAAPI driver
    116       settings = {
    117         #ui.strftime_fmt = "%F %T";
    118         # Pin to FFmpeg 7 due to FFmpeg 8 RTSP issues in NixOS 25.11
    119         ffmpeg.path = pkgs.ffmpeg_7-headless;
    120         ffmpeg.hwaccel_args = "preset-vaapi";
    121         telemetry.version_check = false;
    122 
    123         mqtt = {
    124           enabled = true;
    125           host = "::";
    126         };
    127 
    128         detect = {
    129           enabled = true;
    130           fps = 5;
    131         };
    132 
    133         detectors = {
    134           coral = {
    135             type = "edgetpu";
    136             device = "usb";
    137             enabled = true;
    138           };
    139         };
    140 
    141         record = {
    142           enabled = true;
    143           sync_recordings = true;
    144           retain = {
    145             days = 2;
    146             mode = "all";
    147           };
    148           alerts = {
    149             retain = {
    150               days = 5;
    151               mode = "motion";
    152             };
    153           };
    154           detections = {
    155             retain = {
    156               days = 5;
    157               mode = "motion";
    158             };
    159           };
    160         };
    161 
    162         cameras = {
    163           vno4-dome-panorama =
    164             let
    165               masks = [
    166                 "0.269,0.285,0.235,0.567,0.194,0.634,0.095,1,0,1,0,0,0.321,0,0.323,0.222"
    167                 "0.766,1,0.855,0.123,0.818,0.104,0.818,0,1,0,1,1"
    168               ];
    169             in
    170             {
    171               enabled = true;
    172               motion.mask = masks;
    173               objects = {
    174                 mask = masks;
    175                 track = [
    176                   "bicycle"
    177                   "car"
    178                   "person"
    179                 ];
    180               };
    181               zones.sklypas.coordinates = sklypas;
    182 
    183               review = {
    184                 alerts.required_zones = [ "sklypas" ];
    185                 detections.required_zones = [ "sklypas" ];
    186               };
    187 
    188               ffmpeg = {
    189                 output_args = {
    190                   record = "preset-record-generic";
    191                 };
    192                 inputs = [
    193                   {
    194                     path = "rtsp://localhost:8554/vno4-dome-panorama-high";
    195                     roles = [ "record" ];
    196                   }
    197                   {
    198                     path = "rtsp://localhost:8554/vno4-dome-panorama-low";
    199                     roles = [ "detect" ];
    200                   }
    201                 ];
    202               };
    203             };
    204 
    205           vno4-dome-ptz =
    206             let
    207               masks = [ "0.666,0.095,1,0.095,1,0,0.666,0" ];
    208             in
    209             {
    210               enabled = true;
    211               motion.mask = masks;
    212               objects.mask = masks;
    213 
    214               audio = {
    215                 enabled = true;
    216                 #listen = [ "speech" ];
    217               };
    218 
    219               ffmpeg = {
    220                 output_args = {
    221                   record = "preset-record-generic-audio-copy";
    222                 };
    223                 inputs = [
    224                   {
    225                     path = "rtsp://localhost:8554/vno4-dome-ptz-high";
    226                     roles = [
    227                       "record"
    228                       "audio"
    229                     ];
    230                   }
    231                   {
    232                     path = "rtsp://localhost:8554/vno4-dome-ptz-low";
    233                     roles = [ "detect" ];
    234                   }
    235                 ];
    236               };
    237             };
    238         };
    239 
    240       };
    241     };
    242 
    243   };
    244 }