ookflix: refactors FIX COMMIT

This commit is contained in:
ooks-io 2024-12-02 18:55:06 +11:00
parent da77c223ff
commit c096dc295a
10 changed files with 154 additions and 138 deletions

View file

@ -1,11 +1,4 @@
{ {
lib,
config,
...
}: let
inherit (lib) elem mkIf;
inherit (config.ooknet.server) services;
in {
imports = [ imports = [
./jellyfin.nix ./jellyfin.nix
./plex.nix ./plex.nix
@ -14,21 +7,9 @@ in {
./sonarr.nix ./sonarr.nix
./prowlarr.nix ./prowlarr.nix
./gluetun.nix ./gluetun.nix
./transmission.nix ./qbittorrent.nix
./shared.nix ./shared.nix
./options.nix ./options.nix
]; ];
config = mkIf (elem "ookflix" services) {
ooknet.server.ookflix = {
gpuAcceleration.enable = true;
services = {
jellyfin.enable = true;
plex.enable = true;
jellyseer.enable = true;
tautulli.enable = true;
};
};
};
} }

View file

@ -6,27 +6,24 @@
... ...
}: let }: let
ookflixLib = import ./lib.nix {inherit self lib config;}; ookflixLib = import ./lib.nix {inherit self lib config;};
inherit (ookflixLib) mkServiceUser; inherit (ookflixLib) mkServiceUser mkServiceSecret;
inherit (lib) mkIf; inherit (lib) mkIf;
inherit (ook.lib.container) mkContainerEnvironment mkContainerPort mkServiceSecret; inherit (ook.lib.container) mkContainerEnvironment mkContainerPort;
inherit (config.ooknet.server.ookflix.services) transmission gluetun; inherit (config.ooknet.server.ookflix.services) qbittorrent gluetun;
in { in {
config = mkIf gluetun.enable { config = mkIf gluetun.enable {
users = mkServiceUser gluetun.user.name; users = mkServiceUser gluetun.user.name;
age.secrets.vpn_env = mkServiceSecret "vpn_env" "gluetun"; age.secrets = mkServiceSecret "vpn_env" "gluetun";
virtualisation.oci-containers.containers = { virtualisation.oci-containers.containers = {
# vpn container # vpn container
gluetun = mkIf { gluetun = mkIf gluetun.enable {
image = "qmcgaw/gluetun:latest"; image = "qmcgaw/gluetun:latest";
# should make this an option. # should make this an option.
environmentFiles = [config.age.secrets.vpn_env.path]; environmentFiles = [config.age.secrets.vpn_env.path];
ports = [ ports = [
(mkContainerPort transmission.port) (mkContainerPort qbittorrent.port)
]; ];
environment = mkContainerEnvironment gluetun.user.id gluetun.group.id { environment = mkContainerEnvironment gluetun.user.id gluetun.group.id;
VPN_SERVICE_PROVIDER = gluetun.provider;
VPN_TYPE = "wireguard";
};
extraOptions = [ extraOptions = [
# give network admin permissions # give network admin permissions
"--cap-add=NET_ADMIN" "--cap-add=NET_ADMIN"

View file

@ -23,7 +23,7 @@ in {
image = "lscr.io/linuxserver/jellyfin:latest"; image = "lscr.io/linuxserver/jellyfin:latest";
autoStart = true; autoStart = true;
hostname = "jellyfin"; hostname = "jellyfin";
ports = ["${jellyfin.port}:${jellyfin.port}"]; ports = [(mkContainerPort jellyfin.port)];
volumes = [ volumes = [
"${volumes.media.root}:/data" "${volumes.media.root}:/data"
"${jellyfin.stateDir}:/config" "${jellyfin.stateDir}:/config"

View file

@ -9,6 +9,7 @@
inherit (lib.types) int path port str; inherit (lib.types) int path port str;
inherit (config.ooknet) server; inherit (config.ooknet) server;
cfg = server.ookflix; cfg = server.ookflix;
ookflixEnabled = elem "ookflix" server.services;
mkSubdomainOption = name: description: example: mkSubdomainOption = name: description: example:
mkOption { mkOption {
@ -60,19 +61,25 @@
inherit description example; inherit description example;
}; };
mkVolumeOption = type: pathValue: mkVolumeOption = rootPath: pathValue:
mkOption { mkOption {
type = path; type = path;
default = default =
if type == "state" if rootPath == "state"
then "${cfg.volumes.state.root}/${pathValue}" then "${cfg.volumes.state.root}/${pathValue}"
else if type == "media" else if rootPath == "data"
then "${cfg.volumes.data.root}/${pathValue}"
else if rootPath == "media"
then "${cfg.volumes.media.root}/${pathValue}" then "${cfg.volumes.media.root}/${pathValue}"
else if type == "downloads" else if rootPath == "torrents"
then "${cfg.volumes.downloads.root}/${pathValue}" then "${cfg.volumes.torrents.root}/${pathValue}"
else if type == "root" else if rootPath == "usenet"
then "${cfg.volumes.usenet.root}/${pathValue}"
else if rootPath == "usenet/complete"
then "${cfg.volumes.usenet.complete.root}/${pathValue}"
else if rootPath == "root"
then pathValue then pathValue
else throw "Invalid VolumeOption type: ${type}. Must be one of 'state' 'media' 'downloads' 'root'"; else throw "Invalid VolumeOption rootPath: ${rootPath}. Must be one of 'state' 'data' 'media' 'torrents' 'usenet' 'usenet/complete' 'root'";
}; };
mkServiceOptions = name: { mkServiceOptions = name: {
@ -81,7 +88,7 @@
uid, uid,
... ...
} @ args: { } @ args: {
enable = mkEnableOption "Enable ${name} container"; enable = mkEnableOption "Enable ${name} container" // {default = ookflixEnabled;};
port = mkPortOption args.port "Port for ${name} container." 80; port = mkPortOption args.port "Port for ${name} container." 80;
domain = mkSubdomainOption name "Domain for ${name} container." "${name}.mydomain.com"; domain = mkSubdomainOption name "Domain for ${name} container." "${name}.mydomain.com";
stateDir = mkVolumeOption "state" name; stateDir = mkVolumeOption "state" name;
@ -93,7 +100,7 @@
uid, uid,
... ...
} @ args: { } @ args: {
enable = mkEnableOption "Enable ${name} container"; enable = mkEnableOption "Enable ${name} container" // {default = ookflixEnabled;};
user = mkUserOption name args.uid; user = mkUserOption name args.uid;
group = mkGroupOption name args.gid; group = mkGroupOption name args.gid;
}; };
@ -118,7 +125,7 @@
}; };
mkServiceSecret = name: service: { mkServiceSecret = name: service: {
${name} = { ${name} = {
file = "${self}/secrets/container/${name}.age"; file = "${self}/secrets/containers/${name}.age";
owner = cfg.services.${service}.user.name; owner = cfg.services.${service}.user.name;
group = cfg.services.${service}.group.name; group = cfg.services.${service}.group.name;
}; };

View file

@ -6,16 +6,19 @@
}: let }: let
ookflixLib = import ./lib.nix {inherit lib config self;}; ookflixLib = import ./lib.nix {inherit lib config self;};
inherit (ookflixLib) mkVolumeOption mkGroupOption mkServiceOptions mkBasicServiceOptions; inherit (ookflixLib) mkVolumeOption mkGroupOption mkServiceOptions mkBasicServiceOptions mkPortOption;
inherit (lib) mkOption mkEnableOption; inherit (lib) mkOption mkEnableOption elem;
inherit (config.ooknet.server) services;
inherit (lib.types) enum; inherit (lib.types) enum;
inherit (config.ooknet) server;
cfg = server.ookflix;
in { in {
options.ooknet.server.ookflix = { options.ooknet.server.ookflix = {
enable = mkEnableOption "Enable ookflix a container based media server module"; enable =
mkEnableOption "Enable ookflix a container based media server module"
// {default = elem "ookflix" services;};
gpuAcceleration = { gpuAcceleration = {
enable = mkEnableOption "Enable GPU acceleration for video streamers"; enable =
mkEnableOption "Enable GPU acceleration for video streamers"
// {default = elem "ookflix" services;};
type = mkOption { type = mkOption {
type = enum ["nvidia" "intel" "amd"]; type = enum ["nvidia" "intel" "amd"];
default = config.ooknet.hardware.gpu.type; default = config.ooknet.hardware.gpu.type;
@ -28,15 +31,26 @@ in {
volumes = { volumes = {
state.root = mkVolumeOption "root" "/var/lib/ookflix"; state.root = mkVolumeOption "root" "/var/lib/ookflix";
data.root = mkVolumeOption "root" "/jellyfin"; data.root = mkVolumeOption "root" "/jellyfin";
downloads = {
root = mkVolumeOption "${cfg.content.root}/downloads"; torrents = {
tv = mkVolumeOption "downloads" "tv"; root = mkVolumeOption "data" "torrents";
movies = mkVolumeOption "downloads" "movies"; tv = mkVolumeOption "torrents" "tv";
books = mkVolumeOption "downloads" "books"; movies = mkVolumeOption "torrents" "movies";
books = mkVolumeOption "torrents" "books";
}; };
usenet = {
root = mkVolumeOption "data" "usenet";
incomplete = mkVolumeOption "usenet" "incomplete";
complete = {
root = mkVolumeOption "usenet" "complete";
tv = mkVolumeOption "usenet/complete" "tv";
movies = mkVolumeOption "usenet/complete" "movies";
books = mkVolumeOption "usenet/complete" "books";
};
};
media = { media = {
root = mkVolumeOption "root" "${cfg.volumes.content.root}/media"; root = mkVolumeOption "data" "media";
movies = mkVolumeOption "media" "movies"; movies = mkVolumeOption "media" "movies";
tv = mkVolumeOption "media" "tv"; tv = mkVolumeOption "media" "tv";
books = mkVolumeOption "media" "books"; books = mkVolumeOption "media" "books";
@ -74,11 +88,13 @@ in {
uid = 982; uid = 982;
gid = 987; gid = 987;
}; };
transmission = mkServiceOptions "transmission" { qbittorrent =
port = 9091; mkServiceOptions "qbittorrent" {
uid = 70; port = 8080;
gid = 70; uid = 377;
}; gid = 377;
}
// {torrentPort = mkPortOption 58080 "Torrenting Port for qbittorrent" 58080;};
jellyseer = mkServiceOptions "jellyseer" { jellyseer = mkServiceOptions "jellyseer" {
port = 5055; port = 5055;
uid = 345; uid = 345;

View file

@ -22,7 +22,6 @@ in {
hostname = "prowlarr"; hostname = "prowlarr";
ports = [(mkContainerPort prowlarr.port)]; ports = [(mkContainerPort prowlarr.port)];
volumes = ["${prowlarr.stateDir}:/config"]; volumes = ["${prowlarr.stateDir}:/config"];
extraOptions = ["--network" "host"];
labels = mkContainerLabel { labels = mkContainerLabel {
name = "prowlarr"; name = "prowlarr";
inherit (prowlarr) port domain; inherit (prowlarr) port domain;

View file

@ -0,0 +1,46 @@
{
config,
lib,
ook,
self,
...
}: let
ookflixLib = import ./lib.nix {inherit lib config self;};
inherit (ookflixLib) mkServiceUser mkServiceStateDir;
inherit (lib) mkIf;
inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment;
inherit (config.ooknet.server.ookflix) groups volumes;
inherit (config.ooknet.server.ookflix.services) qbittorrent;
in {
config = mkIf qbittorrent.enable {
users = mkServiceUser qbittorrent.user.name;
systemd.tmpfiles = mkServiceStateDir "qbittorrent" qbittorrent.stateDir;
virtualisation.oci-containers.containers = {
# Torrent client
qbittorrent = {
image = "ghcr.io/hotio/qbittorrent";
dependsOn = ["gluetun"];
volumes = [
"${qbittorrent.stateDir}:/config"
"${volumes.torrents.root}:/data/torrents"
];
extraOptions = ["--network=container:gluetun"];
labels = mkContainerLabel {
name = "qbittorrent";
inherit (qbittorrent) port domain;
homepage = {
group = "downloads";
description = "torrent client";
};
};
environment =
mkContainerEnvironment qbittorrent.user.id groups.downloads.id
// {
UMASK = "002";
WEBUI_PORTS = "${toString qbittorrent.port}/tcp,${toString qbittorrent.port}/udp";
TORRENTING_PORT = "${toString qbittorrent.torrentPort}";
};
};
};
};
}

View file

@ -25,7 +25,6 @@ in {
"${radarr.stateDir}:/config" "${radarr.stateDir}:/config"
"${volumes.data.root}:/data" "${volumes.data.root}:/data"
]; ];
extraOptions = ["--network" "host"];
labels = mkContainerLabel { labels = mkContainerLabel {
name = "radarr"; name = "radarr";
inherit (radarr) port domain; inherit (radarr) port domain;
@ -34,7 +33,11 @@ in {
description = "media-server movies downloader"; description = "media-server movies downloader";
}; };
}; };
environment = mkContainerEnvironment radarr.user.id groups.media.id; environment =
mkContainerEnvironment radarr.user.id groups.media.id
// {
UMASK = "002";
};
}; };
}; };
}; };

View file

@ -7,59 +7,69 @@
inherit (config.ooknet.host) admin; inherit (config.ooknet.host) admin;
inherit (config.ooknet.server) ookflix; inherit (config.ooknet.server) ookflix;
inherit (config.ooknet.server.ookflix) volumes groups; inherit (config.ooknet.server.ookflix) volumes groups;
inherit (config.ooknet.server.ookflix.services) jellyfin plex sonarr radarr prowlarr transmission; inherit (config.ooknet.server.ookflix.services) jellyfin plex sonarr radarr prowlarr qbittorrent;
mediaDirPermissions = { dataDirPermissions = {
mode = "0775"; mode = "0775";
user = admin.name; user = admin.name;
group = groups.media.name; group = groups.media.name;
}; };
downloadDirPermissions = {
mode = "0770";
user = admin.name;
group = groups.downloads.name;
};
ifTheyExist = users: builtins.filter (user: builtins.hasAttr user config.users.users) users; ifTheyExist = users: builtins.filter (user: builtins.hasAttr user config.users.users) users;
in { in {
config = mkIf ookflix.enable { config = mkIf ookflix.enable {
users.groups = { users.groups = {
${groups.media.name} = { ${groups.media.name} = {
inherit (groups.media) name gid; inherit (groups.media) name;
gid = groups.media.id;
members = ifTheyExist [ members = ifTheyExist [
# need access to the media library
jellyfin.user.name jellyfin.user.name
plex.user.name plex.user.name
# need access to the media library and the torrent/usenet library
sonarr.user.name sonarr.user.name
radarr.user.name radarr.user.name
prowlarr.user.name prowlarr.user.name
];
}; # need access to the torrent library
${groups.downloads.name} = { qbittorrent.user.name
inherit (groups.downloads) name gid;
members = ifTheyExist [
sonarr.user.name
radarr.user.name
prowlarr.user.name
transmission.user.name
]; ];
}; };
}; };
systemd.tmpfiles.settings = { systemd.tmpfiles.settings = {
contentRoot = { ookflixDataDirs = {
"${volumes.content.root}"."d" = { /*
mode = "0775"; set up the entire directory structure it should look something like this:
user = "root"; data
group = "root"; torrents
}; movies
}; books
mediaDirectories = { tv
"${volumes.media.root}"."d" = mediaDirPermissions; usenet
"${volumes.media.tv}"."d" = mediaDirPermissions; incomplete
"${volumes.media.movies}"."d" = mediaDirPermissions; complete
}; books
downloadDirectories = { movies
"${volumes.downloads.root}"."d" = downloadDirPermissions; tv
"${volumes.downloads.complete}"."d" = downloadDirPermissions; media
"${volumes.downloads.incomplete}"."d" = downloadDirPermissions; movies
"${volumes.downloads.watch}"."d" = downloadDirPermissions; books
tv
*/
"${volumes.data.root}"."d" = dataDirPermissions;
"${volumes.torrents.root}"."d" = dataDirPermissions;
"${volumes.torrents.movies}"."d" = dataDirPermissions;
"${volumes.torrents.tv}"."d" = dataDirPermissions;
"${volumes.torrents.books}"."d" = dataDirPermissions;
"${volumes.usenet.root}"."d" = dataDirPermissions;
"${volumes.usenet.incomplete}"."d" = dataDirPermissions;
"${volumes.usenet.complete.root}"."d" = dataDirPermissions;
"${volumes.usenet.complete.movies}"."d" = dataDirPermissions;
"${volumes.usenet.complete.tv}"."d" = dataDirPermissions;
"${volumes.usenet.complete.books}"."d" = dataDirPermissions;
"${volumes.media.root}"."d" = dataDirPermissions;
"${volumes.media.movies}"."d" = dataDirPermissions;
"${volumes.media.tv}"."d" = dataDirPermissions;
"${volumes.media.books}"."d" = dataDirPermissions;
}; };
}; };
}; };

View file

@ -1,43 +0,0 @@
{
config,
lib,
ook,
self,
...
}: let
ookflixLib = import ./lib.nix {inherit lib config self;};
inherit (ookflixLib) mkServiceUser mkServiceStateDir;
inherit (lib) mkIf;
inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort;
inherit (config.ooknet.server.ookflix) groups volumes;
inherit (config.ooknet.server.ookflix.services) transmission gluetun;
in {
config = mkIf transmission.enable {
users = mkServiceUser transmission.user.name;
systemd.tmpfiles = mkServiceStateDir "transmission" transmission.stateDir;
virtualisation.oci-containers.containers = {
# Torrent client
transmission = {
image = "lscr.io/linuxserver/transmission:latest";
environmentFiles = [config.age.secrets.transmission_env.path];
environment = mkContainerEnvironment transmission.user.id groups.downloads.id;
dependsOn = ["gluetun"];
networkMode = "service:gluetun"; # Use VPN container's network
volumes = [
"${transmission.stateDir}:/config"
"${volumes.downloads.root}:/downloads"
"${volumes.downloads.watch}:/watch"
];
extraOptions = ["--network=container:gluetun"];
labels = mkContainerLabel {
name = "transmission";
inherit (transmission) port domain;
homepage = {
group = "downloads";
description = "torrent client";
};
};
};
};
};
}