Implement r5500 media stack configuration with NFS and Docker services
- Added configuration for media stack on r5500, including paths for Jellyfin, Sonarr, Radarr, and other media services. - Integrated NFS client for accessing Jellyfin libraries from nixdesk. - Established Docker services for Dispatcharr and Organizr, including necessary user and group setups. - Created systemd services for managing media directories and ensuring proper permissions.
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
# Media stack storage on r5500: btrfs subvolume @media-stack on the OS disk (sda4).
|
||||
{ config, pkgs, lib, ... }:
|
||||
let
|
||||
btrfsUuid = "934a5ec3-4bab-49c3-96c9-c857c50076ba";
|
||||
btrfsDevice = "/dev/disk/by-uuid/${btrfsUuid}";
|
||||
# Created under subvol=@ → full path is @/@media-stack (not a top-level @media-stack).
|
||||
mediaSubvol = "@/@media-stack";
|
||||
in
|
||||
{
|
||||
# Create @media-stack before /mnt/media-stack is mounted.
|
||||
systemd.services.r5500-media-stack-subvolume = {
|
||||
description = "Create btrfs subvolume @media-stack on sda4 if missing";
|
||||
before = [ "mnt-media\\x2dmedia\\x2dstack.mount" ];
|
||||
wantedBy = [ "local-fs-pre.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
rootMount="/mnt/.r5500-btrfs-root"
|
||||
mkdir -p "$rootMount"
|
||||
if ! mountpoint -q "$rootMount"; then
|
||||
mount -o subvol=@ "${btrfsDevice}" "$rootMount"
|
||||
umountAfter=1
|
||||
else
|
||||
umountAfter=0
|
||||
fi
|
||||
if ! ${pkgs.btrfs-progs}/bin/btrfs subvolume show "$rootMount/@media-stack" >/dev/null 2>&1; then
|
||||
${pkgs.btrfs-progs}/bin/btrfs subvolume create "$rootMount/@media-stack"
|
||||
fi
|
||||
if [ "$umountAfter" -eq 1 ]; then
|
||||
umount "$rootMount"
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
# Optional 1 TiB cap (run once after first boot if desired):
|
||||
# sudo btrfs quota enable /mnt/media-stack && sudo btrfs qgroup limit 1T /mnt/media-stack
|
||||
|
||||
fileSystems."/mnt/media-stack" = {
|
||||
device = btrfsDevice;
|
||||
fsType = "btrfs";
|
||||
neededForBoot = false;
|
||||
options = [
|
||||
"subvol=${mediaSubvol}"
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
"nofail"
|
||||
"x-systemd.device-timeout=30"
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
# Shared media group, directory layout, and Jellyfin config bind-mount on /mnt/media-stack.
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
paths = import ./media-stack-paths.nix;
|
||||
prowlarrCustomIndexer = "${./../_services/prowlarr/torrent9-custom.yml}";
|
||||
inherit (paths)
|
||||
mediaRoot
|
||||
downloadsDir
|
||||
downloadsIncompleteDir
|
||||
sonarrDataDir
|
||||
radarrDataDir
|
||||
prowlarrDataDir
|
||||
qbittorrentDataDir
|
||||
seerrConfigDir
|
||||
dispatcharrDataDir
|
||||
organizrDataDir
|
||||
jellyfinConfigDir
|
||||
jellyfinMoviesDir
|
||||
jellyfinTvDir
|
||||
;
|
||||
in
|
||||
{
|
||||
_module.args.mediaStackPaths = paths;
|
||||
|
||||
users.groups.media = { };
|
||||
|
||||
users.users.server.extraGroups = [ "media" ];
|
||||
|
||||
# Layout dirs only after /mnt/media-stack is mounted (tmpfiles at early boot would
|
||||
# otherwise create paths on the root fs and break bind mounts / boot).
|
||||
systemd.services.r5500-media-stack-dirs = {
|
||||
description = "Create media-stack directory layout";
|
||||
after = [ "mnt-media\\x2dmedia\\x2dstack.mount" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
set -e
|
||||
install -d -m 0775 -o root -g media ${mediaRoot}
|
||||
install -d -m 2775 -o root -g media ${jellyfinMoviesDir} ${jellyfinTvDir} ${downloadsDir}
|
||||
install -d -m 2775 -o root -g media ${downloadsIncompleteDir}
|
||||
install -d -m 0755 -o jellyfin -g jellyfin ${jellyfinConfigDir}
|
||||
install -d -m 0700 -o sonarr -g sonarr ${sonarrDataDir}
|
||||
install -d -m 0700 -o radarr -g radarr ${radarrDataDir}
|
||||
install -d -m 0700 -o prowlarr -g prowlarr ${prowlarrDataDir}
|
||||
install -d -m 0750 -o qbittorrent -g qbittorrent ${qbittorrentDataDir}
|
||||
install -d -m 0755 -o jellyseerr -g jellyseerr ${seerrConfigDir} 2>/dev/null \
|
||||
|| install -d -m 0755 -o root -g root ${seerrConfigDir}
|
||||
install -d -m 0777 -o root -g root ${dispatcharrDataDir}
|
||||
install -d -m 0755 -o organizr -g organizr ${organizrDataDir} 2>/dev/null \
|
||||
|| install -d -m 0755 -o root -g root ${organizrDataDir}
|
||||
install -d -m 0700 -o prowlarr -g prowlarr ${prowlarrDataDir}/Definitions/Custom
|
||||
ln -sfn ${prowlarrCustomIndexer} ${prowlarrDataDir}/Definitions/Custom/torrent9-custom.yml
|
||||
'';
|
||||
};
|
||||
|
||||
# Jellyfin metadata on the media subvolume; nofail so a missing subvol never bricks boot.
|
||||
fileSystems."/var/lib/jellyfin" = {
|
||||
device = jellyfinConfigDir;
|
||||
fsType = "none";
|
||||
neededForBoot = false;
|
||||
options = [
|
||||
"bind"
|
||||
"nofail"
|
||||
"x-systemd.after=mnt-media\\x2dmedia\\x2dstack.mount"
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# Path constants for the r5500 media stack (imported by _services/* and media-paths.nix).
|
||||
{
|
||||
mediaRoot = "/mnt/media-stack";
|
||||
downloadsDir = "/mnt/media-stack/downloads";
|
||||
downloadsIncompleteDir = "/mnt/media-stack/downloads/incomplete";
|
||||
sonarrDataDir = "/mnt/media-stack/sonarr";
|
||||
radarrDataDir = "/mnt/media-stack/radarr";
|
||||
prowlarrDataDir = "/mnt/media-stack/prowlarr";
|
||||
qbittorrentDataDir = "/mnt/media-stack/qbittorrent";
|
||||
seerrConfigDir = "/mnt/media-stack/seerr";
|
||||
dispatcharrDataDir = "/mnt/media-stack/dispatcharr";
|
||||
organizrDataDir = "/mnt/media-stack/organizr";
|
||||
jellyfinConfigDir = "/mnt/media-stack/jellyfin/config";
|
||||
jellyfinMoviesDir = "/mnt/media-stack/jellyfin/movies";
|
||||
jellyfinTvDir = "/mnt/media-stack/jellyfin/tv";
|
||||
}
|
||||
Reference in New Issue
Block a user