mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-11-09 16:18:34 +01:00
756 lines
23 KiB
Nix
756 lines
23 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
...
|
|
}:
|
|
|
|
let
|
|
inherit (lib)
|
|
any
|
|
attrValues
|
|
converge
|
|
elem
|
|
filterAttrsRecursive
|
|
hasPrefix
|
|
literalExpression
|
|
makeLibraryPath
|
|
mkDefault
|
|
mkEnableOption
|
|
mkPackageOption
|
|
mkIf
|
|
mkOption
|
|
optionalAttrs
|
|
optionals
|
|
types
|
|
;
|
|
|
|
cfg = config.services.frigate;
|
|
|
|
format = pkgs.formats.yaml { };
|
|
|
|
filteredConfig = converge (filterAttrsRecursive (_: v: !elem v [ null ])) cfg.settings;
|
|
|
|
configFileUnchecked = format.generate "frigate.yaml" filteredConfig;
|
|
configFileChecked =
|
|
pkgs.runCommand "frigate-config"
|
|
{
|
|
preferLocalBuilds = true;
|
|
}
|
|
''
|
|
function error() {
|
|
cat << 'HEREDOC'
|
|
|
|
Note that not all configurations can be reliably checked in the
|
|
build sandbox.
|
|
|
|
This check can be disabled using `services.frigate.checkConfig`.
|
|
HEREDOC
|
|
|
|
exit 1
|
|
}
|
|
|
|
cp ${configFileUnchecked} $out
|
|
export CONFIG_FILE=$out
|
|
export PYTHONPATH=${cfg.package.pythonPath}
|
|
${cfg.package.python.interpreter} -m frigate --validate-config || error
|
|
'';
|
|
configFile = if cfg.checkConfig then configFileChecked else configFileUnchecked;
|
|
|
|
cameraFormat =
|
|
with types;
|
|
submodule {
|
|
freeformType = format.type;
|
|
options = {
|
|
ffmpeg = {
|
|
inputs = mkOption {
|
|
description = ''
|
|
List of inputs for this camera.
|
|
'';
|
|
type = listOf (submodule {
|
|
freeformType = format.type;
|
|
options = {
|
|
path = mkOption {
|
|
type = str;
|
|
example = "rtsp://192.0.2.1:554/rtsp";
|
|
description = ''
|
|
Stream URL
|
|
'';
|
|
};
|
|
roles = mkOption {
|
|
type = listOf (enum [
|
|
"audio"
|
|
"detect"
|
|
"record"
|
|
]);
|
|
example = [
|
|
"detect"
|
|
"record"
|
|
];
|
|
description = ''
|
|
List of roles for this stream
|
|
'';
|
|
};
|
|
};
|
|
});
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
# auth_request.conf
|
|
nginxAuthRequest = ''
|
|
# Send a subrequest to verify if the user is authenticated and has permission to access the resource.
|
|
auth_request /auth;
|
|
|
|
# Save the upstream metadata response headers from the auth request to variables
|
|
auth_request_set $user $upstream_http_remote_user;
|
|
auth_request_set $role $upstream_http_remote_role;
|
|
auth_request_set $groups $upstream_http_remote_groups;
|
|
auth_request_set $name $upstream_http_remote_name;
|
|
auth_request_set $email $upstream_http_remote_email;
|
|
|
|
# Inject the metadata response headers from the variables into the request made to the backend.
|
|
proxy_set_header Remote-User $user;
|
|
proxy_set_header Remote-Role $role;
|
|
proxy_set_header Remote-Groups $groups;
|
|
proxy_set_header Remote-Email $email;
|
|
proxy_set_header Remote-Name $name;
|
|
|
|
# Refresh the cookie as needed
|
|
auth_request_set $auth_cookie $upstream_http_set_cookie;
|
|
add_header Set-Cookie $auth_cookie;
|
|
|
|
# Pass the location header back up if it exists
|
|
auth_request_set $redirection_url $upstream_http_location;
|
|
add_header Location $redirection_url;
|
|
'';
|
|
|
|
nginxProxySettings = ''
|
|
# Basic Proxy Configuration
|
|
client_body_buffer_size 128k;
|
|
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; ## Timeout if the real server is dead.
|
|
proxy_redirect http:// $scheme://;
|
|
proxy_cache_bypass $cookie_session;
|
|
proxy_no_cache $cookie_session;
|
|
proxy_buffers 64 256k;
|
|
|
|
# Advanced Proxy Configuration
|
|
send_timeout 5m;
|
|
proxy_read_timeout 360;
|
|
proxy_send_timeout 360;
|
|
proxy_connect_timeout 360;
|
|
'';
|
|
|
|
# Discover configured detectors for acceleration support
|
|
detectors = attrValues cfg.settings.detectors or { };
|
|
withCoralUSB = any (d: d.type == "edgetpu" && hasPrefix "usb" d.device or "") detectors;
|
|
withCoralPCI = any (d: d.type == "edgetpu" && hasPrefix "pci" d.device or "") detectors;
|
|
withCoral = withCoralPCI || withCoralUSB;
|
|
in
|
|
|
|
{
|
|
meta.buildDocsInSandbox = false;
|
|
|
|
options.services.frigate = with types; {
|
|
enable = mkEnableOption "Frigate NVR";
|
|
|
|
package = mkPackageOption pkgs "frigate" { };
|
|
|
|
hostname = mkOption {
|
|
type = str;
|
|
example = "frigate.exampe.com";
|
|
description = ''
|
|
Hostname of the nginx vhost to configure.
|
|
|
|
Only nginx is supported by upstream for direct reverse proxying.
|
|
'';
|
|
};
|
|
|
|
vaapiDriver = mkOption {
|
|
type = nullOr (enum [
|
|
"i965"
|
|
"iHD"
|
|
"nouveau"
|
|
"vdpau"
|
|
"nvidia"
|
|
"radeonsi"
|
|
]);
|
|
default = null;
|
|
example = "radeonsi";
|
|
description = ''
|
|
Force usage of a particular VA-API driver for video acceleration. Use together with `settings.ffmpeg.hwaccel_args`.
|
|
|
|
Setting this *is not required* for VA-API to work, but it can help steer VA-API towards the correct card if you have multiple.
|
|
|
|
:::{.note}
|
|
For VA-API to work you must enable {option}`hardware.graphics.enable` (sufficient for AMDGPU) and pass for example
|
|
`pkgs.intel-media-driver` (required for Intel 5th Gen. and newer) into {option}`hardware.graphics.extraPackages`.
|
|
:::
|
|
|
|
See also:
|
|
|
|
- <https://docs.frigate.video/configuration/hardware_acceleration>
|
|
- <https://docs.frigate.video/configuration/ffmpeg_presets#hwaccel-presets>
|
|
'';
|
|
};
|
|
|
|
checkConfig = mkOption {
|
|
type = bool;
|
|
default =
|
|
pkgs.stdenv.buildPlatform.canExecute pkgs.stdenv.hostPlatform
|
|
&& (!pkgs.stdenv.hostPlatform.isAarch64);
|
|
defaultText = literalExpression ''
|
|
pkgs.stdenv.buildPlatform.canExecute pkgs.stdenv.hostPlatform && !(pkgs.stdenv.hostPlaform.isAarch64)
|
|
'';
|
|
description = ''
|
|
Whether to check the configuration at build time.
|
|
'';
|
|
};
|
|
|
|
settings = mkOption {
|
|
type = submodule {
|
|
freeformType = format.type;
|
|
options = {
|
|
cameras = mkOption {
|
|
type = attrsOf cameraFormat;
|
|
description = ''
|
|
Attribute set of cameras configurations.
|
|
|
|
<https://docs.frigate.video/configuration/cameras>
|
|
'';
|
|
};
|
|
|
|
database = {
|
|
path = mkOption {
|
|
type = path;
|
|
default = "/var/lib/frigate/frigate.db";
|
|
description = ''
|
|
Path to the SQLite database used
|
|
'';
|
|
};
|
|
};
|
|
|
|
ffmpeg = {
|
|
path = mkOption {
|
|
type = coercedTo package toString str;
|
|
default = pkgs.ffmpeg-headless;
|
|
example = literalExpression "pkgs.ffmpeg-full";
|
|
description = ''
|
|
Package providing the ffmpeg and ffprobe executables below the bin/ directory.
|
|
'';
|
|
};
|
|
};
|
|
|
|
mqtt = {
|
|
enabled = mkEnableOption "MQTT support";
|
|
|
|
host = mkOption {
|
|
type = nullOr str;
|
|
default = null;
|
|
example = "mqtt.example.com";
|
|
description = ''
|
|
MQTT server hostname
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
};
|
|
default = { };
|
|
description = ''
|
|
Frigate configuration as a nix attribute set.
|
|
|
|
See the project documentation for how to configure frigate.
|
|
- [Creating a config file](https://docs.frigate.video/guides/getting_started)
|
|
- [Configuration reference](https://docs.frigate.video/configuration/index)
|
|
'';
|
|
};
|
|
};
|
|
|
|
config = mkIf cfg.enable {
|
|
services.nginx = {
|
|
enable = true;
|
|
additionalModules = with pkgs.nginxModules; [
|
|
develkit
|
|
rtmp
|
|
secure-token
|
|
set-misc
|
|
vod
|
|
];
|
|
recommendedGzipSettings = mkDefault true;
|
|
mapHashBucketSize = mkDefault 128;
|
|
upstreams = {
|
|
frigate-api.servers = {
|
|
"127.0.0.1:5001" = { };
|
|
};
|
|
frigate-mqtt-ws.servers = {
|
|
"127.0.0.1:5002" = { };
|
|
};
|
|
frigate-jsmpeg.servers = {
|
|
"127.0.0.1:8082" = { };
|
|
};
|
|
frigate-go2rtc.servers = {
|
|
"127.0.0.1:1984" = { };
|
|
};
|
|
};
|
|
proxyCachePath."frigate" = {
|
|
enable = true;
|
|
keysZoneSize = "10m";
|
|
keysZoneName = "frigate_api_cache";
|
|
maxSize = "10m";
|
|
inactive = "1m";
|
|
levels = "1:2";
|
|
};
|
|
# Based on https://github.com/blakeblackshear/frigate/blob/v0.13.1/docker/main/rootfs/usr/local/nginx/conf/nginx.conf
|
|
virtualHosts."${cfg.hostname}" = {
|
|
locations = {
|
|
# auth_location.conf
|
|
"/auth" = {
|
|
proxyPass = "http://frigate-api/auth";
|
|
recommendedProxySettings = true;
|
|
extraConfig = ''
|
|
internal;
|
|
|
|
# Strip all request headers
|
|
proxy_pass_request_headers off;
|
|
|
|
# Pass info about the request
|
|
proxy_set_header X-Original-Method $request_method;
|
|
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
|
|
proxy_set_header X-Server-Port $server_port;
|
|
proxy_set_header Content-Length "";
|
|
|
|
# Pass along auth related info
|
|
proxy_set_header Authorization $http_authorization;
|
|
proxy_set_header Cookie $http_cookie;
|
|
proxy_set_header X-CSRF-TOKEN "1";
|
|
|
|
# Header used to validate reverse proxy trust
|
|
proxy_set_header X-Proxy-Secret $http_x_proxy_secret;
|
|
|
|
# Pass headers for common auth proxies
|
|
proxy_set_header Remote-User $http_remote_user;
|
|
proxy_set_header Remote-Groups $http_remote_groups;
|
|
proxy_set_header Remote-Email $http_remote_email;
|
|
proxy_set_header Remote-Name $http_remote_name;
|
|
proxy_set_header X-Forwarded-User $http_x_forwarded_user;
|
|
proxy_set_header X-Forwarded-Groups $http_x_forwarded_groups;
|
|
proxy_set_header X-Forwarded-Email $http_x_forwarded_email;
|
|
proxy_set_header X-Forwarded-Preferred-Username $http_x_forwarded_preferred_username;
|
|
proxy_set_header X-authentik-username $http_x_authentik_username;
|
|
proxy_set_header X-authentik-groups $http_x_authentik_groups;
|
|
proxy_set_header X-authentik-email $http_x_authentik_email;
|
|
proxy_set_header X-authentik-name $http_x_authentik_name;
|
|
proxy_set_header X-authentik-uid $http_x_authentik_uid;
|
|
|
|
${nginxProxySettings}
|
|
'';
|
|
};
|
|
"/vod/" = {
|
|
extraConfig = nginxAuthRequest + ''
|
|
aio threads;
|
|
vod hls;
|
|
|
|
secure_token $args;
|
|
secure_token_types application/vnd.apple.mpegurl;
|
|
|
|
add_header Cache-Control "no-store";
|
|
expires off;
|
|
|
|
keepalive_disable safari;
|
|
|
|
# vod module returns 502 for non-existent media
|
|
# https://github.com/kaltura/nginx-vod-module/issues/468
|
|
error_page 502 =404 /vod-not-found;
|
|
'';
|
|
};
|
|
"/vod-not-found" = {
|
|
return = 404;
|
|
};
|
|
"/stream/" = {
|
|
alias = "/var/cache/frigate/stream/";
|
|
extraConfig = nginxAuthRequest + ''
|
|
add_header Cache-Control "no-store";
|
|
expires off;
|
|
|
|
types {
|
|
application/dash+xml mpd;
|
|
application/vnd.apple.mpegurl m3u8;
|
|
video/mp2t ts;
|
|
image/jpeg jpg;
|
|
}
|
|
'';
|
|
};
|
|
"/clips/" = {
|
|
root = "/var/lib/frigate";
|
|
extraConfig = nginxAuthRequest + ''
|
|
types {
|
|
video/mp4 mp4;
|
|
image/jpeg jpg;
|
|
}
|
|
|
|
expires 7d;
|
|
add_header Cache-Control "public";
|
|
autoindex on;
|
|
'';
|
|
};
|
|
"/cache/" = {
|
|
alias = "/var/cache/frigate/";
|
|
extraConfig = ''
|
|
internal;
|
|
'';
|
|
};
|
|
"/recordings/" = {
|
|
root = "/var/lib/frigate";
|
|
extraConfig = nginxAuthRequest + ''
|
|
types {
|
|
video/mp4 mp4;
|
|
}
|
|
|
|
autoindex on;
|
|
autoindex_format json;
|
|
'';
|
|
};
|
|
"/exports/" = {
|
|
root = "/var/lib/frigate";
|
|
extraConfig = nginxAuthRequest + ''
|
|
types {
|
|
video/mp4 mp4;
|
|
}
|
|
|
|
autoindex on;
|
|
autoindex_format json;
|
|
'';
|
|
};
|
|
"/ws" = {
|
|
proxyPass = "http://frigate-mqtt-ws/";
|
|
recommendedProxySettings = true;
|
|
proxyWebsockets = true;
|
|
extraConfig = nginxAuthRequest + nginxProxySettings;
|
|
};
|
|
"/live/jsmpeg" = {
|
|
proxyPass = "http://frigate-jsmpeg/";
|
|
recommendedProxySettings = true;
|
|
proxyWebsockets = true;
|
|
extraConfig = nginxAuthRequest + nginxProxySettings;
|
|
};
|
|
# frigate lovelace card uses this path
|
|
"/live/mse/api/ws" = {
|
|
proxyPass = "http://frigate-go2rtc/api/ws";
|
|
proxyWebsockets = true;
|
|
recommendedProxySettings = true;
|
|
extraConfig =
|
|
nginxAuthRequest
|
|
+ nginxProxySettings
|
|
+ ''
|
|
limit_except GET {
|
|
deny all;
|
|
}
|
|
'';
|
|
};
|
|
"/live/webrtc/api/ws" = {
|
|
proxyPass = "http://frigate-go2rtc/api/ws";
|
|
proxyWebsockets = true;
|
|
recommendedProxySettings = true;
|
|
extraConfig =
|
|
nginxAuthRequest
|
|
+ nginxProxySettings
|
|
+ ''
|
|
limit_except GET {
|
|
deny all;
|
|
}
|
|
'';
|
|
};
|
|
# pass through go2rtc player
|
|
"/live/webrtc/webrtc.html" = {
|
|
proxyPass = "http://frigate-go2rtc/webrtc.html";
|
|
recommendedProxySettings = true;
|
|
extraConfig =
|
|
nginxAuthRequest
|
|
+ nginxProxySettings
|
|
+ ''
|
|
limit_except GET {
|
|
deny all;
|
|
}
|
|
'';
|
|
};
|
|
# frontend uses this to fetch the version
|
|
"/api/go2rtc/api" = {
|
|
proxyPass = "http://frigate-go2rtc/api";
|
|
recommendedProxySettings = true;
|
|
extraConfig =
|
|
nginxAuthRequest
|
|
+ nginxProxySettings
|
|
+ ''
|
|
limit_except GET {
|
|
deny all;
|
|
}
|
|
'';
|
|
};
|
|
# integrationn uses this to add webrtc candidate
|
|
"/api/go2rtc/webrtc" = {
|
|
proxyPass = "http://frigate-go2rtc/api/webrtc";
|
|
proxyWebsockets = true;
|
|
recommendedProxySettings = true;
|
|
extraConfig =
|
|
nginxAuthRequest
|
|
+ nginxProxySettings
|
|
+ ''
|
|
limit_except GET {
|
|
deny all;
|
|
}
|
|
'';
|
|
};
|
|
"~* /api/.*\\.(jpg|jpeg|png|webp|gif)$" = {
|
|
proxyPass = "http://frigate-api";
|
|
recommendedProxySettings = true;
|
|
extraConfig =
|
|
nginxAuthRequest
|
|
+ nginxProxySettings
|
|
+ ''
|
|
rewrite ^/api/(.*)$ /$1 break;
|
|
'';
|
|
};
|
|
"/api/" = {
|
|
proxyPass = "http://frigate-api/";
|
|
recommendedProxySettings = true;
|
|
extraConfig =
|
|
nginxAuthRequest
|
|
+ nginxProxySettings
|
|
+ ''
|
|
add_header Cache-Control "no-store";
|
|
expires off;
|
|
|
|
proxy_cache frigate_api_cache;
|
|
proxy_cache_lock on;
|
|
proxy_cache_use_stale updating;
|
|
proxy_cache_valid 200 5s;
|
|
proxy_cache_bypass $http_x_cache_bypass;
|
|
proxy_no_cache $should_not_cache;
|
|
add_header X-Cache-Status $upstream_cache_status;
|
|
|
|
location /api/vod/ {
|
|
${nginxAuthRequest}
|
|
proxy_pass http://frigate-api/vod/;
|
|
proxy_cache off;
|
|
add_header Cache-Control "no-store";
|
|
${nginxProxySettings}
|
|
}
|
|
|
|
location /api/login {
|
|
auth_request off;
|
|
rewrite ^/api(/.*)$ $1 break;
|
|
proxy_pass http://frigate-api;
|
|
${nginxProxySettings}
|
|
}
|
|
|
|
location /api/stats {
|
|
${nginxAuthRequest}
|
|
access_log off;
|
|
rewrite ^/api(/.*)$ $1 break;
|
|
add_header Cache-Control "no-store";
|
|
proxy_pass http://frigate-api;
|
|
${nginxProxySettings}
|
|
}
|
|
|
|
location /api/version {
|
|
${nginxAuthRequest}
|
|
access_log off;
|
|
rewrite ^/api(/.*)$ $1 break;
|
|
add_header Cache-Control "no-store";
|
|
proxy_pass http://frigate-api;
|
|
${nginxProxySettings}
|
|
}
|
|
'';
|
|
};
|
|
"/assets/" = {
|
|
root = cfg.package.web;
|
|
extraConfig = ''
|
|
access_log off;
|
|
expires 1y;
|
|
add_header Cache-Control "public";
|
|
'';
|
|
};
|
|
"/locales/" = {
|
|
root = cfg.package.web;
|
|
extraConfig = ''
|
|
access_log off;
|
|
add_header Cache-Control "public";
|
|
'';
|
|
};
|
|
"~ ^/.*-([A-Za-z0-9]+)\\.webmanifest$" = {
|
|
root = cfg.package.web;
|
|
extraConfig = ''
|
|
access_log off;
|
|
expires 1y;
|
|
add_header Cache-Control "public";
|
|
default_type application/json;
|
|
proxy_set_header Accept-Encoding "";
|
|
'';
|
|
};
|
|
"/" = {
|
|
root = cfg.package.web;
|
|
tryFiles = "$uri $uri.html $uri/ /index.html";
|
|
extraConfig = ''
|
|
add_header Cache-Control "no-store";
|
|
expires off;
|
|
'';
|
|
};
|
|
};
|
|
extraConfig = ''
|
|
# Frigate wants to connect on 127.0.0.1:5000 for unauthenticated requests
|
|
# https://github.com/NixOS/nixpkgs/issues/370349
|
|
listen 127.0.0.1:5000;
|
|
|
|
# vod settings
|
|
vod_base_url "";
|
|
vod_segments_base_url "";
|
|
vod_mode mapped;
|
|
vod_max_mapping_response_size 1m;
|
|
vod_upstream_location /api;
|
|
vod_align_segments_to_key_frames on;
|
|
vod_manifest_segment_durations_mode accurate;
|
|
vod_ignore_edit_list on;
|
|
vod_segment_duration 10000;
|
|
vod_hls_mpegts_align_frames off;
|
|
vod_hls_mpegts_interleave_frames on;
|
|
|
|
# file handle caching / aio
|
|
open_file_cache max=1000 inactive=5m;
|
|
open_file_cache_valid 2m;
|
|
open_file_cache_min_uses 1;
|
|
open_file_cache_errors on;
|
|
aio on;
|
|
|
|
# file upload size
|
|
client_max_body_size 20M;
|
|
|
|
# https://github.com/kaltura/nginx-vod-module#vod_open_file_thread_pool
|
|
vod_open_file_thread_pool default;
|
|
|
|
# vod caches
|
|
vod_metadata_cache metadata_cache 512m;
|
|
vod_mapping_cache mapping_cache 5m 10m;
|
|
|
|
# gzip manifest
|
|
gzip_types application/vnd.apple.mpegurl;
|
|
'';
|
|
};
|
|
appendConfig = ''
|
|
# frigate
|
|
rtmp {
|
|
server {
|
|
listen 1935;
|
|
chunk_size 4096;
|
|
allow publish 127.0.0.1;
|
|
deny publish all;
|
|
allow play all;
|
|
application live {
|
|
live on;
|
|
record off;
|
|
meta copy;
|
|
}
|
|
}
|
|
}
|
|
'';
|
|
appendHttpConfig = ''
|
|
# frigate
|
|
map $sent_http_content_type $should_not_cache {
|
|
'application/json' 0;
|
|
default 1;
|
|
}
|
|
'';
|
|
};
|
|
|
|
systemd.services.nginx.serviceConfig.SupplementaryGroups = [
|
|
"frigate"
|
|
];
|
|
|
|
hardware.coral = {
|
|
usb.enable = mkDefault withCoralUSB;
|
|
pcie.enable = mkDefault withCoralPCI;
|
|
};
|
|
|
|
users.users.frigate = {
|
|
isSystemUser = true;
|
|
group = "frigate";
|
|
};
|
|
users.groups.frigate = { };
|
|
|
|
systemd.services.frigate = {
|
|
after = [
|
|
"go2rtc.service"
|
|
"network.target"
|
|
];
|
|
wantedBy = [
|
|
"multi-user.target"
|
|
];
|
|
environment = {
|
|
CONFIG_FILE = "/run/frigate/frigate.yml";
|
|
HOME = "/var/lib/frigate";
|
|
PYTHONPATH = cfg.package.pythonPath;
|
|
}
|
|
// optionalAttrs (cfg.vaapiDriver != null) {
|
|
LIBVA_DRIVER_NAME = cfg.vaapiDriver;
|
|
}
|
|
// optionalAttrs withCoral {
|
|
LD_LIBRARY_PATH = makeLibraryPath (with pkgs; [ libedgetpu ]);
|
|
};
|
|
path =
|
|
with pkgs;
|
|
[
|
|
# unfree:
|
|
# config.boot.kernelPackages.nvidiaPackages.latest.bin
|
|
libva-utils
|
|
procps
|
|
radeontop
|
|
]
|
|
++ optionals (!stdenv.hostPlatform.isAarch64) [
|
|
# not available on aarch64-linux
|
|
intel-gpu-tools
|
|
rocmPackages.rocminfo
|
|
];
|
|
serviceConfig = {
|
|
ExecStartPre = [
|
|
(pkgs.writeShellScript "frigate-clear-cache" ''
|
|
shopt -s extglob
|
|
rm --recursive --force /var/cache/frigate/!(model_cache)
|
|
'')
|
|
(pkgs.writeShellScript "frigate-create-writable-config" ''
|
|
cp --no-preserve=mode ${configFile} /run/frigate/frigate.yml
|
|
'')
|
|
];
|
|
ExecStart = "${cfg.package.python.interpreter} -m frigate";
|
|
Restart = "on-failure";
|
|
SyslogIdentifier = "frigate";
|
|
|
|
User = "frigate";
|
|
Group = "frigate";
|
|
SupplementaryGroups = [ "render" ] ++ optionals withCoral [ "coral" ];
|
|
|
|
AmbientCapabilities = optionals (elem cfg.vaapiDriver [
|
|
"i965"
|
|
"iHD"
|
|
]) [ "CAP_PERFMON" ]; # for intel_gpu_top
|
|
|
|
UMask = "0027";
|
|
|
|
StateDirectory = "frigate";
|
|
StateDirectoryMode = "0750";
|
|
|
|
# Caches
|
|
PrivateTmp = true;
|
|
CacheDirectory = [
|
|
"frigate"
|
|
# https://github.com/blakeblackshear/frigate/discussions/18129
|
|
"frigate/model_cache"
|
|
];
|
|
CacheDirectoryMode = "0750";
|
|
|
|
# Sockets/IPC
|
|
RuntimeDirectory = "frigate";
|
|
};
|
|
};
|
|
};
|
|
}
|