ookflix: add containers

This commit is contained in:
ooks-io 2024-12-02 12:30:30 +11:00
parent 4ee2e2a877
commit 79a37fa8eb
13 changed files with 303 additions and 68 deletions

View file

@ -9,6 +9,14 @@ in {
imports = [
./jellyfin.nix
./plex.nix
./jellyseer.nix
./tautulli.nix
./sonarr.nix
./prowlarr.nix
./gluetun.nix
./transmission.nix
./shared.nix
./options.nix
];
@ -18,6 +26,8 @@ in {
services = {
jellyfin.enable = true;
plex.enable = true;
jellyseer.enable = true;
tautulli.enable = true;
};
};
};

View file

@ -2,9 +2,10 @@
config,
lib,
ook,
self,
...
}: let
ookflixLib = import ./lib.nix {inherit lib config;};
ookflixLib = import ./lib.nix {inherit lib config self;};
inherit (ookflixLib) mkServiceStateDir mkServiceUser;
inherit (lib) mkIf optionalAttrs;
inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort;
@ -22,10 +23,9 @@ in {
image = "lscr.io/linuxserver/jellyfin:latest";
autoStart = true;
hostname = "jellyfin";
ports = [(mkContainerPort jellyfin.port)];
ports = ["${jellyfin.port}:${jellyfin.port}"];
volumes = [
"${volumes.media.movies}:/data/movies"
"${volumes.media.tv}:/data/tv"
"${volumes.media.root}:/data"
"${jellyfin.stateDir}:/config"
];
labels = mkContainerLabel {

View file

@ -6,27 +6,29 @@
}: let
inherit (lib) mkIf;
inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort;
inherit (config.ooknet.server.ookflix) storage groups;
inherit (config.ooknet.server.ookflix) groups;
inherit (config.ooknet.server.ookflix.services) jellyseer;
in {
config = mkIf jellyseer.enable {
# media requesting for jellyfin
jellyseer = {
image = "fallenbagel/jellyseerr:latest";
autoStart = true;
hostname = "jellyseer";
ports = [(mkContainerPort jellyseer.port)];
volumes = ["${storage.state.jellyseer}:/config"];
extraOptions = ["--network" "host"];
labels = mkContainerLabel {
name = "jellyseer";
inherit (jellyseer) domain port;
homepage = {
group = "media";
description = "media-server requesting";
virtualisation.oci-containers.containers = {
jellyseer = {
image = "fallenbagel/jellyseerr:latest";
autoStart = true;
hostname = "jellyseer";
ports = [(mkContainerPort jellyseer.port)];
volumes = ["${jellyseer.stateDir}:/config"];
extraOptions = ["--network" "host"];
labels = mkContainerLabel {
name = "jellyseer";
inherit (jellyseer) domain port;
homepage = {
group = "media";
description = "media-server requesting";
};
};
environment = mkContainerEnvironment jellyseer.user.id groups.media.id;
};
environment = mkContainerEnvironment jellyseer.user.id groups.media.id;
};
};
}

View file

@ -1,6 +1,7 @@
{
lib,
config,
self,
...
}: let
inherit (lib) mkOption mkEnableOption elem assertMsg;
@ -87,6 +88,15 @@
user = mkUserOption name args.uid;
group = mkGroupOption name args.gid;
};
mkBasicServiceOptions = name: {
gid,
uid,
...
} @ args: {
enable = mkEnableOption "Enable ${name} container";
user = mkUserOption name args.uid;
group = mkGroupOption name args.gid;
};
mkServiceUser = service: {
users.${service} = {
isSystemUser = true;
@ -106,6 +116,13 @@
group = cfg.services.${service}.group.name;
};
};
mkServiceSecret = name: service: {
${name} = {
file = "${self}/secrets/container/${name}.age";
owner = cfg.services.${service}.user.name;
group = cfg.services.${service}.group.name;
};
};
in {
inherit mkServiceOptions mkServiceStateDir mkServiceUser mkUserOption mkPortOption mkGroupOption mkVolumeOption mkSubdomainOption;
inherit mkServiceSecret mkBasicServiceOptions mkServiceOptions mkServiceStateDir mkServiceUser mkUserOption mkPortOption mkGroupOption mkVolumeOption mkSubdomainOption;
}

View file

@ -1,11 +1,12 @@
{
lib,
config,
self,
...
}: let
ookflixLib = import ./lib.nix {inherit lib config;};
ookflixLib = import ./lib.nix {inherit lib config self;};
inherit (ookflixLib) mkVolumeOption mkGroupOption mkServiceOptions;
inherit (ookflixLib) mkVolumeOption mkGroupOption mkServiceOptions mkBasicServiceOptions;
inherit (lib) mkOption mkEnableOption;
inherit (lib.types) enum;
inherit (config.ooknet) server;
@ -26,24 +27,25 @@ in {
};
volumes = {
state.root = mkVolumeOption "root" "/var/lib/ookflix";
content.root = mkVolumeOption "root" "/jellyfin";
data.root = mkVolumeOption "root" "/jellyfin";
downloads = {
root = mkVolumeOption "${cfg.content.root}/downloads";
incomplete = mkVolumeOption "downloads" "incomplete";
complete = mkVolumeOption "downloads" "complete";
watch = mkVolumeOption "downloads" "watch";
tv = mkVolumeOption "downloads" "tv";
movies = mkVolumeOption "downloads" "movies";
books = mkVolumeOption "downloads" "books";
};
media = {
root = mkVolumeOption "root" "${cfg.volumes.content.root}/media";
movies = mkVolumeOption "media" "movies";
tv = mkVolumeOption "media" "tv";
books = mkVolumeOption "media" "books";
};
};
# Shared groups
groups = {
media = mkGroupOption "media" 992;
downloader = mkGroupOption "downloader" 981;
downloads = mkGroupOption "downloader" 981;
};
services = {
@ -87,6 +89,10 @@ in {
uid = 355;
gid = 355;
};
gluetun = mkBasicServiceOptions "gluetun" {
uid = 356;
gid = 357;
};
};
};
}

View file

@ -2,9 +2,10 @@
config,
lib,
ook,
self,
...
}: let
ookflixLib = import ./lib.nix {inherit lib config;};
ookflixLib = import ./lib.nix {inherit lib config self;};
inherit (ookflixLib) mkServiceUser mkServiceStateDir;
inherit (lib) mkIf optionalAttrs;
inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort;

View file

@ -0,0 +1,42 @@
{
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;
inherit (config.ooknet.server.ookflix.services) prowlarr;
in {
config = mkIf prowlarr.enable {
users = mkServiceUser prowlarr.user.name;
systemd.tmpfiles = mkServiceStateDir "prowlarr" prowlarr.stateDir;
virtualisation.oci-containers.containers = {
prowlarr = {
image = "lscr.io/linuxserver/prowlarr:latest";
autoStart = true;
hostname = "prowlarr";
ports = [(mkContainerPort prowlarr.port)];
volumes = ["${prowlarr.stateDir}:/config"];
extraOptions = ["--network" "host"];
labels = mkContainerLabel {
name = "prowlarr";
inherit (prowlarr) port domain;
homepage = {
group = "arr";
description = "media-server indexer";
};
};
environment =
mkContainerEnvironment prowlarr.user.id groups.media.id
// {
UMASK = "002";
};
};
};
};
}

View file

@ -0,0 +1,41 @@
{
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) radarr;
in {
config = mkIf radarr.enable {
users = mkServiceUser radarr.user.name;
systemd.tmpfiles = mkServiceStateDir "radarr" radarr.stateDir;
virtualisation.oci-containers.containers = {
radarr = {
image = "ghcr.io/hotio/qbittorrent";
autoStart = true;
hostname = "radarr";
ports = ["${radarr.port}:${radarr.port}"];
volumes = [
"${radarr.stateDir}:/config"
"${volumes.data.root}:/data"
];
extraOptions = ["--network" "host"];
labels = mkContainerLabel {
name = "radarr";
inherit (radarr) port domain;
homepage = {
group = "arr";
description = "media-server movies downloader";
};
};
environment = mkContainerEnvironment radarr.user.id groups.media.id;
};
};
};
}

View file

@ -0,0 +1,66 @@
{
lib,
config,
...
}: let
inherit (lib) mkIf;
inherit (config.ooknet.host) admin;
inherit (config.ooknet.server) ookflix;
inherit (config.ooknet.server.ookflix) volumes groups;
inherit (config.ooknet.server.ookflix.services) jellyfin plex sonarr radarr prowlarr transmission;
mediaDirPermissions = {
mode = "0775";
user = admin.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;
in {
config = mkIf ookflix.enable {
users.groups = {
${groups.media.name} = {
inherit (groups.media) name gid;
members = ifTheyExist [
jellyfin.user.name
plex.user.name
sonarr.user.name
radarr.user.name
prowlarr.user.name
];
};
${groups.downloads.name} = {
inherit (groups.downloads) name gid;
members = ifTheyExist [
sonarr.user.name
radarr.user.name
prowlarr.user.name
transmission.user.name
];
};
};
systemd.tmpfiles.settings = {
contentRoot = {
"${volumes.content.root}"."d" = {
mode = "0775";
user = "root";
group = "root";
};
};
mediaDirectories = {
"${volumes.media.root}"."d" = mediaDirPermissions;
"${volumes.media.tv}"."d" = mediaDirPermissions;
"${volumes.media.movies}"."d" = mediaDirPermissions;
};
downloadDirectories = {
"${volumes.downloads.root}"."d" = downloadDirPermissions;
"${volumes.downloads.complete}"."d" = downloadDirPermissions;
"${volumes.downloads.incomplete}"."d" = downloadDirPermissions;
"${volumes.downloads.watch}"."d" = downloadDirPermissions;
};
};
};
}

View file

@ -0,0 +1,44 @@
{
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) sonarr;
in {
config = mkIf sonarr.enable {
users = mkServiceUser sonarr.user.name;
systemd.tmpfiles = mkServiceStateDir "sonarr" sonarr.stateDir;
virtualisation.oci-containers.containers = {
sonarr = {
image = "ghcr.io/hotio/sonarr";
autoStart = true;
hostname = "sonarr";
ports = [(mkContainerPort sonarr.port)];
volumes = [
"${sonarr.stateDir}:/config"
"${volumes.data.root}:/data"
];
labels = mkContainerLabel {
name = "sonarr";
inherit (sonarr) port domain;
homepage = {
group = "arr";
description = "media-server tv downloader";
};
};
environment =
mkContainerEnvironment sonarr.user.id groups.media.id
// {
UMASK = "002";
};
};
};
};
}

View file

@ -2,14 +2,15 @@
config,
lib,
ook,
self,
...
}: let
ookflixLib = import ./lib.nix {inherit lib config;};
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;
inherit (config.ooknet.server.services) tautulli;
inherit (config.ooknet.server.ookflix.services) tautulli;
in {
config = mkIf tautulli.enable {
users = mkServiceUser tautulli.user.name;

View file

@ -0,0 +1,43 @@
{
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";
};
};
};
};
};
}

View file

@ -1,38 +0,0 @@
{
lib,
config,
...
}: let
inherit (lib) mkIf mkMerge;
inherit (builtins) mapAttrs;
inherit (config.ooknet.server) ookflix;
inherit (config.ooknet.server.ookflix) services storage users groups;
mkServiceUser = name: user: {
isSystemUser = true;
group = groups.${name}.name;
uid = users.${name}.id;
home = storage.state.${name};
};
generateUsers = mapAttrs mkServiceUser users;
in {
config = mkIf ookflix.enable {
users = {
users = mkMerge [
# media service users
(mkIf services.jellyfin.enable {
${users.jellyfin.name} = mkServiceUser users.jellyfin.name groups.media.name;
})
(mkIf services.plex.enable {
${users.plex.name} = mkServiceUser users.plex.name groups.media.name;
})
(mkIf (services.jellyfin.enable || services.jellyseer.enable) {
${users.jellyseer.name} = mkServiceUser users.jellyseer.name groups.media.name;
})
];
groups = {
};
};
};
}