From 2415b34dc30fb99c308f77f67b47cbab5d496ae7 Mon Sep 17 00:00:00 2001 From: Jake Hillion Date: Sat, 9 Nov 2024 22:26:10 +0000 Subject: [PATCH] frigate: initial setup --- hosts/phoenix.st.ts.hillion.co.uk/default.nix | 7 ++ modules/ids.nix | 2 + modules/impermanence.nix | 21 ++-- modules/locations.nix | 1 + modules/services/authoritative_dns.nix | 3 +- modules/services/default.nix | 1 + modules/services/frigate.nix | 106 ++++++++++++++++++ secrets/frigate/secrets.env.age | 31 +++++ secrets/secrets.nix | 3 + 9 files changed, 165 insertions(+), 10 deletions(-) create mode 100644 modules/services/frigate.nix create mode 100644 secrets/frigate/secrets.env.age diff --git a/hosts/phoenix.st.ts.hillion.co.uk/default.nix b/hosts/phoenix.st.ts.hillion.co.uk/default.nix index 1316f7e..bb4f7ae 100644 --- a/hosts/phoenix.st.ts.hillion.co.uk/default.nix +++ b/hosts/phoenix.st.ts.hillion.co.uk/default.nix @@ -132,6 +132,13 @@ in interfaces.enp5s0.name = "eth1"; interfaces.enp6s0.name = "eth2"; interfaces.enp8s0.name = "eth3"; + + vlans = { + cameras = { + id = 3; + interface = "eth0"; + }; + }; }; networking.nameservers = lib.mkForce [ ]; # Trust the DHCP nameservers diff --git a/modules/ids.nix b/modules/ids.nix index de1984b..9f3304a 100644 --- a/modules/ids.nix +++ b/modules/ids.nix @@ -10,6 +10,7 @@ node-exporter = 188; step-ca = 198; isponsorblocktv = 199; + frigate = 200; ## Consistent People jake = 1000; @@ -23,6 +24,7 @@ node-exporter = 188; step-ca = 198; isponsorblocktv = 199; + frigate = 200; ## Consistent Groups mediaaccess = 1200; diff --git a/modules/impermanence.nix b/modules/impermanence.nix index f5ce19b..19afa46 100644 --- a/modules/impermanence.nix +++ b/modules/impermanence.nix @@ -39,15 +39,18 @@ in services = { openssh.hostKeys = [ - { path = "/data/system/etc/ssh/ssh_host_ed25519_key"; type = "ed25519"; } - { path = "/data/system/etc/ssh/ssh_host_rsa_key"; type = "rsa"; bits = 4096; } + { path = "${cfg.base}/system/etc/ssh/ssh_host_ed25519_key"; type = "ed25519"; } + { path = "${cfg.base}/system/etc/ssh/ssh_host_rsa_key"; type = "rsa"; bits = 4096; } ]; matrix-synapse.dataDir = "${cfg.base}/system/var/lib/matrix-synapse"; gitea.stateDir = "${cfg.base}/system/var/lib/gitea"; }; custom.chia = lib.mkIf config.custom.chia.enable { - path = lib.mkOverride 999 "/data/chia"; + path = lib.mkOverride 999 "${cfg.base}/chia"; + }; + custom.services.frigate = lib.mkIf config.custom.services.frigate.enable { + dataPath = lib.mkOverride 999 "${cfg.base}/frigate"; }; services.resilio = lib.mkIf config.services.resilio.enable { @@ -55,7 +58,7 @@ in }; services.plex = lib.mkIf config.services.plex.enable { - dataDir = lib.mkOverride 999 "/data/plex"; + dataDir = lib.mkOverride 999 "${cfg.base}/plex"; }; services.home-assistant = lib.mkIf config.services.home-assistant.enable { @@ -101,18 +104,18 @@ in name = x; value = { home = { - persistence."/data/users/${x}" = { + persistence."${cfg.base}/users/${x}" = { allowOther = false; files = cfg.userExtraFiles.${x} or [ ]; directories = cfg.userExtraDirs.${x} or [ ]; }; - sessionVariables = lib.attrsets.optionalAttrs homeCfg.programs.zoxide.enable { _ZO_DATA_DIR = "/data/users/${x}/.local/share/zoxide"; }; + sessionVariables = lib.attrsets.optionalAttrs homeCfg.programs.zoxide.enable { _ZO_DATA_DIR = "${cfg.base}/users/${x}/.local/share/zoxide"; }; }; programs = { - zsh.history.path = lib.mkOverride 999 "/data/users/${x}/.zsh_history"; + zsh.history.path = lib.mkOverride 999 "${cfg.base}/users/${x}/.zsh_history"; }; }; }); @@ -122,8 +125,8 @@ in systemd.tmpfiles.rules = lib.lists.flatten (builtins.map (user: let details = config.users.users.${user}; in [ - "d /data/users/${user} 0700 ${user} ${details.group} - -" - "L ${details.home}/local - ${user} ${details.group} - /data/users/${user}" + "d ${cfg.base}/users/${user} 0700 ${user} ${details.group} - -" + "L ${details.home}/local - ${user} ${details.group} - ${cfg.base}/users/${user}" ]) cfg.users); }; diff --git a/modules/locations.nix b/modules/locations.nix index 875c5db..9ae8fa2 100644 --- a/modules/locations.nix +++ b/modules/locations.nix @@ -21,6 +21,7 @@ in services = { authoritative_dns = [ "boron.cx.ts.hillion.co.uk" ]; downloads = "phoenix.st.ts.hillion.co.uk"; + frigate = "phoenix.st.ts.hillion.co.uk"; gitea = "boron.cx.ts.hillion.co.uk"; homeassistant = "stinger.pop.ts.hillion.co.uk"; mastodon = ""; diff --git a/modules/services/authoritative_dns.nix b/modules/services/authoritative_dns.nix index 6d66b73..c85e6f9 100644 --- a/modules/services/authoritative_dns.nix +++ b/modules/services/authoritative_dns.nix @@ -33,8 +33,9 @@ in 86400 NS ns1.hillion.co.uk. ca 21600 CNAME sodium.pop.ts.hillion.co.uk. - restic 21600 CNAME ${config.custom.locations.locations.services.restic}. + frigate 21600 CNAME ${config.custom.locations.locations.services.frigate}. prometheus 21600 CNAME ${config.custom.locations.locations.services.prometheus}. + restic 21600 CNAME ${config.custom.locations.locations.services.restic}. deluge.downloads 21600 CNAME ${config.custom.locations.locations.services.downloads}. prowlarr.downloads 21600 CNAME ${config.custom.locations.locations.services.downloads}. diff --git a/modules/services/default.nix b/modules/services/default.nix index dd0370b..ae455e2 100644 --- a/modules/services/default.nix +++ b/modules/services/default.nix @@ -4,6 +4,7 @@ imports = [ ./authoritative_dns.nix ./downloads.nix + ./frigate.nix ./gitea/default.nix ./homeassistant.nix ./isponsorblocktv.nix diff --git a/modules/services/frigate.nix b/modules/services/frigate.nix new file mode 100644 index 0000000..3296182 --- /dev/null +++ b/modules/services/frigate.nix @@ -0,0 +1,106 @@ +{ config, pkgs, lib, ... }: + +let + cfg = config.custom.services.frigate; +in +{ + options.custom.services.frigate = { + enable = lib.mkEnableOption "frigate"; + + dataPath = lib.mkOption { + type = lib.types.str; + default = "/var/lib/frigate"; + }; + recordingsPath = lib.mkOption { + type = lib.types.str; + default = "/practical-defiant-coffee/cctv"; + }; + }; + + config = lib.mkIf cfg.enable { + age.secrets."frigate/secrets.env".file = ../../secrets/frigate/secrets.env.age; + + services.caddy = { + enable = true; + + virtualHosts."frigate.ts.hillion.co.uk" = { + listenAddresses = [ config.custom.dns.tailscale.ipv4 config.custom.dns.tailscale.ipv6 ]; + extraConfig = '' + reverse_proxy unix//${cfg.dataPath}/nginx.sock + + tls { + ca https://ca.ts.hillion.co.uk:8443/acme/acme/directory + } + ''; + }; + }; + + users.users.frigate = { + group = "frigate"; + home = cfg.dataPath; + createHome = true; + homeMode = "0770"; + uid = config.ids.uids.frigate; + }; + users.groups.frigate.gid = config.ids.gids.frigate; + + containers."frigate" = { + autoStart = true; + ephemeral = true; + + macvlans = [ "cameras" ]; + bindMounts = { + "/run/agenix/frigate/secrets.env".hostPath = config.age.secrets."frigate/secrets.env".path; + + "/var/lib/frigate" = { hostPath = cfg.dataPath; isReadOnly = false; }; + "/media/frigate/recordings" = { hostPath = cfg.recordingsPath; isReadOnly = false; }; + }; + + config = (hostConfig: { config, pkgs, ... }: { + config = { + system.stateVersion = "24.05"; + + networking.interfaces.mv-cameras.useDHCP = true; + + users.users.frigate.uid = hostConfig.ids.uids.frigate; + users.groups.frigate.gid = hostConfig.ids.gids.frigate; + + users.users.nginx.extraGroups = [ "frigate" ]; + services.nginx.virtualHosts."frigate.ts.hillion.co.uk".listen = lib.mkForce [ + { addr = "unix:/media/frigate_data/nginx.sock"; } + ]; + + services.frigate = { + enable = true; + hostname = "frigate.ts.hillion.co.uk"; + + settings = { + record = { + enabled = true; + retain.mode = "motion"; + }; + + cameras = { + living_room = { + enabled = true; + ffmpeg.inputs = [ + { + path = "rtsp://admin:{FRIGATE_RTSP_PASSWORD}@10.133.145.2:554/h264Preview_01_sub"; + roles = [ "detect" ]; + } + { + path = "rtsp://admin:{FRIGATE_RTSP_PASSWORD}@10.133.145.2:554/"; + roles = [ "record" ]; + } + ]; + }; + }; + }; + }; + systemd.services.frigate.unitConfig.EnvironmentFile = "/run/agenix/frigate/secrets.env"; + }; + }) config; + }; + + }; +} diff --git a/secrets/frigate/secrets.env.age b/secrets/frigate/secrets.env.age new file mode 100644 index 0000000..5bce9c3 --- /dev/null +++ b/secrets/frigate/secrets.env.age @@ -0,0 +1,31 @@ +age-encryption.org/v1 +-> ssh-rsa JSzstA +UxtA9OeecK4nVLsDq1BVy1NnWzf4ITfGqQdd31u1iTDhKhPmg8bvu4TuiVn+hD7/ +B2Ar0GOHXH/JB882Q8o2D2DlkVYfwkGmtSxnw/p/um05+l59JGi6zAkw3uSAGrMF +rdte3EdlRrxCImxJVp6AvXEH3kXjT1BtDVBwARpLBGAONc++rwDIFeP56ras4hIa +H2JReFBethNMMZCOa0jH1nUDoRVohdt2wD2KO4LuOxTK0qkRxky4Pwt/+MP26X4j +Uo2FRLrgBb4DlqeNz9EQEnJeRS1Pz6GbzfqZi7f1LUoa5ifKuBobPe2sDBDvE0RR +jFAHZp1Nir/FXEkfjPw2uOfdCUZRLQ2OQ5JLlb0BKo5hV202eGCTY3Fhf34JYkE2 +n++1I5oX2dX1qY9KDpj+LMASKWHtC7ayei9Mcr4Ee7m/dGq9y7Ipjw5aliFJd74n +23idt0MgZbM6GPcqig/Mbz1EQTGwu99HN5wAp8jxusjAkMfmmqosLtkUii4hvKCa +7YnbOJT/6AofZucuylfrJpD3uzkEyaKVlNeZUU82ROSKZK6VdILLB8WfWAMPAsH9 +bLXHtcUo3nF/eQ4P8DZhJM/8tUdg0at4LW4Rb/wQX72xMB2l0F6sqS741f5jjqN3 +gL0tSpYQXtB3ni1mBbj2jKq8+UUP6NpDwOU5p5pfK+I +-> ssh-rsa GxPFJQ +cNBRc51b5Pw2KQq+EHQ4tCGSQQu+JMZHpJjoSAPx5sLd1DgGhE1x1F9h9CuSRFZh +J6fh5xtr9l0rzae/IgSQgfaaq4KVgIC/TIiyLX1VN1MSgbrisMAFA1fu0N/mTJGJ +XEiZI3RebiBxnfS3yJpBAdsFvZDw6o0xD2d1rSzN2dKFKNr9XGPNX1wUqERnWVQF +B5fRpNiWygGPdBaXYDc5OC49vlCAkldaU2EvA1wEuesdTDDn9nisqAlgBBYXEDWq +EBGgiITNyz+wI7ncSVW6JWr5TFfDNEtqGo1JS8nYnpVNHTgU4PbTpqq5fvlAy+hI +gyIR51YZaJZNQhrQ/N4KYw +-> ssh-rsa K9mW1w +c9vvvWH+MrbfNifQYOsfhiw1Ie6npjBVCMrx8YZJwtVmRy3RYjXYn6zcFH+xzSGr +tC0WPwyQ1dqgUNTUdvxaGrSayo5WF2CNosjc66eMrqyG72pcpJwAqlNbWbDNHbm9 +nE3c6XBv0WnEq7G+nkRx0luD96twkor4LVzDa37MUtljNqJo1Puv2AcEylEqXCUX +bKN78TlUOhCpec93ZIxQoE71+26qqpGNnwyTQkHII/RzMKZGQjtmdRtQiUPzVmxT +/3WjnQm4vbeKjOeBjjIdV1Wc7dykBRE7rq/Oe8AGl/7FAnbe6c2Bav50OOL5/Tbo +Fe5TZbOwFDc1ob3IezRI5Q +-> ssh-ed25519 RR/L5A Mvv5Y3bd2IqR1cffLQbJ3WuJCoGMpJaqf/TvV0kcYQs +jRBAHCUuW6hBsuv0VjR+uSKmmqK5rsU4vUIuNHQyAiE +--- /Xx07JneqPgZUC0LrtSMMHAt9eSoB0KUHxQ+j8mkr6c +).*?$Me1"v84 <ގJ+ۃQ"ӵz"ǠB,^kI,B \ No newline at end of file diff --git a/secrets/secrets.nix b/secrets/secrets.nix index ca703a0..3930f8c 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -143,4 +143,7 @@ in "certs/gitea.hillion.co.uk.pem.age".publicKeys = jake_users ++ [ ts.cx.boron ]; "certs/homeassistant.hillion.co.uk.pem.age".publicKeys = jake_users ++ [ ts.cx.boron ]; "certs/links.hillion.co.uk.pem.age".publicKeys = jake_users ++ [ ts.cx.boron ]; + + # Frigate secrets + "frigate/secrets.env.age".publicKeys = jake_users ++ [ ts.st.phoenix ]; }