From 71fa4f64ac738a81d62e565f95921871e4de88b5 Mon Sep 17 00:00:00 2001 From: Henrik Jess Nielsen Date: Mon, 11 May 2026 21:37:15 +0200 Subject: [PATCH] Initial Frigate NVR deployment - Dockerfile: wrapper FROM ghcr.io/blakeblackshear/frigate:stable - frigate.nomad: Nomad job, constrained to int node, dynamic port->5000, host volumes - config/config.yml: cam_167 + cam_168 RTSP, motion detection, 7-day recording - .gitea/workflows/deploy.yml: build -> push registry.i80.dk -> nomad deploy --- .gitea/workflows/deploy.yml | 34 +++++++++++++++ .gitignore | 2 + Dockerfile | 1 + config/config.yml | 45 ++++++++++++++++++++ frigate.nomad | 85 +++++++++++++++++++++++++++++++++++++ 5 files changed, 167 insertions(+) create mode 100644 .gitea/workflows/deploy.yml create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 config/config.yml create mode 100644 frigate.nomad diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..cd7625e --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,34 @@ +name: Build and Deploy Frigate + +on: + push: + branches: + - main + +jobs: + build-push-deploy: + runs-on: debian-host + steps: + - uses: actions/checkout@v4 + + - name: Login to Harbor + run: echo "${{ secrets.HARBOR_ROBOT_TOKEN }}" | docker login registry.i80.dk -u 'robot$gitserver' --password-stdin + + - name: Build and push image + run: | + docker build \ + -t registry.i80.dk/gitea/frigate:latest \ + -t registry.i80.dk/gitea/frigate:${{ github.sha }} \ + . + docker push registry.i80.dk/gitea/frigate:latest + docker push registry.i80.dk/gitea/frigate:${{ github.sha }} + + - name: Validate Nomad job + run: nomad job validate frigate.nomad + env: + NOMAD_ADDR: https://nomad.i80.dk:4646 + + - name: Deploy to Nomad + run: nomad job run frigate.nomad + env: + NOMAD_ADDR: https://nomad.i80.dk:4646 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2334d82 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.env +*.log diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0318858 --- /dev/null +++ b/Dockerfile @@ -0,0 +1 @@ +FROM ghcr.io/blakeblackshear/frigate:stable diff --git a/config/config.yml b/config/config.yml new file mode 100644 index 0000000..2e0e749 --- /dev/null +++ b/config/config.yml @@ -0,0 +1,45 @@ +mqtt: + enabled: false + +cameras: + cam_167: + ffmpeg: + inputs: + - path: rtsp://192.168.15.167:554/s0 + roles: + - detect + - record + motion: + threshold: 41 + contour_area: 30 + improve_contrast: true + cam_168: + ffmpeg: + inputs: + - path: rtsp://192.168.15.168:554/s0 + roles: + - detect + - record + +record: + enabled: true + continuous: + days: 7 + motion: + days: 7 + +detect: + enabled: true + width: 1280 + height: 720 + fps: 5 + +objects: + track: + - person + - car + +ui: + timezone: Europe/Copenhagen + +version: 0.17-0 diff --git a/frigate.nomad b/frigate.nomad new file mode 100644 index 0000000..e6cfc2c --- /dev/null +++ b/frigate.nomad @@ -0,0 +1,85 @@ +job "frigate" { + datacenters = ["dc1"] + type = "service" + + constraint { + attribute = "${attr.unique.hostname}" + value = "int" + } + + group "frigate" { + count = 1 + + update { + canary = 1 + auto_promote = true + auto_revert = true + } + + network { + port "http" { to = 5000 } + } + + volume "frigate-config" { + type = "host" + source = "frigate-config" + read_only = false + } + + volume "frigate-media" { + type = "host" + source = "frigate-media" + read_only = false + } + + task "frigate" { + driver = "docker" + + config { + image = "registry.i80.dk/gitea/frigate:latest" + force_pull = true + privileged = true + shm_size = 268435456 + volumes = ["/etc/localtime:/etc/localtime:ro"] + ports = ["http"] + } + + volume_mount { + volume = "frigate-config" + destination = "/config" + read_only = false + } + + volume_mount { + volume = "frigate-media" + destination = "/media/frigate" + read_only = false + } + + env { + FRIGATE_RTSP_PASSWORD = "" + } + + service { + name = "frigate" + port = "http" + tags = [ + "traefik.enable=true", + "traefik.http.routers.frigate.rule=Host(`cams.i80.dk`)", + "traefik.http.routers.frigate.tls=true", + ] + check { + type = "http" + path = "/api/version" + interval = "10s" + timeout = "5s" + } + } + + resources { + cpu = 2000 + memory = 4096 + } + } + } +}