217 lines
5.8 KiB
HCL
217 lines
5.8 KiB
HCL
job "frigate" {
|
|
# Pin to N150 LattePanda nodes - Intel UHD iGPU for OpenVINO-accelerated detection.
|
|
# hardware.graphics (intel-compute-runtime) is deployed to these nodes via configuration.nix.
|
|
constraint {
|
|
attribute = "${node.class}"
|
|
value = "latte-panda-n150"
|
|
}
|
|
|
|
group "frigate" {
|
|
count = 1
|
|
|
|
network {
|
|
port "http" {
|
|
to = 5000
|
|
}
|
|
}
|
|
|
|
# Prestart: restore Frigate's SQLite DB from the Litestream file replica on the CIFS share.
|
|
# Runs to completion before the frigate task starts. Safe on first boot (-if-replica-exists
|
|
# is a no-op when no replica exists yet).
|
|
task "litestream-restore" {
|
|
lifecycle {
|
|
hook = "prestart"
|
|
sidecar = false
|
|
}
|
|
|
|
driver = "docker"
|
|
|
|
config {
|
|
image = "litestream/litestream:0.5.9"
|
|
command = "restore"
|
|
args = ["-if-replica-exists", "-config", "/local/litestream.yml", "/alloc/data/frigate.db"]
|
|
}
|
|
|
|
# Litestream config: replicate to /config/frigate.db.litestream/ on the CIFS share.
|
|
# Litestream writes its own segment format - no SQLite advisory locking involved.
|
|
# Frigate must be configured with database.path: /alloc/data/frigate.db in config.yml.
|
|
template {
|
|
data = <<EOH
|
|
dbs:
|
|
- path: /alloc/data/frigate.db
|
|
replicas:
|
|
- url: file:///config/frigate.db.litestream
|
|
EOH
|
|
destination = "local/litestream.yml"
|
|
}
|
|
|
|
volume_mount {
|
|
volume = "unraid_appdata_frigate"
|
|
destination = "/config"
|
|
read_only = false
|
|
}
|
|
|
|
resources {
|
|
cpu = 100
|
|
memory = 64
|
|
memory_max = 256
|
|
}
|
|
}
|
|
|
|
# Sidecar: continuously stream WAL changes from /alloc/data/frigate.db to the CIFS replica.
|
|
# Runs alongside frigate for the lifetime of the allocation.
|
|
task "litestream-replicate" {
|
|
lifecycle {
|
|
hook = "poststart"
|
|
sidecar = true
|
|
}
|
|
|
|
driver = "docker"
|
|
|
|
config {
|
|
image = "litestream/litestream:0.5"
|
|
command = "replicate"
|
|
args = ["-config", "/local/litestream.yml"]
|
|
}
|
|
|
|
template {
|
|
data = <<EOH
|
|
dbs:
|
|
- path: /alloc/data/frigate.db
|
|
replicas:
|
|
- url: file:///config/frigate.db.litestream
|
|
EOH
|
|
destination = "local/litestream.yml"
|
|
}
|
|
|
|
volume_mount {
|
|
volume = "unraid_appdata_frigate"
|
|
destination = "/config"
|
|
read_only = false
|
|
}
|
|
|
|
resources {
|
|
cpu = 100
|
|
memory = 64
|
|
memory_max = 256
|
|
}
|
|
}
|
|
|
|
task "frigate" {
|
|
driver = "docker"
|
|
|
|
config {
|
|
image = "ghcr.io/blakeblackshear/frigate:0.17.1"
|
|
ports = ["http"]
|
|
privileged = true
|
|
|
|
# Shared memory for inter-process frame buffers (frigate forks detector processes).
|
|
shm_size = 268435456 # 256 MiB
|
|
|
|
# Large tmpfs for decoded frame cache - avoids wearing out any storage.
|
|
mounts = [
|
|
{
|
|
type = "tmpfs"
|
|
target = "/tmp/cache"
|
|
readonly = false
|
|
tmpfs_options = {
|
|
size = 1000000000 # 1 GiB in bytes
|
|
}
|
|
}
|
|
]
|
|
|
|
# Intel iGPU render node - Frigate's bundled OpenVINO runtime auto-detects
|
|
# GPU device and uses it for object detection without any extra env vars.
|
|
# Requires hardware.graphics.enable = true on the NixOS node (N150 nodes).
|
|
devices = [
|
|
{
|
|
host_path = "/dev/dri/renderD128"
|
|
container_path = "/dev/dri/renderD128"
|
|
}
|
|
]
|
|
}
|
|
|
|
# RTSP password injected from Nomad variables (sourced from sops secrets).
|
|
# Reference in config.yml as: {FRIGATE_RTSP_PASSWORD}
|
|
template {
|
|
data = <<EOH
|
|
FRIGATE_RTSP_PASSWORD="{{ with nomadVar "nomad/jobs/frigate" }}{{ .rtsp_password }}{{ end }}"
|
|
EOH
|
|
destination = "secrets/frigate.env"
|
|
env = true
|
|
}
|
|
|
|
service {
|
|
name = "frigate"
|
|
port = "http"
|
|
|
|
tags = [
|
|
"traefik.enable=true",
|
|
"traefik.http.routers.frigate.middlewares=auth@file",
|
|
"traefik.http.routers.frigate-token.rule=Host(`n7gdph5cuh7bd1cakbq8s099rvrv3qhs-frigate.othrayte.one`)",
|
|
]
|
|
|
|
check {
|
|
name = "alive"
|
|
type = "http"
|
|
path = "/api/version"
|
|
port = "http"
|
|
interval = "10s"
|
|
timeout = "5s"
|
|
}
|
|
}
|
|
|
|
env {
|
|
TZ = "Australia/Melbourne"
|
|
}
|
|
|
|
# config.yml lives here (read from CIFS). SQLite DB is at /alloc/data/frigate.db
|
|
# (local NVMe, managed by Litestream). Requires in config.yml:
|
|
# database:
|
|
# path: /alloc/data/frigate.db
|
|
volume_mount {
|
|
volume = "unraid_appdata_frigate"
|
|
destination = "/config"
|
|
read_only = false
|
|
}
|
|
|
|
# Recordings, clips, and exports.
|
|
volume_mount {
|
|
volume = "unraid_media_frigate"
|
|
destination = "/media/frigate"
|
|
read_only = false
|
|
}
|
|
|
|
resources {
|
|
# GPU handles inference; CPU manages stream ingestion, motion detection, and recording.
|
|
cpu = 2000
|
|
memory = 2048
|
|
}
|
|
}
|
|
|
|
volume "unraid_appdata_frigate" {
|
|
type = "csi"
|
|
read_only = false
|
|
source = "unraid_appdata_frigate"
|
|
access_mode = "single-node-writer"
|
|
attachment_mode = "file-system"
|
|
|
|
mount_options {
|
|
mount_flags = ["nobrl", "uid=0", "gid=0"]
|
|
}
|
|
}
|
|
|
|
volume "unraid_media_frigate" {
|
|
type = "csi"
|
|
read_only = false
|
|
source = "unraid_media_frigate"
|
|
access_mode = "single-node-writer"
|
|
attachment_mode = "file-system"
|
|
|
|
mount_options {
|
|
mount_flags = ["nobrl", "uid=0", "gid=0"]
|
|
}
|
|
}
|
|
}
|
|
}
|