main @ 142 LINES
[ HISTORY ] [ UP ]
┌─ NIX ──────────────────────────────────────────────────────────────────────┐
│ { │
│ lib, │
│ config, │
│ ... │
│ }: let │
│ inherit (lib) getExe nameValuePair mkOption mkEnableOption elem assertMsg; │
│ inherit (builtins) attrValues; │
│ inherit (lib.types) int path port str; │
│ inherit (config.ooknet) server; │
│ inherit (config.virtualisation) podman; │
│ cfg = server.ookflix; │
│ ookflixEnabled = elem "ookflix" server.services; │
│ │
│ mkSubdomainOption = name: description: example: │
│ mkOption { │
│ type = str; │
│ default = "${name}.${server.domain}"; │
│ inherit description example; │
│ }; │
│ │
│ # check config.ids for static uid/gid based on service name, if available use th │
│ at, if not, use fallback. │
│ # check fallback doesnt conflict with existing static id │
│ getId = idType: name: fallback: let │
│ allNixosIds = attrValues config.ids.${idType}; │
│ fallbackConflict = elem fallback allNixosIds; │
│ in │
│ mkOption { │
│ type = int; │
│ default = │
│ config.ids.${ │
│ idType │
│ }.${ │
│ name │
│ } │
│ or ( │
│ assert assertMsg (!fallbackConflict) │
│ "Fallback ${idType} ${toString fallback} for ${name} conflicts with NixO │
│ S static allocation"; fallback │
│ ); │
│ description = "${idType} of ${name} container"; │
│ example = 224; │
│ }; │
│ │
│ mkUserOption = name: fallback: { │
│ name = mkOption { │
│ type = str; │
│ default = name; │
│ description = "Name of ${name} container user"; │
│ example = "${name}"; │
│ }; │
│ id = getId "uids" name fallback; │
│ }; │
│ │
│ mkGroupOption = name: fallback: { │
│ name = mkOption { │
│ type = str; │
│ default = name; │
│ }; │
│ id = getId "gids" name fallback; │
│ }; │
│ │
│ mkPortOption = value: description: example: │
│ mkOption { │
│ type = port; │
│ default = value; │
│ inherit description example; │
│ }; │
│ │
│ mkVolumeOption = rootPath: pathValue: │
│ mkOption { │
│ type = path; │
│ default = │
│ if rootPath == "state" │
│ then "${cfg.volumes.state.root}/${pathValue}" │
│ else if rootPath == "data" │
│ then "${cfg.volumes.data.root}/${pathValue}" │
│ else if rootPath == "media" │
│ then "${cfg.volumes.media.root}/${pathValue}" │
│ else if rootPath == "torrents" │
│ then "${cfg.volumes.torrents.root}/${pathValue}" │
│ 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 │
│ else throw "Invalid VolumeOption rootPath: ${rootPath}. Must be one of 'st │
│ ate' 'data' 'media' 'torrents' 'usenet' 'usenet/complete' 'root'"; │
│ }; │
│ │
│ mkServiceOptions = name: {...} @ args: { │
│ enable = mkEnableOption "Enable ${name} container" // {default = ookflixEnable │
│ d;}; │
│ port = mkPortOption args.port "Port for ${name} container." 80; │
│ domain = mkSubdomainOption name "Domain for ${name} container." "${name}.mydom │
│ ain.com"; │
│ stateDir = mkVolumeOption "state" name; │
│ user = mkUserOption name args.uid; │
│ group = mkGroupOption name args.gid; │
│ }; │
│ mkBasicServiceOptions = name: {...} @ args: { │
│ enable = mkEnableOption "Enable ${name} container" // {default = ookflixEnable │
│ d;}; │
│ user = mkUserOption name args.uid; │
│ group = mkGroupOption name args.gid; │
│ }; │
│ mkServiceUser = service: { │
│ users.${service} = { │
│ isSystemUser = true; │
│ uid = cfg.services.${service}.user.id; │
│ name = service; │
│ group = service; │
│ }; │
│ groups.${service} = { │
│ gid = cfg.services.${service}.group.id; │
│ name = service; │
│ }; │
│ }; │
│ mkServiceStateDir = service: { │
│ "${cfg.services.${service}.stateDir}"."d" = { │
│ mode = "0700"; │
│ user = cfg.services.${service}.user.name; │
│ group = cfg.services.${service}.group.name; │
│ }; │
│ }; │
│ mkServiceStateFile = service: file: { │
│ "${cfg.services.${service}.stateDir}/${file}"."f" = { │
│ mode = "0600"; │
│ user = cfg.services.${service}.user.name; │
│ group = cfg.services.${service}.group.name; │
│ }; │
│ }; │
│ │
│ mkNetworkService = name: _network: │
│ nameValuePair "podman-network-${name}" { │
│ description = "Podman network ${name} for ookflix"; │
│ serviceConfig = { │
│ Type = "oneshot"; │
│ RemainsAfterExit = true; │
│ ExecStart = "${getExe podman.package} network create -d bridge ${name}"; │
│ ExecStop = "${getExe podman.package} network rm -f ${name}"; │
│ }; │
│ }; │
│ in { │
│ inherit mkServiceStateFile mkBasicServiceOptions mkServiceOptions mkServiceState │
│ Dir mkServiceUser mkUserOption mkPortOption mkGroupOption mkVolumeOption mkSubdoma │
│ inOption mkNetworkService; │
│ } │
└────────────────────────────────────────────────────────────────────────────────────┘
┌─ NIX ────────────────────────────────┐
│ { │
│ lib, │
│ config, │
│ ... │
│ }: let │
│ inherit (lib) getExe nameValuePair mkOptio │
│ n mkEnableOption elem assertMsg; │
│ inherit (builtins) attrValues; │
│ inherit (lib.types) int path port str; │
│ inherit (config.ooknet) server; │
│ inherit (config.virtualisation) podman; │
│ cfg = server.ookflix; │
│ ookflixEnabled = elem "ookflix" server.ser │
│ vices; │
│ │
│ mkSubdomainOption = name: description: exa │
│ mple: │
│ mkOption { │
│ type = str; │
│ default = "${name}.${server.domain}"; │
│ inherit description example; │
│ }; │
│ │
│ # check config.ids for static uid/gid base │
│ d on service name, if available use that, if │
│ not, use fallback. │
│ # check fallback doesnt conflict with exis │
│ ting static id │
│ getId = idType: name: fallback: let │
│ allNixosIds = attrValues config.ids.${id │
│ Type}; │
│ fallbackConflict = elem fallback allNixo │
│ sIds; │
│ in │
│ mkOption { │
│ type = int; │
│ default = │
│ config.ids.${ │
│ idType │
│ }.${ │
│ name │
│ } │
│ or ( │
│ assert assertMsg (!fallbackConflic │
│ t) │
│ "Fallback ${idType} ${toString fal │
│ lback} for ${name} conflicts with NixOS stat │
│ ic allocation"; fallback │
│ ); │
│ description = "${idType} of ${name} co │
│ ntainer"; │
│ example = 224; │
│ }; │
│ │
│ mkUserOption = name: fallback: { │
│ name = mkOption { │
│ type = str; │
│ default = name; │
│ description = "Name of ${name} contain │
│ er user"; │
│ example = "${name}"; │
│ }; │
│ id = getId "uids" name fallback; │
│ }; │
│ │
│ mkGroupOption = name: fallback: { │
│ name = mkOption { │
│ type = str; │
│ default = name; │
│ }; │
│ id = getId "gids" name fallback; │
│ }; │
│ │
│ mkPortOption = value: description: example │
│ : │
│ mkOption { │
│ type = port; │
│ default = value; │
│ inherit description example; │
│ }; │
│ │
│ mkVolumeOption = rootPath: pathValue: │
│ mkOption { │
│ type = path; │
│ default = │
│ if rootPath == "state" │
│ then "${cfg.volumes.state.root}/${pa │
│ thValue}" │
│ else if rootPath == "data" │
│ then "${cfg.volumes.data.root}/${pat │
│ hValue}" │
│ else if rootPath == "media" │
│ then "${cfg.volumes.media.root}/${pa │
│ thValue}" │
│ else if rootPath == "torrents" │
│ then "${cfg.volumes.torrents.root}/$ │
│ {pathValue}" │
│ else if rootPath == "usenet" │
│ then "${cfg.volumes.usenet.root}/${p │
│ athValue}" │
│ else if rootPath == "usenet/complete │
│ " │
│ then "${cfg.volumes.usenet.complete. │
│ root}/${pathValue}" │
│ else if rootPath == "root" │
│ then pathValue │
│ else throw "Invalid VolumeOption roo │
│ tPath: ${rootPath}. Must be one of 'state' ' │
│ data' 'media' 'torrents' 'usenet' 'usenet/co │
│ mplete' 'root'"; │
│ }; │
│ │
│ mkServiceOptions = name: {...} @ args: { │
│ enable = mkEnableOption "Enable ${name} │
│ container" // {default = ookflixEnabled;}; │
│ port = mkPortOption args.port "Port for │
│ ${name} container." 80; │
│ domain = mkSubdomainOption name "Domain │
│ for ${name} container." "${name}.mydomain.co │
│ m"; │
│ stateDir = mkVolumeOption "state" name; │
│ user = mkUserOption name args.uid; │
│ group = mkGroupOption name args.gid; │
│ }; │
│ mkBasicServiceOptions = name: {...} @ args │
│ : { │
│ enable = mkEnableOption "Enable ${name} │
│ container" // {default = ookflixEnabled;}; │
│ user = mkUserOption name args.uid; │
│ group = mkGroupOption name args.gid; │
│ }; │
│ mkServiceUser = service: { │
│ users.${service} = { │
│ isSystemUser = true; │
│ uid = cfg.services.${service}.user.id; │
│ name = service; │
│ group = service; │
│ }; │
│ groups.${service} = { │
│ gid = cfg.services.${service}.group.id │
│ ; │
│ name = service; │
│ }; │
│ }; │
│ mkServiceStateDir = service: { │
│ "${cfg.services.${service}.stateDir}"."d │
│ " = { │
│ mode = "0700"; │
│ user = cfg.services.${service}.user.na │
│ me; │
│ group = cfg.services.${service}.group. │
│ name; │
│ }; │
│ }; │
│ mkServiceStateFile = service: file: { │
│ "${cfg.services.${service}.stateDir}/${f │
│ ile}"."f" = { │
│ mode = "0600"; │
│ user = cfg.services.${service}.user.na │
│ me; │
│ group = cfg.services.${service}.group. │
│ name; │
│ }; │
│ }; │
│ │
│ mkNetworkService = name: _network: │
│ nameValuePair "podman-network-${name}" { │
│ description = "Podman network ${name} │
│ for ookflix"; │
│ serviceConfig = { │
│ Type = "oneshot"; │
│ RemainsAfterExit = true; │
│ ExecStart = "${getExe podman.package │
│ } network create -d bridge ${name}"; │
│ ExecStop = "${getExe podman.package} │
│ network rm -f ${name}"; │
│ }; │
│ }; │
│ in { │
│ inherit mkServiceStateFile mkBasicServiceO │
│ ptions mkServiceOptions mkServiceStateDir mk │
│ ServiceUser mkUserOption mkPortOption mkGrou │
│ pOption mkVolumeOption mkSubdomainOption mkN │
│ etworkService; │
│ } │
└──────────────────────────────────────────────┘
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET