refactor!: I went too close into the sun

Simlified everything, things were getting out of control
This commit is contained in:
Gustavo "Guz" L. de Mello
2024-04-08 16:37:29 -03:00
parent 0cf8524902
commit 5ce99497d7
87 changed files with 3726 additions and 2415 deletions

View File

@@ -1,15 +1,17 @@
{ config, lib, ... }:
let
cfg = config.server.adguard;
in
{
imports = [ ];
options.server.adguard = with lib; with lib.types; {
config,
lib,
...
}: let
cfg = config.server.adguard;
in {
imports = [];
options.server.adguard = with lib;
with lib.types; {
enable = mkEnableOption "";
extraArgs = mkOption {
type = listOf str;
default = [ ];
default = [];
};
domain = mkOption {
type = str;
@@ -34,10 +36,10 @@ in
};
dns.rewrites = mkOption {
type = attrsOf str;
default = { };
default = {};
};
dns.filters = mkOption {
type = attrsOf (submodule ({ lib, ... }: {
type = attrsOf (submodule ({lib, ...}: {
options = {
name = mkOption {
type = nullOr str;
@@ -52,14 +54,14 @@ in
};
};
}));
default = { };
default = {};
};
};
};
config = lib.mkIf cfg.enable {
networking.firewall = {
allowedTCPPorts = [ 53 ];
allowedUDPPorts = [ 53 51820 ];
allowedTCPPorts = [53];
allowedUDPPorts = [53 51820];
};
services.adguardhome = with builtins; {
enable = true;
@@ -69,22 +71,24 @@ in
http = {
address = "${cfg.settings.server.address}:${toString cfg.settings.server.port}";
};
dns.rewrites = (builtins.attrValues (builtins.mapAttrs
dns.rewrites = builtins.attrValues (builtins.mapAttrs
(from: to: {
domain = from;
answer = to;
})
cfg.settings.dns.rewrites));
filters = (attrValues (mapAttrs
cfg.settings.dns.rewrites);
filters = attrValues (mapAttrs
(id: list: {
name = if isNull list.name then id else list.name;
name =
if isNull list.name
then id
else list.name;
ID = id;
url = list.url;
enabled = list.enabled;
})
cfg.settings.dns.filters));
cfg.settings.dns.filters);
};
};
};
}

View File

@@ -1,15 +1,21 @@
{ config, lib, ... }:
let
cfg = config.server.caddy;
in
{
imports = [ ];
options.server.caddy = with lib; with lib.types; {
config,
lib,
...
}: let
cfg = config.server.caddy;
in {
imports = [];
options.server.caddy = with lib;
with lib.types; {
enable = mkEnableOption "";
settings = {
virtualHosts = mkOption {
type = attrsOf (submodule ({ config, lib, ... }: {
type = attrsOf (submodule ({
config,
lib,
...
}: {
options = {
extraConfig = mkOption {
type = lines;
@@ -17,7 +23,7 @@ in
};
};
}));
default = { };
default = {};
};
};
};

View File

@@ -1,6 +1,9 @@
{ config, lib, pkgs, ... }:
let
{
config,
lib,
pkgs,
...
}: let
cfg = config.server;
server = pkgs.writeShellScriptBin "server" ''
gum="${pkgs.gum}/bin/gum";
@@ -13,15 +16,23 @@ let
sudo nixos-rebuild switch --flake "$flakeDir" "$@"
fi
${if cfg.forgejo.cliAlias then ''
if [[ "$command" == "forgejo" ]]; then
shift 1;
sudo --user=${cfg.forgejo.user} ${cfg.forgejo.package}/bin/gitea --work-path ${cfg.forgejo.data.root} "$@"
fi
'' else ""}
${
if cfg.forgejo.cliAlias
then ''
if [[ "$command" == "forgejo" ]]; then
shift 1;
sudo --user=${cfg.forgejo.user} ${cfg.forgejo.package}/bin/gitea --work-path ${cfg.forgejo.data.root} "$@"
fi
if [[ "$command" == "forgejo-act" ]]; then
shift 1;
sudo --user=${cfg.forgejo.user} ${cfg.forgejo.actions.package}/bin/act_runner --config /var/lib/gitea-runner/${cfg.forgejo.actions.instanceName} "$@"
fi
''
else ""
}
'';
in
{
in {
imports = [
./adguard.nix
./caddy.nix
@@ -33,7 +44,8 @@ in
./photoprism.nix
./tailscale.nix
];
options.server = with lib; with lib.types; {
options.server = with lib;
with lib.types; {
enable = mkEnableOption "";
name = mkOption {
type = str;
@@ -68,42 +80,45 @@ in
server
];
networking.firewall.allowedTCPPorts = lib.mkIf cfg.handleDomains [ 80 433 ];
networking.firewall.allowedTCPPorts = lib.mkIf cfg.handleDomains [80 433];
systemd.services."tailscaled" = lib.mkIf cfg.handleDomains {
serviceConfig = {
Environment = [ "TS_PERMIT_CERT_UID=caddy" ];
Environment = ["TS_PERMIT_CERT_UID=caddy"];
};
};
server = with lib; mkIf cfg.handleDomains {
adguard = {
enable = true;
settings.dns.rewrites = (if hasPrefix "*." cfg.domain then {
"${cfg.domain}" = cfg.ip;
} else {
"${cfg.domain}" = cfg.ip;
"${"*." + cfg.domain}" = cfg.ip;
});
};
caddy =
let
homelabServices = (lib.filterAttrs (n: v: builtins.isAttrs v && v?domain) cfg);
in
with lib;
mkIf cfg.handleDomains {
server = with lib;
mkIf cfg.handleDomains {
adguard = {
enable = true;
settings.virtualHosts = mapAttrs'
(name: value: nameValuePair (value.domain) ({
extraConfig = ''
reverse_proxy ${cfg.localIp}:${toString value.port}
'';
}))
homelabServices;
settings.dns.rewrites =
if hasPrefix "*." cfg.domain
then {
"${cfg.domain}" = cfg.ip;
}
else {
"${cfg.domain}" = cfg.ip;
"${"*." + cfg.domain}" = cfg.ip;
};
};
};
caddy = let
homelabServices = lib.filterAttrs (n: v: builtins.isAttrs v && v ? domain) cfg;
in
with lib;
mkIf cfg.handleDomains {
enable = true;
settings.virtualHosts =
mapAttrs'
(name: value:
nameValuePair (value.domain) {
extraConfig = ''
reverse_proxy ${cfg.localIp}:${toString value.port}
'';
})
homelabServices;
};
};
};
}

View File

@@ -1,24 +1,67 @@
{ config, lib, pkgs, ... }:
let
{
config,
lib,
pkgs,
utils,
...
}: let
cfg = config.server.forgejo;
users = (builtins.attrValues (builtins.mapAttrs
users = builtins.attrValues (builtins.mapAttrs
(username: info: {
name = if isNull info.name then username else info.name;
name =
if isNull info.name
then username
else info.name;
email = info.email;
password = info.password;
admin = info.admin;
})
cfg.settings.users));
in
{
imports = [ ];
options.server.forgejo = with lib; with lib.types; {
cfg.settings.users);
settingsFormat = pkgs.formats.yaml {};
in {
imports = [];
options.server.forgejo = with lib;
with lib.types; {
enable = mkEnableOption "";
user = mkOption {
type = str;
default = "git";
};
actions.enable = mkOption {
type = bool;
default = false;
};
actions.runnerToken = mkOption {
type = str;
};
actions.package = mkOption {
type = package;
default = pkgs.forgejo-actions-runner;
};
actions.instanceUrl = mkOption {
type = str;
default = "https://${cfg.domain}";
};
actions.url = mkOption {
type = str;
default = "http://localhost:${toString cfg.port}";
};
actions.instanceName = mkOption {
type = str;
default = "${cfg.user}Forgejo${toString cfg.port}";
};
actions.settings = mkOption {
type = submodule {
freeformType = settingsFormat.type;
options = {
runner.insecure = mkOption {
type = bool;
default = true;
};
};
};
default = {};
};
package = mkOption {
type = package;
default = pkgs.forgejo;
@@ -47,25 +90,31 @@ in
};
settings = {
users = mkOption {
type = attrsOf (submodule ({ config, lib, ... }: with lib; with lib.types; {
options = {
name = mkOption {
type = nullOr (either str path);
default = null;
type = attrsOf (submodule ({
config,
lib,
...
}:
with lib;
with lib.types; {
options = {
name = mkOption {
type = nullOr (either str path);
default = null;
};
password = mkOption {
type = either str path;
};
email = mkOption {
type = either str path;
};
admin = mkOption {
type = bool;
default = false;
};
};
password = mkOption {
type = either str path;
};
email = mkOption {
type = either str path;
};
admin = mkOption {
type = bool;
default = false;
};
};
}));
default = { };
}));
default = {};
};
name = mkOption {
type = str;
@@ -103,7 +152,7 @@ in
"repo.packages"
"repo.actions"
]);
default = [ ];
default = [];
};
repo.pushCreate = mkOption {
type = bool;
@@ -115,11 +164,11 @@ in
};
cors.domains = mkOption {
type = listOf str;
default = [ ];
default = [];
};
cors.methods = mkOption {
type = listOf str;
default = [ ];
default = [];
};
ui.defaultTheme = mkOption {
type = str;
@@ -137,7 +186,7 @@ in
];
};
server.protocol = mkOption {
type = enum [ "http" "https" "fcgi" "http+unix" "fcgi+unix" ];
type = enum ["http" "https" "fcgi" "http+unix" "fcgi+unix"];
default = "http";
};
server.domain = mkOption {
@@ -150,7 +199,10 @@ in
};
server.address = mkOption {
type = either str path;
default = if hasSuffix "+unix" cfg.settings.server.protocol then "/run/forgejo/forgejo.sock" else "0.0.0.0";
default =
if hasSuffix "+unix" cfg.settings.server.protocol
then "/run/forgejo/forgejo.sock"
else "0.0.0.0";
};
server.url = mkOption {
type = str;
@@ -165,7 +217,7 @@ in
default = false;
};
server.landingPage = mkOption {
type = enum [ "home" "explore" "organizations" "login" str ];
type = enum ["home" "explore" "organizations" "login" str];
default = "home";
};
service.registration = mkOption {
@@ -178,134 +230,190 @@ in
};
};
};
config = lib.mkIf cfg.enable {
users.users."${cfg.user}" = {
home = cfg.data.root;
useDefaultShell = true;
group = cfg.user;
isSystemUser = true;
initialPassword = "1313";
};
users.groups."${cfg.user}" = { };
config = let
inherit (utils) escapeSystemdPath;
in
with lib;
mkIf cfg.enable {
users.users."${cfg.user}" = {
home = cfg.data.root;
useDefaultShell = true;
group = cfg.user;
isSystemUser = true;
initialPassword = "1313";
};
users.groups."${cfg.user}" = {};
services.forgejo = {
enable = true;
package = cfg.package;
user = cfg.user;
group = cfg.user;
stateDir = toString cfg.data.root;
useWizard = false;
database = {
user = cfg.user;
type = "sqlite3";
};
settings = with builtins; {
DEFAULT = {
APP_NAME = cfg.settings.name;
RUN_MODE = if cfg.settings.prod then "prod" else "dev";
virtualisation.docker.enable = cfg.actions.enable;
services.gitea-actions-runner.instances."${cfg.actions.instanceName}" = mkIf cfg.actions.enable {
enable = true;
name = cfg.actions.instanceName;
url = cfg.actions.instanceUrl;
token = cfg.actions.runnerToken;
settings = cfg.actions.settings;
labels = [
"host:host"
"shell:host://-self-hosted"
"debian-latest:docker://node:18-bullseye"
"ubuntu-latest:docker://node:18-bullseye"
"debian-slim:docker://node:18-bullseye-slim"
"ubuntu-slim:docker://node:18-bullseye-slim"
"alpine-latest:docker://alpine:latest"
];
};
repository = {
DISABLED_REPO_UNITS = concatStringsSep "," cfg.settings.repo.disabledUnits;
DEFAULT_REPO_UNITS = concatStringsSep "," cfg.settings.repo.defaultUnits;
ENABLE_PUSH_CREATE_USER = cfg.settings.repo.pushCreate;
ENABLE_PUSH_CREATE_ORG = cfg.settings.repo.pushCreate;
};
cors = {
ENABLED = cfg.settings.cors.enable;
ALLOW_DOMAIN = concatStringsSep "," cfg.settings.cors.domains;
METHODS = concatStringsSep "," cfg.settings.cors.methods;
};
ui = {
DEFAULT_THEME = cfg.settings.ui.defaultTheme;
THEMES = concatStringsSep "," cfg.settings.ui.themes;
};
server = {
PROTOCOL = cfg.settings.server.protocol;
DOMAIN = cfg.settings.server.domain;
ROOT_URL = cfg.settings.server.url;
HTTP_ADDR = cfg.settings.server.address;
HTTP_PORT = cfg.settings.server.port;
OFFLINE_MODE = cfg.settings.server.offline;
ENABLE_GZIP = cfg.settings.server.compression;
LANDING_PAGE = cfg.settings.server.landingPage;
};
security = {
ONLY_ALLOW_PUSH_IF_GITEA_ENVIRONMENT_SET = if cfg.settings.security.allowBypassGiteaEnv then false else true;
};
service = {
DISABLE_REGISTRATION = if cfg.settings.service.registration then false else true;
};
};
};
systemd.services."homelab-forgejo-setup" = with builtins; {
script = ''
configFile="${toString cfg.data.root}/custom/conf/app.ini";
touch $configFile
services.gitea-actions-runner.package = cfg.actions.package;
systemd.services."${escapeSystemdPath cfg.actions.instanceName}".serviceConfig.User = cfg.user;
gum="${pkgs.gum}/bin/gum"
forgejo="${cfg.package}/bin/gitea --config $configFile"
user="$forgejo admin user"
awk="${pkgs.gawk}/bin/awk"
services.forgejo = {
enable = true;
package = cfg.package;
user = cfg.user;
group = cfg.user;
stateDir = toString cfg.data.root;
useWizard = false;
database = {
user = cfg.user;
type = "sqlite3";
};
settings = with builtins; {
actions = mkIf cfg.actions.enable {
ENABLED = true;
DEFAULT_ACTIONS_URL = cfg.actions.url;
};
DEFAULT = {
APP_NAME = cfg.settings.name;
RUN_MODE =
if cfg.settings.prod
then "prod"
else "dev";
};
repository = {
DISABLED_REPO_UNITS = concatStringsSep "," cfg.settings.repo.disabledUnits;
DEFAULT_REPO_UNITS = concatStringsSep "," cfg.settings.repo.defaultUnits;
ENABLE_PUSH_CREATE_USER = cfg.settings.repo.pushCreate;
ENABLE_PUSH_CREATE_ORG = cfg.settings.repo.pushCreate;
};
cors = {
ENABLED = cfg.settings.cors.enable;
ALLOW_DOMAIN = concatStringsSep "," cfg.settings.cors.domains;
METHODS = concatStringsSep "," cfg.settings.cors.methods;
};
ui = {
DEFAULT_THEME = cfg.settings.ui.defaultTheme;
THEMES = concatStringsSep "," cfg.settings.ui.themes;
};
server = {
PROTOCOL = cfg.settings.server.protocol;
DOMAIN = cfg.settings.server.domain;
ROOT_URL = cfg.settings.server.url;
HTTP_ADDR = cfg.settings.server.address;
HTTP_PORT = cfg.settings.server.port;
OFFLINE_MODE = cfg.settings.server.offline;
ENABLE_GZIP = cfg.settings.server.compression;
LANDING_PAGE = cfg.settings.server.landingPage;
};
security = {
ONLY_ALLOW_PUSH_IF_GITEA_ENVIRONMENT_SET =
if cfg.settings.security.allowBypassGiteaEnv
then false
else true;
};
service = {
DISABLE_REGISTRATION =
if cfg.settings.service.registration
then false
else true;
};
};
};
systemd.services."homelab-forgejo-setup" = with builtins; {
script = ''
declaredUsers=(${toString (map (user: "${if isPath user.name then "$(cat ${toString user.name})" else user.name}") users)});
configFile="${toString cfg.data.root}/custom/conf/app.ini";
touch $configFile
$gum log --structured --time timeonly --level info "HANDLING UNDECLARED USERS"
$user list | $awk '{print $2}' | tail -n +2 | while read username; do
if printf '%s\0' "''${declaredUsers[@]}" | grep -Fxqz -- "$username"; then
$gum log --structured --time timeonly --level warn "Declared user already exists, ignoring" username $username;
else
if [[ "$($user list | tail -n +2 | $awk '{print $2 " " $5}' | grep "$username " | $awk '{print $2}')" == "true" ]]; then
$gum log --structured --time timeonly --level warn "Undeclared user is a ADMIN, ignoring" username $username;
else
${if cfg.handleUndeclaredUsers then ''
gum="${pkgs.gum}/bin/gum"
forgejo="${cfg.package}/bin/gitea --config $configFile"
user="$forgejo admin user"
awk="${pkgs.gawk}/bin/awk"
declaredUsers=(${toString (map (user: "${
if isPath user.name
then "$(cat ${toString user.name})"
else user.name
}")
users)});
$gum log --structured --time timeonly --level info "HANDLING UNDECLARED USERS"
$user list | $awk '{print $2}' | tail -n +2 | while read username; do
if printf '%s\0' "''${declaredUsers[@]}" | grep -Fxqz -- "$username"; then
$gum log --structured --time timeonly --level warn "Declared user already exists, ignoring" username $username;
else
if [[ "$($user list | tail -n +2 | $awk '{print $2 " " $5}' | grep "$username " | $awk '{print $2}')" == "true" ]]; then
$gum log --structured --time timeonly --level warn "Undeclared user is a ADMIN, ignoring" username $username;
else
${
if cfg.handleUndeclaredUsers
then ''
$gum log --structured --time timeonly --level warn "DELETING undeclared user" username $username;
$user delete -u "$username";
'' else ''
''
else ''
$gum log --structured --time timeonly --level warn "UNDECLARED user, please declare it in the config so it's reproducible" username "$username";
''}
fi
fi
done
''
}
fi
fi
done
${toString (map (user: ''
username="${if isPath user.name then "\"$(cat ${toString user.name})\"" else user.name}";
email="${if isPath user.email then "\"$(cat ${toString user.email})\"" else user.email}";
password="${if isPath user.password then "\"$(cat ${toString user.password})\"" else user.password}";
${toString (map (user: ''
username="${
if isPath user.name
then "\"$(cat ${toString user.name})\""
else user.name
}";
email="${
if isPath user.email
then "\"$(cat ${toString user.email})\""
else user.email
}";
password="${
if isPath user.password
then "\"$(cat ${toString user.password})\""
else user.password
}";
if [[ "$($user list | grep "$username" | $awk '{print $2}')" ]]; then
$gum log --structured --time timeonly --level warn "User with username already exists" username $username;
if [[ "$($user list | grep "$username" | $awk '{print $2}')" ]]; then
$gum log --structured --time timeonly --level warn "User with username already exists" username $username;
elif [[ "$($user list | grep "$email" | $awk '{print $3}')" ]]; then
$gum log --structured --time timeonly --level warn "User with email already exists" email $email;
elif [[ "$($user list | grep "$email" | $awk '{print $3}')" ]]; then
$gum log --structured --time timeonly --level warn "User with email already exists" email $email;
else
$gum log --structured --time timeonly --level info ${if user.admin then "Creating ADMIN user" else "Creating user"} username $username email $email password $password;
$user create --username $username --email $email --password $password ${if user.admin then "--admin" else ""};
else
$gum log --structured --time timeonly --level info ${
if user.admin
then "Creating ADMIN user"
else "Creating user"
} username $username email $email password $password;
$user create --username $username --email $email --password $password ${
if user.admin
then "--admin"
else ""
};
fi
'') users)}
'';
wantedBy = [ "multi-user.target" ];
after = [ "forgejo.service" ];
serviceConfig = {
Type = "oneshot";
User = cfg.user;
Group = cfg.user;
fi
'')
users)}
'';
wantedBy = ["multi-user.target"];
after = ["forgejo.service"];
serviceConfig = {
Type = "oneshot";
User = cfg.user;
Group = cfg.user;
};
};
};
};
};
}

View File

@@ -1,6 +1,9 @@
{ config, lib, pkgs, ... }:
let
{
config,
lib,
pkgs,
...
}: let
cfg = config.server.jellyfin;
networkConfig = pkgs.writeTextFile {
name = "network.json";
@@ -14,12 +17,12 @@ let
name = "encoding.json";
text = builtins.toJSON cfg.settings.system;
};
in
{
in {
imports = [
./jellyseerr.nix
];
options.server.jellyfin = with lib; with lib.types; {
options.server.jellyfin = with lib;
with lib.types; {
enable = mkEnableOption "";
user = mkOption {
type = str;
@@ -49,8 +52,8 @@ in
};
settings = {
network = mkOption {
type = (submodule {
freeformType = (pkgs.formats.json { }).type;
type = submodule {
freeformType = (pkgs.formats.json {}).type;
options = {
AutoDiscovery = mkOption {
type = bool;
@@ -185,149 +188,148 @@ in
default = "vEthernet*";
};
};
});
default = { };
};
default = {};
};
encoding = mkOption {
type =
(submodule {
freeformType = (pkgs.formats.json { }).type;
options = {
AllowOnDemandMetadataBasedKeyframeExtractionForExtensions.string = mkOption {
type = listOf str;
default = [ "mkv" ];
};
DeinterlaceDoubleRate = mkOption {
type = bool;
default = false;
};
DeinterlaceMethod = mkOption {
type = str;
default = "yadif";
};
DownMixAudioBoost = mkOption {
type = int;
default = 2;
};
EnableDecodingColorDepth10Hevc = mkOption {
type = bool;
default = true;
};
EnableDecodingColorDepth10Vp9 = mkOption {
type = bool;
default = true;
};
EnableEnhancedNvdecDecoder = mkOption {
type = bool;
default = true;
};
EnableFallbackFont = mkOption {
type = bool;
default = false;
};
EnableHardwareEncoding = mkOption {
type = bool;
default = true;
};
EnableIntelLowPowerH264HwEncoder = mkOption {
type = bool;
default = false;
};
EnableIntelLowPowerHevcHwEncoder = mkOption {
type = bool;
default = false;
};
EnableSubtitleExtraction = mkOption {
type = bool;
default = true;
};
EnableThrottling = mkOption {
type = bool;
default = false;
};
EnableTonemapping = mkOption {
type = bool;
default = false;
};
EnableVppTonemapping = mkOption {
type = bool;
default = false;
};
EncoderAppPathDisplay = mkOption {
type = either path str;
default = "${pkgs.jellyfin-ffmpeg}/bin/ffmpeg";
};
EncodingThreadCount = mkOption {
type = int;
default = -1;
};
H264Crf = mkOption {
type = int;
default = 23;
};
H265Crf = mkOption {
type = int;
default = 28;
};
HardwareDecodingCodecs.string = mkOption {
type = listOf str;
default = [ "h254" "vc1" ];
};
MaxMuxingQueueSize = mkOption {
type = int;
default = 2048;
};
PreferSystemNativeHwDecoder = mkOption {
type = bool;
default = true;
};
ThrottleDelaySeconds = mkOption {
type = int;
default = 180;
};
TonemappingAlgorithm = mkOption {
type = str;
default = "bt2390";
};
TonemappingDesat = mkOption {
type = int;
default = 0;
};
TonemappingMode = mkOption {
type = str;
default = "auto";
};
TonemappingParam = mkOption {
type = int;
default = 0;
};
TonemappingPeak = mkOption {
type = int;
default = 100;
};
TonemappingRange = mkOption {
type = str;
default = "auto";
};
VaapiDevice = mkOption {
type = either path str;
default = "/dev/dri/renderD128";
};
VppTonemappingBrightness = mkOption {
type = int;
default = 16;
};
VppTonemappingContrast = mkOption {
type = int;
default = 1;
};
type = submodule {
freeformType = (pkgs.formats.json {}).type;
options = {
AllowOnDemandMetadataBasedKeyframeExtractionForExtensions.string = mkOption {
type = listOf str;
default = ["mkv"];
};
});
default = { };
DeinterlaceDoubleRate = mkOption {
type = bool;
default = false;
};
DeinterlaceMethod = mkOption {
type = str;
default = "yadif";
};
DownMixAudioBoost = mkOption {
type = int;
default = 2;
};
EnableDecodingColorDepth10Hevc = mkOption {
type = bool;
default = true;
};
EnableDecodingColorDepth10Vp9 = mkOption {
type = bool;
default = true;
};
EnableEnhancedNvdecDecoder = mkOption {
type = bool;
default = true;
};
EnableFallbackFont = mkOption {
type = bool;
default = false;
};
EnableHardwareEncoding = mkOption {
type = bool;
default = true;
};
EnableIntelLowPowerH264HwEncoder = mkOption {
type = bool;
default = false;
};
EnableIntelLowPowerHevcHwEncoder = mkOption {
type = bool;
default = false;
};
EnableSubtitleExtraction = mkOption {
type = bool;
default = true;
};
EnableThrottling = mkOption {
type = bool;
default = false;
};
EnableTonemapping = mkOption {
type = bool;
default = false;
};
EnableVppTonemapping = mkOption {
type = bool;
default = false;
};
EncoderAppPathDisplay = mkOption {
type = either path str;
default = "${pkgs.jellyfin-ffmpeg}/bin/ffmpeg";
};
EncodingThreadCount = mkOption {
type = int;
default = -1;
};
H264Crf = mkOption {
type = int;
default = 23;
};
H265Crf = mkOption {
type = int;
default = 28;
};
HardwareDecodingCodecs.string = mkOption {
type = listOf str;
default = ["h254" "vc1"];
};
MaxMuxingQueueSize = mkOption {
type = int;
default = 2048;
};
PreferSystemNativeHwDecoder = mkOption {
type = bool;
default = true;
};
ThrottleDelaySeconds = mkOption {
type = int;
default = 180;
};
TonemappingAlgorithm = mkOption {
type = str;
default = "bt2390";
};
TonemappingDesat = mkOption {
type = int;
default = 0;
};
TonemappingMode = mkOption {
type = str;
default = "auto";
};
TonemappingParam = mkOption {
type = int;
default = 0;
};
TonemappingPeak = mkOption {
type = int;
default = 100;
};
TonemappingRange = mkOption {
type = str;
default = "auto";
};
VaapiDevice = mkOption {
type = either path str;
default = "/dev/dri/renderD128";
};
VppTonemappingBrightness = mkOption {
type = int;
default = 16;
};
VppTonemappingContrast = mkOption {
type = int;
default = 1;
};
};
};
default = {};
};
system = mkOption {
type = (submodule {
freeformType = (pkgs.formats.json { }).type;
type = submodule {
freeformType = (pkgs.formats.json {}).type;
options = {
ActivityLogRetentionDays = mkOption {
type = int;
@@ -347,7 +349,7 @@ in
};
CorsHost.string = mkOption {
type = listOf str;
default = [ "*" ];
default = ["*"];
};
DisableLiveTvChannelUserDataName = mkOption {
type = bool;
@@ -439,19 +441,19 @@ in
}
{
ItemType = "MusicVideo";
DisabledMetadataFetchers.string = [ "The Open Movie Database" ];
DisabledImageFetchers.string = [ "The Open Movie Database" ];
DisabledMetadataFetchers.string = ["The Open Movie Database"];
DisabledImageFetchers.string = ["The Open Movie Database"];
}
{
ItemType = "Series";
}
{
ItemType = "MusicAlbum";
DisabledMetadataFetchers.string = [ "TheAudioDB" ];
DisabledMetadataFetchers.string = ["TheAudioDB"];
}
{
ItemType = "MusicArtist";
DisabledMetadataFetchers.string = [ "TheAudioDB" ];
DisabledMetadataFetchers.string = ["TheAudioDB"];
}
{
ItemType = "BoxSet";
@@ -470,27 +472,27 @@ in
type = str;
};
DisabledMetadataSavers.string = mkOption {
default = [ ];
default = [];
type = listOf str;
};
LocalMetadataReaderOrder.string = mkOption {
default = [ ];
default = [];
type = listOf str;
};
DisabledMetadataFetchers.string = mkOption {
default = [ ];
default = [];
type = listOf str;
};
MetadataFetcherOrder.string = mkOption {
default = [ ];
default = [];
type = listOf str;
};
DisabledImageFetchers.string = mkOption {
default = [ ];
default = [];
type = listOf str;
};
ImageFetcherOrder.string = mkOption {
default = [ ];
default = [];
type = listOf str;
};
};
@@ -517,11 +519,13 @@ in
default = "";
};
PluginRepositories.RepositoryInfo = mkOption {
default = [{
Name = "Jellyfin Stable";
Url = "https://repo.jellyfin.org/releases/plugin/manifest-stable.json";
Enabled = true;
}];
default = [
{
Name = "Jellyfin Stable";
Url = "https://repo.jellyfin.org/releases/plugin/manifest-stable.json";
Enabled = true;
}
];
type = listOf (submodule {
options = {
Name = mkOption {
@@ -571,23 +575,23 @@ in
};
SortRemoveCharacters.string = mkOption {
type = listOf str;
default = [ "," "&" "-" "{" "}" "'" ];
default = ["," "&" "-" "{" "}" "'"];
};
SortRemoveWords.string = mkOption {
type = listOf str;
default = [ "the" "a" "an" ];
default = ["the" "a" "an"];
};
SortReplaceCharacters.string = mkOption {
type = listOf str;
default = [ "." "+" "%" ];
default = ["." "+" "%"];
};
UICulture = mkOption {
type = str;
default = "en-US";
};
};
});
default = { };
};
default = {};
};
};
};
@@ -636,12 +640,11 @@ in
touch "$jellyfin_dir/config/system.xml";
echo "$(system_file)" > "$jellyfin_dir/config/system.xml";
'';
wantedBy = [ "multi-user.target" ];
after = [ "jellyfin.service" ];
wantedBy = ["multi-user.target"];
after = ["jellyfin.service"];
serviceConfig = {
Type = "oneshot";
};
};
};
}

View File

@@ -1,11 +1,13 @@
{ config, lib, ... }:
let
cfg = config.server.jellyseerr;
in
{
imports = [ ];
options.server.jellyseerr = with lib; with lib.types; {
config,
lib,
...
}: let
cfg = config.server.jellyseerr;
in {
imports = [];
options.server.jellyseerr = with lib;
with lib.types; {
enable = mkEnableOption "";
domain = mkOption {
type = str;

View File

@@ -1,11 +1,13 @@
{ config, lib, ... }:
let
cfg = config.server.network;
in
{
imports = [ ];
options.server.network = with lib; with lib.types; {
config,
lib,
...
}: let
cfg = config.server.network;
in {
imports = [];
options.server.network = with lib;
with lib.types; {
enable = mkOption {
type = bool;
default = true;
@@ -27,7 +29,7 @@ in
};
nameservers = mkOption {
type = listOf str;
default = [ "1.1.1.1" "8.8.8.8" ];
default = ["1.1.1.1" "8.8.8.8"];
};
portForwarding = mkOption {
type = bool;
@@ -37,25 +39,39 @@ in
type = bool;
default = true;
};
settings = { };
settings = {};
};
config = lib.mkIf cfg.enable {
host.networking.hostName = cfg.hostName;
networking = {
dhcpcd.enable = true;
interfaces."${cfg.interface}".ipv4.addresses = [{
address = cfg.localIp;
prefixLength = 28;
}];
interfaces."${cfg.interface}".ipv4.addresses = [
{
address = cfg.localIp;
prefixLength = 28;
}
];
defaultGateway = cfg.defaultGateway;
nameservers = [
(if config.server.tailscale.enable then "100.100.100.100" else null)
] ++ cfg.nameservers;
nameservers =
[
(
if config.server.tailscale.enable
then "100.100.100.100"
else null
)
]
++ cfg.nameservers;
};
boot.kernel.sysctl."net.ipv4.ip_forward" = if cfg.portForwarding then 1 else 0;
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = if cfg.portForwarding then 1 else 0;
boot.kernel.sysctl."net.ipv4.ip_forward" =
if cfg.portForwarding
then 1
else 0;
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" =
if cfg.portForwarding
then 1
else 0;
services.openssh.enable = cfg.openssh;
};

View File

@@ -1,11 +1,14 @@
{ config, lib, pkgs, ... }:
let
cfg = config.server.nextcloud;
in
{
imports = [ ];
options.server.nextcloud = with lib; with lib.types; {
config,
lib,
pkgs,
...
}: let
cfg = config.server.nextcloud;
in {
imports = [];
options.server.nextcloud = with lib;
with lib.types; {
enable = mkEnableOption "";
user = mkOption {
type = str;

View File

@@ -1,11 +1,13 @@
{ config, lib, ... }:
let
cfg = config.server.photoprism;
in
{
imports = [ ];
options.server.photoprism = with lib; with lib.types; {
config,
lib,
...
}: let
cfg = config.server.photoprism;
in {
imports = [];
options.server.photoprism = with lib;
with lib.types; {
enable = mkEnableOption "";
user = mkOption {
type = str;

View File

@@ -1,13 +1,15 @@
{ config, lib, ... }:
let
cfg = config.server.tailscale;
in
{
config,
lib,
...
}: let
cfg = config.server.tailscale;
in {
imports = [
./network.nix
];
options.server.tailscale = with lib; with lib.types; {
options.server.tailscale = with lib;
with lib.types; {
enable = mkEnableOption "";
mode = mkOption {
type = enum [
@@ -21,7 +23,7 @@ in
type = bool;
default = false;
};
settings = { };
settings = {};
};
config = lib.mkIf cfg.enable {
services.tailscale = {
@@ -29,7 +31,6 @@ in
useRoutingFeatures = cfg.mode;
};
server.network = lib.mkIf cfg.exitNode { portForwarding = lib.mkDefault true; };
server.network = lib.mkIf cfg.exitNode {portForwarding = lib.mkDefault true;};
};
}