diff --git a/modules/nixos/services/frigate/default.nix b/modules/nixos/services/frigate/default.nix new file mode 100644 index 0000000..868dbcf --- /dev/null +++ b/modules/nixos/services/frigate/default.nix @@ -0,0 +1,126 @@ +{ + config, + lib, + namespace, + ... +}: +let + cfg = config.${namespace}.services.frigate; +in +{ + options.${namespace}.services.frigate = { + enable = lib.mkEnableOption "Frigate NVR"; + + acmeCertName = lib.mkOption { + type = lib.types.str; + default = ""; + description = '' + If set to a non-empty string, forces SSL with the supplied acme + certificate. + ''; + }; + + hostname = lib.mkOption { + type = lib.types.str; + default = "frigate.kilonull.com"; + description = '' + The hostname for the Frigate web interface. + ''; + }; + + port = lib.mkOption { + type = lib.types.port; + default = 8971; + description = '' + The port on which Frigate's web interface will listen. + ''; + }; + + openFirewall = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Whether to open the firewall for HTTP/HTTPS traffic. + ''; + }; + }; + + config = + let + setEnvVars = '' + export FRIGATE_MQTT_PASSWORD=$(cat ${config.age.secrets.frigate_mqtt.path}) + ''; + in + lib.mkIf cfg.enable { + age.secrets.frigate_mqtt.file = ../../../../secrets/frigate_mqtt.age; + + systemd.services.frigate.preStart = setEnvVars; + services.frigate.preCheckConfig = setEnvVars; + + services.frigate = { + enable = true; + hostname = cfg.hostname; + settings = { + # Basic Frigate configuration + mqtt = { + enabled = true; + host = "192.168.113.42"; + port = 1883; + user = "frigate"; + password = "{FRIGATE_MQTT_PASSWORD}"; + }; + + # TLS terminated at reverse proxy (nginx) + tls.enabled = false; + + go2rtc.streams = { + video_doorbell = [ + "ffmpeg:http://reolink_ip/flv?port=1935&app=bcs&stream=channel0_main.bcs&user=username&password=password#video=copy#audio=copy#audio=opus" + "rtsp://username:password@reolink_ip/Preview_01_sub" + ]; + video_doorbell_sub = [ + "ffmpeg:http://reolink_ip/flv?port=1935&app=bcs&stream=channel0_ext.bcs&user=username&password=password" + "rtsp://username:password@reolink_ip/Preview_01_sub" + ]; + }; + go2rtc.webrtc.candidates = [ + "192.168.113.69:8555" + # "gospel:8555" + ]; + + cameras = { + video_doorbell.ffmpeg.inputs = [ + { + + path = "rtsp://127.0.0.1:8554/video_doorbell"; + input_args = "preset-rtsp-restream"; + roles = [ "record" ]; + } + + { + path = "rtsp://127.0.0.1:8554/video_doorbell_sub"; + input_args = "preset-rtsp-restream"; + roles = [ "detect" ]; + } + ]; + }; + }; + }; + + services.nginx = { + enable = true; + virtualHosts.${cfg.hostname} = lib.mkIf (cfg.acmeCertName != "") { + forceSSL = true; + useACMEHost = cfg.acmeCertName; + }; + }; + + networking.firewall = lib.mkIf cfg.openFirewall { + allowedTCPPorts = [ + 80 + 443 + 855 + ]; + }; + }; +} diff --git a/modules/nixos/services/mosquitto/default.nix b/modules/nixos/services/mosquitto/default.nix index ef95b2b..6f43548 100644 --- a/modules/nixos/services/mosquitto/default.nix +++ b/modules/nixos/services/mosquitto/default.nix @@ -15,6 +15,7 @@ in hass_mqtt.file = ../../../../secrets/hass_mqtt.age; teslamate_mqtt.file = ../../../../secrets/teslamate_mqtt.age; zigbee2mqtt_mqtt.file = ../../../../secrets/zigbee2mqtt_mqtt.age; + frigate_mqtt.file = ../../../../secrets/frigate_mqtt.age; }; services.mosquitto = { @@ -43,6 +44,10 @@ in ]; passwordFile = config.age.secrets.zigbee2mqtt_mqtt.path; }; + frigate = { + acl = [ "readwrite frigate/#" ]; + passwordFile = config.age.secrets.frigate_mqtt.path; + }; }; } ]; diff --git a/secrets/frigate_mqtt.age b/secrets/frigate_mqtt.age new file mode 100644 index 0000000..dd586cf --- /dev/null +++ b/secrets/frigate_mqtt.age @@ -0,0 +1,15 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IHQ1WElHQSBKQWc1 +V3l2Z1dzbDY3a3J5ZEkrNG1BWE0yN29kS2c0dys3ZWlCSDh4RzNJCnJlclQ4QzFL +elczZ29raXJMRTdhdTUzdzdvdEhCV2oycTVKQ0dSNlBhVUEKLT4gc3NoLWVkMjU1 +MTkgekJMRFpnIFRTd3ZIenZ6K25CQnRWL2pMajJVQ1U5NDNDemNIZ0E3cVFKRy8v +RzhyaW8KeTJYYjRRNzFpdXE5eTJYRW9wSTVoM09SS0h2aXlySHFFLzJDbXBSc1JI +OAotPiBwaXYtcDI1NiBVSUVHemcgQXlGVHJuU09EM2FUSDFpZy9pTEdqQWltL1Jl +aWpHMWRJbHFkSWZCWWdjRXUKRDRkV3pDY3lmRzNCaGtrL0ZtMFdWdXVySHdZS0ln +SjNtdEFrQzlLTUVsWQotPiBnVDRmLWdyZWFzZSBUOF1nbXdweiB3b1k5IF58aiNH +PQowQTRsWDFlVXFSbkZnZmJDczNLZ284b29JVFFRSmJzOGpNNDJTQlpJTEkvUjAx +cFlrcVErQlN3eHhzWERtWDRYCkJPQ21BL3dGUVF5NGlkcC9xdVV5WDk3UTZwclFk +ZEJEUmN4QWxiTDUzdlREY3BpZTdvTWhLZwotLS0gaEw0UmVPalVXVHRzOUxLUDh4 +bWpEeUtIN0gxRU54VldNeE9NRCtCTVd2QQrgAsqGfYSyORhEGrgkGS19MkXP8Xfc +GIaAcpDywO9MOi2BTUmlfqnRZkexRxQkKijc +-----END AGE ENCRYPTED FILE----- diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 8a0b8a7..e5a8dd7 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -67,6 +67,11 @@ in machines.node machines.gospel ]; + "frigate_mqtt.age".publicKeys = [ + users.me + machines.pi4 + machines.gospel + ]; "zigbee2mqtt_mqtt.age".publicKeys = [ users.me tmp diff --git a/systems/x86_64-linux/gospel/default.nix b/systems/x86_64-linux/gospel/default.nix index 06df61b..eb9fe06 100644 --- a/systems/x86_64-linux/gospel/default.nix +++ b/systems/x86_64-linux/gospel/default.nix @@ -53,6 +53,10 @@ enable = true; acmeCertName = "kilonull.com"; }; + services.frigate = { + enable = true; + acmeCertName = "kilonull.com"; + }; hardware.audio.enable = true; hardware.bluetooth.enable = true;