2025-01-15 14:46:51 +01:00
{
config ,
lib ,
pkgs ,
utils ,
. . .
} :
let
cfg = config . services . recyclarr ;
format = pkgs . formats . yaml { } ;
stateDir = " / v a r / l i b / r e c y c l a r r " ;
configPath = " ${ stateDir } / c o n f i g . j s o n " ;
in
{
options . services . recyclarr = {
enable = lib . mkEnableOption " r e c y c l a r r s e r v i c e " ;
package = lib . mkPackageOption pkgs " r e c y c l a r r " { } ;
configuration = lib . mkOption {
type = format . type ;
default = { } ;
example = {
sonarr = [
{
instance_name = " m a i n " ;
base_url = " h t t p : / / l o c a l h o s t : 8 9 8 9 " ;
api_key = {
_secret = " / r u n / c r e d e n t i a l s / r e c y c l a r r . s e r v i c e / s o n a r r - a p i _ k e y " ;
} ;
}
] ;
radarr = [
{
instance_name = " m a i n " ;
base_url = " h t t p : / / l o c a l h o s t : 7 8 7 8 " ;
api_key = {
_secret = " / r u n / c r e d e n t i a l s / r e c y c l a r r . s e r v i c e / r a d a r r - a p i _ k e y " ;
} ;
}
] ;
} ;
2025-02-07 14:13:38 +01:00
description = ''
2025-01-15 14:46:51 +01:00
Recyclarr YAML configuration as a Nix attribute set .
For detailed configuration options and examples , see the
[ official configuration reference ] ( https://recyclarr.dev/wiki/yaml/config-reference/ ) .
The configuration is processed using [ utils . genJqSecretsReplacementSnippet ] ( https://github.com/NixOS/nixpkgs/blob/master/nixos/lib/utils.nix #L232-L331) to handle secret substitution.
To avoid permission issues , secrets should be provided via systemd's credential mechanism :
` ` ` nix
systemd . services . recyclarr . serviceConfig . LoadCredential = [
" r a d a r r - a p i _ k e y : ' ' ${ config . sops . secrets . radarr-api_key . path } "
] ;
2025-02-07 14:13:38 +01:00
` ` `
2025-01-15 14:46:51 +01:00
'' ;
} ;
schedule = lib . mkOption {
type = lib . types . str ;
default = " d a i l y " ;
description = " W h e n t o r u n r e c y c l a r r i n s y s t e m d c a l e n d a r f o r m a t . " ;
} ;
command = lib . mkOption {
type = lib . types . str ;
default = " s y n c " ;
description = " T h e r e c y c l a r r c o m m a n d t o r u n ( e . g . , s y n c ) . " ;
} ;
user = lib . mkOption {
type = lib . types . str ;
default = " r e c y c l a r r " ;
description = " U s e r a c c o u n t u n d e r w h i c h r e c y c l a r r r u n s . " ;
} ;
group = lib . mkOption {
type = lib . types . str ;
default = " r e c y c l a r r " ;
description = " G r o u p u n d e r w h i c h r e c y c l a r r r u n s . " ;
} ;
} ;
config = lib . mkIf cfg . enable {
users . users = lib . mkIf ( cfg . user = = " r e c y c l a r r " ) {
recyclarr = {
isSystemUser = true ;
description = " r e c y c l a r r u s e r " ;
home = stateDir ;
group = cfg . group ;
} ;
} ;
users . groups = lib . mkIf ( cfg . group = = " r e c y c l a r r " ) {
$ { cfg . group } = { } ;
} ;
systemd . services . recyclarr = {
description = " R e c y c l a r r S e r v i c e " ;
# YAML is a JSON super-set
preStart = utils . genJqSecretsReplacementSnippet cfg . configuration configPath ;
serviceConfig = {
Type = " o n e s h o t " ;
User = cfg . user ;
Group = cfg . group ;
StateDirectory = " r e c y c l a r r " ;
ExecStart = " ${ lib . getExe cfg . package } ${ cfg . command } - - a p p - d a t a ${ stateDir } - - c o n f i g ${ configPath } " ;
ProtectSystem = " s t r i c t " ;
ProtectHome = true ;
PrivateTmp = true ;
PrivateDevices = true ;
ProtectHostname = true ;
ProtectClock = true ;
ProtectKernelTunables = true ;
ProtectKernelModules = true ;
ProtectKernelLogs = true ;
ProtectControlGroups = true ;
PrivateNetwork = false ;
RestrictAddressFamilies = [
" A F _ I N E T "
" A F _ I N E T 6 "
] ;
NoNewPrivileges = true ;
RestrictSUIDSGID = true ;
RemoveIPC = true ;
ReadWritePaths = [ stateDir ] ;
CapabilityBoundingSet = " " ;
LockPersonality = true ;
RestrictRealtime = true ;
} ;
} ;
systemd . timers . recyclarr = {
description = " R e c y c l a r r T i m e r " ;
wantedBy = [ " t i m e r s . t a r g e t " ] ;
partOf = [ " r e c y c l a r r . s e r v i c e " ] ;
timerConfig = {
OnCalendar = cfg . schedule ;
Persistent = true ;
RandomizedDelaySec = " 5 m " ;
} ;
} ;
} ;
}