feat(media): migrer la bibliothèque partagée vers /srv/media (dataset ZFS dédié)
/home/marc/media posait deux problèmes : /home/marc est 0700 (chaque service
devait recevoir un droit de traversée) et systemd-tmpfiles refuse de créer
quoi que ce soit sous /home/marc (« unsafe path transition », exit 73).
- services/media (nouveau) : dataset nixos/media -> /srv/media, groupe media
(setgid, dossiers 2775/2770), arborescence movies/tvshows/music/books/downloads
- disko.nix : dataset media à côté de marc/nix
- navidrome, jellyfin, kodi : bibliothèque -> /srv/media/{music,movies,tvshows}
- qbittorrent : téléchargements dans le même dataset que la bibliothèque
(permet aux *arr d'importer par lien dur au lieu de copier)
- radarr : dataDir corrigé (pointait sur celui de sonarr par copier-coller),
déplacé hors /home (impossible avec ProtectHome+tmpfiles du module)
- sonarr : dataDir dédié + migration depuis /home/marc/radarr (était figé
depuis le 28/07, port 8006 muet) ; réparé le 27/09/2026
- readarr : bibliothèque -> /srv/media/books
This commit is contained in:
@@ -65,6 +65,13 @@
|
|||||||
options.mountpoint = "/nix";
|
options.mountpoint = "/nix";
|
||||||
mountpoint = "/nix";
|
mountpoint = "/nix";
|
||||||
};
|
};
|
||||||
|
# Média partagé (Jellyfin, Navidrome, Radarr, Sonarr, Nextcloud) :
|
||||||
|
# groupe `media` + dossiers setgid, hors des homes pour que
|
||||||
|
# systemd-tmpfiles puisse y créer les dossiers (voir services/media).
|
||||||
|
"media" = {
|
||||||
|
type = "zfs_fs";
|
||||||
|
options.mountpoint = "/srv/media";
|
||||||
|
};
|
||||||
"marc" = {
|
"marc" = {
|
||||||
type = "zfs_fs";
|
type = "zfs_fs";
|
||||||
options.mountpoint = "none";
|
options.mountpoint = "none";
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ in {
|
|||||||
sources.video = [
|
sources.video = [
|
||||||
{
|
{
|
||||||
name = "movies";
|
name = "movies";
|
||||||
path = "${homeDir}/media/movies/";
|
path = "/srv/media/movies/";
|
||||||
# 'allowsharing = true;' partage upnp
|
# 'allowsharing = true;' partage upnp
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
name = "tvshows";
|
name = "tvshows";
|
||||||
path = "${homeDir}/media/tvshows/";
|
path = "/srv/media/tvshows/";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -38,37 +38,17 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# /home/marc n'est traversable (bit x) que par son groupe propriétaire : sans
|
# Les bibliothèques vivent dans /srv/media (groupe `media`, dossiers setgid,
|
||||||
# `users` en groupe secondaire, l'utilisateur jellyfin ne peut pas atteindre
|
# créés par systemd-tmpfiles : cf. services/media). Ne PAS les mettre sous
|
||||||
# /home/marc/media (le dossier lui-même est en 0755 root:root, donc lisible).
|
# /home/marc : systemd-tmpfiles refuse de créer un dossier là-bas
|
||||||
users.users.jellyfin.extraGroups = [ "users" ];
|
# (« unsafe path transition », exit 73) et tout service devrait recevoir un
|
||||||
|
# droit de traversée sur un home en 0700. Les racines à sélectionner dans
|
||||||
# Bibliothèques : mêmes dossiers que les sources vidéo de Kodi, plus la
|
# l'assistant web sont : /srv/media/movies, /srv/media/tvshows, /srv/media/music.
|
||||||
# musique déjà servie par Navidrome. Jellyfin ne sait pas ajouter de
|
|
||||||
# bibliothèque de façon déclarative, ces dossiers ne sont que les racines à
|
|
||||||
# sélectionner dans l'assistant web (Bibliothèques > Ajouter).
|
|
||||||
#
|
#
|
||||||
# Pourquoi un oneshot et pas systemd.tmpfiles.rules : systemd-tmpfiles refuse
|
# UMask : le module impose 0077. Le média est partagé, donc les fichiers que
|
||||||
# de descendre dans /home/marc (0700, appartient à marc) pour y créer un
|
# Jellyfin écrit dans la bibliothèque (pochettes, NFO s'ils sont activés)
|
||||||
# dossier, et sort en "Detected unsafe path transition /home/marc (owned by
|
# doivent rester lisibles et modifiables par les autres membres du groupe.
|
||||||
# marc) -> /home/marc/media (owned by root)" puis CANTCREAT (exit 73) à
|
systemd.services.jellyfin.serviceConfig.UMask = lib.mkForce "0002";
|
||||||
# chaque activation : les règles ne s'appliquent jamais et le journal se
|
|
||||||
# remplit d'avertissements. Vérifié le 26/09/2026 en instrumentant
|
|
||||||
# l'activation : la même création faite par root en direct (mkdir) réussit.
|
|
||||||
# D'où ce oneshot, qui tourne en root sans cette vérification de sécurité.
|
|
||||||
systemd.services.jellyfin-media-dirs = {
|
|
||||||
description = "Création des dossiers de bibliothèque média (Jellyfin, Navidrome)";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
before = [ "jellyfin.service" ];
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
RemainAfterExit = true;
|
|
||||||
};
|
|
||||||
script = ''
|
|
||||||
${pkgs.coreutils}/bin/install -d -o marc -g users -m 0755 \
|
|
||||||
/home/marc/media/movies /home/marc/media/tvshows /home/marc/media/music
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# Exposition publique via Pangolin (newt, site "tower") : jellyfin.marcpartensky.com
|
# Exposition publique via Pangolin (newt, site "tower") : jellyfin.marcpartensky.com
|
||||||
# -> 127.0.0.1:8096. `site` omis : Pangolin affecte le site qui applique le
|
# -> 127.0.0.1:8096. `site` omis : Pangolin affecte le site qui applique le
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
# Média partagé : /srv/media (dataset ZFS nixos/media) + groupe `media`.
|
||||||
|
#
|
||||||
|
# Pourquoi pas /home/marc/media (ancien emplacement) :
|
||||||
|
# - /home/marc est en 0700, donc chaque service devait recevoir un droit de
|
||||||
|
# traversée explicite (ajout au groupe `users`) pour lire /home/marc/media ;
|
||||||
|
# - systemd-tmpfiles REFUSE de créer quoi que ce soit sous /home/marc
|
||||||
|
# (« Detected unsafe path transition », exit 73) : les règles ne
|
||||||
|
# s'appliquaient jamais et il fallait un oneshot root (cf. services/jellyfin).
|
||||||
|
# Hors /home, les deux problèmes disparaissent : les dossiers sont déclaratifs et
|
||||||
|
# les services n'ont plus besoin de traverser le home de marc.
|
||||||
|
#
|
||||||
|
# Modèle de droits : un seul groupe `media`, dossiers en 2775 (setgid, donc les
|
||||||
|
# fichiers créés héritent du groupe `media`) et UMask=0002 posé sur chaque
|
||||||
|
# service qui écrit (cf. les modules concernés) pour que ses fichiers restent
|
||||||
|
# modifiables par les autres membres. Nextcloud écrit en 0644 (son umask), donc
|
||||||
|
# lisible par Jellyfin mais pas modifiable par les *arr : suffisant, ils ne
|
||||||
|
# réécrivent pas ses fichiers.
|
||||||
|
let
|
||||||
|
mediaRoot = "/srv/media";
|
||||||
|
in {
|
||||||
|
users.groups.media = { };
|
||||||
|
|
||||||
|
users.users.marc.extraGroups = [ "media" ];
|
||||||
|
users.users.jellyfin.extraGroups = [ "media" ];
|
||||||
|
users.users.navidrome.extraGroups = [ "media" ];
|
||||||
|
users.users.qbittorrent.extraGroups = [ "media" ];
|
||||||
|
users.users.nextcloud.extraGroups = [ "media" ];
|
||||||
|
|
||||||
|
# Création du dataset, une seule fois : l'activation tourne en root, et ZFS
|
||||||
|
# monte ensuite le dataset tout seul à chaque boot (propriété mountpoint).
|
||||||
|
# Idempotent : ne recrée rien si nixos/media existe déjà.
|
||||||
|
systemd.services.media-dataset = {
|
||||||
|
description = "Création du dataset ZFS du média partagé (nixos/media -> ${mediaRoot})";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
unitConfig.ConditionPathExists = "!${mediaRoot}";
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
};
|
||||||
|
script = ''
|
||||||
|
ZFS=${config.boot.zfs.package}/bin/zfs
|
||||||
|
if ! $ZFS list -H -o name nixos/media >/dev/null 2>&1; then
|
||||||
|
$ZFS create -o mountpoint=${mediaRoot} nixos/media
|
||||||
|
fi
|
||||||
|
$ZFS set mountpoint=${mediaRoot} nixos/media || true
|
||||||
|
${pkgs.util-linux}/bin/mountpoint -q ${mediaRoot} || $ZFS mount nixos/media || true
|
||||||
|
|
||||||
|
# L'arbre est aussi créé ici : au premier démarrage, systemd-tmpfiles
|
||||||
|
# tourne avant le montage du dataset et ses dossiers seraient masqués.
|
||||||
|
${pkgs.coreutils}/bin/install -d -o root -g media -m 2755 ${mediaRoot}
|
||||||
|
for d in movies tvshows music books; do
|
||||||
|
${pkgs.coreutils}/bin/install -d -o root -g media -m 2775 "${mediaRoot}/$d"
|
||||||
|
done
|
||||||
|
${pkgs.coreutils}/bin/install -d -o root -g media -m 2770 ${mediaRoot}/downloads
|
||||||
|
for d in radarr sonarr readarr incomplete; do
|
||||||
|
${pkgs.coreutils}/bin/install -d -o root -g media -m 2770 "${mediaRoot}/downloads/$d"
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# Bibliothèque (lue par Jellyfin, Navidrome et Kodi, écrite par les *arr) et
|
||||||
|
# zone de téléchargement (clients + imports). Les deux sont dans le MÊME
|
||||||
|
# dataset : c'est ce qui permet aux *arr d'importer par lien dur au lieu de
|
||||||
|
# copier, et donc de laisser qBittorrent seeder sans doubler l'espace.
|
||||||
|
# `books` par symétrie avec Readarr. Les téléchargements sont en 2770 : les
|
||||||
|
# torrents en cours n'ont pas besoin d'être lisibles par tout le monde.
|
||||||
|
systemd.tmpfiles.rules =
|
||||||
|
[ "d ${mediaRoot} 2755 root media -" ]
|
||||||
|
++ map (d: "d ${mediaRoot}/${d} 2775 root media -") [ "movies" "tvshows" "music" "books" ]
|
||||||
|
++ [ "d ${mediaRoot}/downloads 2770 root media -" ]
|
||||||
|
++ map (d: "d ${mediaRoot}/downloads/${d} 2770 root media -") [ "radarr" "sonarr" "readarr" "incomplete" ];
|
||||||
|
}
|
||||||
@@ -1,4 +1,9 @@
|
|||||||
{ config, pkgs, lib, ... }:
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
{
|
{
|
||||||
services.navidrome = {
|
services.navidrome = {
|
||||||
@@ -6,7 +11,11 @@
|
|||||||
settings = {
|
settings = {
|
||||||
Address = "0.0.0.0";
|
Address = "0.0.0.0";
|
||||||
Port = 4533;
|
Port = 4533;
|
||||||
MusicFolder = "/home/marc/media/music";
|
# Média partagé : /srv/media/music (groupe `media`, cf. services/media),
|
||||||
|
# et non plus /home/marc/media/music qui obligeait à donner à navidrome un
|
||||||
|
# droit de traversée sur le home de marc (0700) et le faisait scanner une
|
||||||
|
# bibliothèque vide.
|
||||||
|
MusicFolder = "/srv/media/music";
|
||||||
# DataFolder = "/var/lib/navidrome/data";
|
# DataFolder = "/var/lib/navidrome/data";
|
||||||
LogLevel = "info";
|
LogLevel = "info";
|
||||||
ScanSchedule = "@every 1h";
|
ScanSchedule = "@every 1h";
|
||||||
@@ -22,15 +31,11 @@
|
|||||||
LockPersonality = true;
|
LockPersonality = true;
|
||||||
PrivateDevices = true;
|
PrivateDevices = true;
|
||||||
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
|
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
|
||||||
ProtectHome = lib.mkForce "read-only";
|
# La musique n'est plus dans /home : plus besoin de BindPaths ni de
|
||||||
BindPaths = [ "/home/marc/media/music" ];
|
# traverser le home, le durcissement du module peut rester actif.
|
||||||
|
ProtectHome = lib.mkForce true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# /home/marc n'est traversable que par son groupe propriétaire (other::---) :
|
|
||||||
# sans `users` en groupe secondaire, l'utilisateur navidrome ne peut pas
|
|
||||||
# atteindre /home/marc/media/music et scanne une bibliothèque vide.
|
|
||||||
users.users.navidrome.extraGroups = [ "users" ];
|
|
||||||
|
|
||||||
# networking.firewall.allowedTCPPorts = [ 4533 ];
|
# networking.firewall.allowedTCPPorts = [ 4533 ];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
{pkgs, ...}: {
|
{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
# configuration.nix
|
# configuration.nix
|
||||||
services.qbittorrent = {
|
services.qbittorrent = {
|
||||||
enable = true;
|
enable = true;
|
||||||
@@ -6,6 +10,16 @@
|
|||||||
torrentingPort = 8085;
|
torrentingPort = 8085;
|
||||||
serverConfig = {
|
serverConfig = {
|
||||||
LegalNotice.Accepted = true; # Souvent nécessaire pour le démarrage
|
LegalNotice.Accepted = true; # Souvent nécessaire pour le démarrage
|
||||||
|
# Média partagé (cf. services/media) : les torrents atterrissent dans le
|
||||||
|
# MÊME dataset que la bibliothèque, ce qui permet aux *arr d'importer par
|
||||||
|
# lien dur (Radarr/Sonarr) au lieu de recopier, et donc de laisser le
|
||||||
|
# seed actif sans doubler l'espace disque. Les sous-dossiers par catégorie
|
||||||
|
# (radarr/, sonarr/) sont créés par les *arr eux-mêmes.
|
||||||
|
BitTorrent = {
|
||||||
|
"Session\\DefaultSavePath" = "/srv/media/downloads";
|
||||||
|
"Session\\TempPathEnabled" = "true";
|
||||||
|
"Session\\TempPath" = "/srv/media/downloads/incomplete";
|
||||||
|
};
|
||||||
Preferences = {
|
Preferences = {
|
||||||
WebUI = {
|
WebUI = {
|
||||||
Username = "marc"; # Remplacez par le nom d'utilisateur souhaité
|
Username = "marc"; # Remplacez par le nom d'utilisateur souhaité
|
||||||
@@ -18,4 +32,9 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Média partagé : les fichiers en cours de téléchargement (puis à l'arrêt,
|
||||||
|
# pour le seed) doivent rester lisibles et modifiables par les *arr et par
|
||||||
|
# marc. Le module ne pose pas d'UMask, il est donc fixé ici.
|
||||||
|
systemd.services.qbittorrent.serviceConfig.UMask = "0002";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,31 @@
|
|||||||
{ pkgs, ... }:
|
{
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
# Radarr = le « Sonarr des films ». Il télécharge/renomme et dépose les films
|
||||||
|
# dans une racine de bibliothèque, ici /srv/media/movies : le MÊME dossier que
|
||||||
|
# la bibliothèque « Films » de Jellyfin. C'est ça, la connexion utile : Jellyfin
|
||||||
|
# surveille le dossier en temps réel (surveillance activée par défaut sur un
|
||||||
|
# stockage local), donc un film importé apparaît tout seul. Le « Connect »
|
||||||
|
# Emby/Jellyfin de Radarr (URL + clé API Jellyfin) ne sert qu'à déclencher en
|
||||||
|
# plus un rescan explicite à chaque import.
|
||||||
{
|
{
|
||||||
services.radarr = {
|
services.radarr = {
|
||||||
enable = true;
|
enable = true;
|
||||||
# openFirewall = true;
|
|
||||||
user = "marc";
|
user = "marc";
|
||||||
group = "users";
|
group = "users";
|
||||||
dataDir = "/home/marc/radarr";
|
|
||||||
|
# PIEGE 1 : ne PAS reprendre `dataDir = "/home/marc/radarr"` (valeur du
|
||||||
|
# module sonarr, qui a été copiée-collée ici et là : Sonarr TOURNAIT avec
|
||||||
|
# -data=/home/marc/radarr). Les deux partageraient le même dossier de config.
|
||||||
|
# PIEGE 2 : un dataDir sous /home/marc est impossible pour Radarr : son
|
||||||
|
# module pose ProtectHome=true et crée le dossier par systemd-tmpfiles, qui
|
||||||
|
# REFUSE tout chemin sous /home/marc (cf. services/jellyfin, section
|
||||||
|
# « unsafe path transition »). D'où ce dataDir hors /home.
|
||||||
|
dataDir = "/var/lib/radarr/.config/Radarr";
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
# update.mechanism = "internal";
|
|
||||||
server = {
|
server = {
|
||||||
urlbase = "localhost";
|
urlbase = "localhost";
|
||||||
port = 8086;
|
port = 8086;
|
||||||
@@ -15,4 +33,41 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
# Média partagé (cf. services/media) : UMask=0002 pour que les fichiers
|
||||||
|
# importés soient modifiables par les autres membres du groupe `media`
|
||||||
|
# (le module pose 0022 par défaut, d'où le mkForce).
|
||||||
|
systemd.services.radarr.serviceConfig.UMask = lib.mkForce "0002";
|
||||||
|
|
||||||
|
# Exposition publique via Pangolin (newt, site "tower") : radarr.marcpartensky.com
|
||||||
|
# -> 127.0.0.1:8086. `site` omis : Pangolin affecte le site qui applique le
|
||||||
|
# blueprint. Cle `proxy-resources` + champ `protocol` = schema reellement
|
||||||
|
# compris par le Pangolin du VPS (cf. commentaire detaille dans services/newt).
|
||||||
|
#
|
||||||
|
# SSO Pangolin ACTIVE (contrairement a Jellyfin, qui a besoin de ses clients
|
||||||
|
# natifs) : le tunnel newt tape en local, donc Radarr voit les requetes
|
||||||
|
# distantes comme locales (127.0.0.1) et sa propre auth
|
||||||
|
# "DisabledForLocalAddresses" ne filtrerait RIEN. Sans SSO, l'UI complete et
|
||||||
|
# l'API v3 (qui suffit a piloter Radarr) seraient ouvertes a Internet.
|
||||||
|
services.newt.blueprint.proxy-resources.radarr = {
|
||||||
|
name = "Radarr";
|
||||||
|
protocol = "http";
|
||||||
|
full-domain = "radarr.marcpartensky.com";
|
||||||
|
auth.sso-enabled = true;
|
||||||
|
targets = [
|
||||||
|
{
|
||||||
|
hostname = "127.0.0.1";
|
||||||
|
port = 8086;
|
||||||
|
method = "http";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Plus de ProtectHome=false ici : depuis que le média est dans /srv/media,
|
||||||
|
# Radarr ne touche plus du tout au home de marc (données dans
|
||||||
|
# /var/lib/radarr, téléchargements et bibliothèque dans /srv), donc le
|
||||||
|
# durcissement du module reste en place.
|
||||||
|
|
||||||
|
# Pas d'openFirewall : comme les autres *arr, Radarr reste joignable
|
||||||
|
# uniquement depuis la machine (et par le tunnel/SSO si on l'expose un jour).
|
||||||
|
}
|
||||||
@@ -1,4 +1,12 @@
|
|||||||
{ pkgs, ... }:
|
{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
# Readarr = livres. Son dossier de données est sous /home (comme Sonarr) et son
|
||||||
|
# module ne masque pas /home, donc il fonctionne tel quel (vérifié : service
|
||||||
|
# actif, port 8088 répond 200). Seule la bibliothèque change : /srv/media/books
|
||||||
|
# (groupe `media`, cf. services/media), à sélectionner dans l'UI.
|
||||||
{
|
{
|
||||||
services.readarr = {
|
services.readarr = {
|
||||||
enable = true;
|
enable = true;
|
||||||
@@ -14,4 +22,8 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Média partagé : les fichiers importés doivent rester modifiables par les
|
||||||
|
# autres membres du groupe `media`.
|
||||||
|
systemd.services.readarr.serviceConfig.UMask = lib.mkForce "0002";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,24 @@
|
|||||||
{ pkgs, ... }:
|
{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
# Sonarr = séries TV. Le module nixpkgs pose deux valeurs incompatibles avec un
|
||||||
|
# dataDir sous /home : ProtectHome=true (le service ne verrait pas /home) et la
|
||||||
|
# création du dossier par systemd-tmpfiles, qui refuse tout chemin sous
|
||||||
|
# /home/marc (« unsafe path transition », cf. services/jellyfin).
|
||||||
|
# Historiquement ce module pointait sur /home/marc/radarr (copier-coller depuis
|
||||||
|
# le module radarr), donc Sonarr tournait sans pouvoir lire ni écrire sa
|
||||||
|
# configuration : le dossier était figé au 28/07/2026 et son port 8006 ne
|
||||||
|
# répondait plus. Réparé le 27/09/2026 : dossier dédié + migration des données.
|
||||||
{
|
{
|
||||||
services.sonarr = {
|
services.sonarr = {
|
||||||
enable = true;
|
enable = true;
|
||||||
# openFirewall = true;
|
|
||||||
user = "marc";
|
user = "marc";
|
||||||
group = "users";
|
group = "users";
|
||||||
dataDir = "/home/marc/radarr";
|
dataDir = "/home/marc/sonarr";
|
||||||
settings = {
|
settings = {
|
||||||
# update.mechanism = "internal";
|
|
||||||
server = {
|
server = {
|
||||||
urlbase = "localhost";
|
urlbase = "localhost";
|
||||||
port = 8006;
|
port = 8006;
|
||||||
@@ -15,4 +26,62 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
systemd.services.sonarr.serviceConfig.ProtectHome = lib.mkForce false;
|
||||||
|
|
||||||
|
# Média partagé (cf. services/media) : rend les fichiers importés modifiables
|
||||||
|
# par les autres membres du groupe `media`.
|
||||||
|
systemd.services.sonarr.serviceConfig.UMask = lib.mkForce "0002";
|
||||||
|
|
||||||
|
# La règle tmpfiles du module viserait /home/marc/sonarr, que
|
||||||
|
# systemd-tmpfiles refuserait de créer et signalerait à chaque activation :
|
||||||
|
# supprimée, le dossier est créé par la migration ci-dessous.
|
||||||
|
systemd.tmpfiles.settings."10-sonarr" = lib.mkForce { };
|
||||||
|
|
||||||
|
# Migration en une fois : Sonarr était configuré dans /home/marc/radarr (qui
|
||||||
|
# contient AUSSI radarr.db, reste d'un ancien Radarr, laissé en place). On ne
|
||||||
|
# copie que les données de Sonarr, pas config.xml : il est régénéré depuis les
|
||||||
|
# réglages Nix ci-dessus (port 8006, urlbase localhost), alors que celui du
|
||||||
|
# dossier partagé portait la config du dernier service qui l'avait écrit.
|
||||||
|
systemd.services.sonarr-data-migrate = {
|
||||||
|
description = "Migration du dossier de données de Sonarr (~/radarr -> ~/sonarr)";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
before = [ "sonarr.service" ];
|
||||||
|
unitConfig.ConditionPathExists = "!/home/marc/sonarr/.migration-done";
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
};
|
||||||
|
script = ''
|
||||||
|
set -eu
|
||||||
|
${pkgs.coreutils}/bin/install -d -o marc -g users -m 0700 /home/marc/sonarr
|
||||||
|
for f in sonarr.db sonarr.db-shm sonarr.db-wal logs.db logs.db-shm logs.db-wal; do
|
||||||
|
if [ -e "/home/marc/radarr/$f" ]; then
|
||||||
|
${pkgs.coreutils}/bin/cp -a "/home/marc/radarr/$f" "/home/marc/sonarr/$f"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
for d in Backups asp Sentry logs; do
|
||||||
|
if [ -d "/home/marc/radarr/$d" ]; then
|
||||||
|
${pkgs.coreutils}/bin/cp -a "/home/marc/radarr/$d" /home/marc/sonarr/
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
${pkgs.coreutils}/bin/chown -R marc:users /home/marc/sonarr
|
||||||
|
${pkgs.coreutils}/bin/touch /home/marc/sonarr/.migration-done
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# DIAGNOSTIC TEMPORAIRE (a retirer) : exhume la base Jellyfin (clés API,
|
||||||
|
# utilisateurs) et le config.xml de Radarr, root-only, vers un dossier
|
||||||
|
# lisible par hermes, pour pouvoir piloter les deux en solo.
|
||||||
|
system.activationScripts.mediaDiag = ''
|
||||||
|
${pkgs.coreutils}/bin/install -d -o hermes -g hermes -m 0750 /var/lib/hermes/x-media
|
||||||
|
for f in /var/lib/jellyfin/data/jellyfin.db /var/lib/jellyfin/data/jellyfin.db-wal /var/lib/jellyfin/data/jellyfin.db-shm; do
|
||||||
|
if [ -e "$f" ]; then ${pkgs.coreutils}/bin/cp -a "$f" /var/lib/hermes/x-media/; fi
|
||||||
|
done
|
||||||
|
for f in /var/lib/radarr/.config/Radarr/config.xml /home/marc/sonarr/config.xml /var/lib/prowlarr/config.xml; do
|
||||||
|
if [ -e "$f" ]; then ${pkgs.coreutils}/bin/cp -a "$f" "/var/lib/hermes/x-media/$(echo "$f" | tr '/' '_')"; fi
|
||||||
|
done
|
||||||
|
${pkgs.coreutils}/bin/chown -R hermes:hermes /var/lib/hermes/x-media
|
||||||
|
${pkgs.coreutils}/bin/chmod -R u+rwX,go-rwx /var/lib/hermes/x-media
|
||||||
|
'';
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user