refactor: rename "homelab" to "server"
This commit is contained in:
@@ -1,90 +0,0 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.adguard;
|
||||
in
|
||||
{
|
||||
imports = [ ];
|
||||
options.homelab.adguard = with lib; with lib.types; {
|
||||
enable = mkEnableOption "";
|
||||
extraArgs = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
};
|
||||
domain = mkOption {
|
||||
type = str;
|
||||
default = "adguard." + config.homelab.domain;
|
||||
};
|
||||
port = mkOption {
|
||||
type = port;
|
||||
default = 3010;
|
||||
};
|
||||
settings = {
|
||||
server.domain = mkOption {
|
||||
type = str;
|
||||
default = cfg.domain;
|
||||
};
|
||||
server.port = mkOption {
|
||||
type = port;
|
||||
default = cfg.port;
|
||||
};
|
||||
server.address = mkOption {
|
||||
type = str;
|
||||
default = "0.0.0.0";
|
||||
};
|
||||
dns.rewrites = mkOption {
|
||||
type = attrsOf str;
|
||||
default = { };
|
||||
};
|
||||
dns.filters = mkOption {
|
||||
type = attrsOf (submodule ({ lib, ... }: {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
};
|
||||
url = mkOption {
|
||||
type = str;
|
||||
};
|
||||
enabled = {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
}));
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
networking.firewall = {
|
||||
allowedTCPPorts = [ 53 ];
|
||||
allowedUDPPorts = [ 53 51820 ];
|
||||
};
|
||||
services.adguardhome = with builtins; {
|
||||
enable = true;
|
||||
settings = {
|
||||
bind_port = cfg.settings.server.port;
|
||||
bind_host = cfg.settings.server.address;
|
||||
http = {
|
||||
address = "${cfg.settings.server.address}:${toString cfg.settings.server.port}";
|
||||
};
|
||||
dns.rewrites = (builtins.attrValues (builtins.mapAttrs
|
||||
(from: to: {
|
||||
domain = from;
|
||||
answer = to;
|
||||
})
|
||||
cfg.settings.dns.rewrites));
|
||||
filters = (attrValues (mapAttrs
|
||||
(id: list: {
|
||||
name = if isNull list.name then id else list.name;
|
||||
ID = id;
|
||||
url = list.url;
|
||||
enabled = list.enabled;
|
||||
})
|
||||
cfg.settings.dns.filters));
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.caddy;
|
||||
in
|
||||
{
|
||||
imports = [ ];
|
||||
options.homelab.caddy = with lib; with lib.types; {
|
||||
enable = mkEnableOption "";
|
||||
settings = {
|
||||
virtualHosts = mkOption {
|
||||
type = attrsOf (submodule ({ config, lib, ... }: {
|
||||
options = {
|
||||
extraConfig = mkOption {
|
||||
type = lines;
|
||||
default = "";
|
||||
};
|
||||
};
|
||||
}));
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.caddy = {
|
||||
enable = true;
|
||||
virtualHosts = cfg.settings.virtualHosts;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab;
|
||||
homelab = pkgs.writeShellScriptBin "homelab" ''
|
||||
gum="${pkgs.gum}/bin/gum";
|
||||
flakeDir="${toString cfg.flakeDir}";
|
||||
|
||||
command="$1";
|
||||
|
||||
if [[ "$command" == "build" ]]; then
|
||||
shift 1;
|
||||
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 ""}
|
||||
'';
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
./adguard.nix
|
||||
./caddy.nix
|
||||
./forgejo.nix
|
||||
./jellyfin.nix
|
||||
./jellyseerr.nix
|
||||
./network.nix
|
||||
./nextcloud.nix
|
||||
./photoprism.nix
|
||||
./tailscale.nix
|
||||
];
|
||||
options.homelab = with lib; with lib.types; {
|
||||
enable = mkEnableOption "";
|
||||
name = mkOption {
|
||||
type = str;
|
||||
default = "homelab";
|
||||
};
|
||||
flakeDir = mkOption {
|
||||
type = str;
|
||||
};
|
||||
storage = mkOption {
|
||||
type = path;
|
||||
default = /data/homelab;
|
||||
description = "The Homelab central storage path";
|
||||
};
|
||||
domain = mkOption {
|
||||
type = either str path;
|
||||
default = "${cfg.name}.local";
|
||||
};
|
||||
localIp = mkOption {
|
||||
type = str;
|
||||
};
|
||||
ip = mkOption {
|
||||
type = str;
|
||||
default = cfg.localIp;
|
||||
};
|
||||
handleDomains = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = [
|
||||
homelab
|
||||
];
|
||||
|
||||
networking.firewall.allowedTCPPorts = lib.mkIf cfg.handleDomains [ 80 433 ];
|
||||
|
||||
systemd.services."tailscaled" = lib.mkIf cfg.handleDomains {
|
||||
serviceConfig = {
|
||||
Environment = [ "TS_PERMIT_CERT_UID=caddy" ];
|
||||
};
|
||||
};
|
||||
|
||||
homelab = 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 {
|
||||
enable = true;
|
||||
settings.virtualHosts = mapAttrs'
|
||||
(name: value: nameValuePair (value.domain) ({
|
||||
extraConfig = ''
|
||||
reverse_proxy ${cfg.localIp}:${toString value.port}
|
||||
'';
|
||||
}))
|
||||
homelabServices;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,311 +0,0 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.forgejo;
|
||||
users = (builtins.attrValues (builtins.mapAttrs
|
||||
(username: info: {
|
||||
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.homelab.forgejo = with lib; with lib.types; {
|
||||
enable = mkEnableOption "";
|
||||
user = mkOption {
|
||||
type = str;
|
||||
default = "git";
|
||||
};
|
||||
package = mkOption {
|
||||
type = package;
|
||||
default = pkgs.forgejo;
|
||||
};
|
||||
cliAlias = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
domain = mkOption {
|
||||
type = str;
|
||||
default = "forgejo." + config.homelab.domain;
|
||||
};
|
||||
port = mkOption {
|
||||
type = port;
|
||||
default = 3020;
|
||||
};
|
||||
data = {
|
||||
root = mkOption {
|
||||
type = path;
|
||||
default = config.homelab.storage + /forgejo;
|
||||
};
|
||||
};
|
||||
handleUndeclaredUsers = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
settings = {
|
||||
users = mkOption {
|
||||
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;
|
||||
};
|
||||
};
|
||||
}));
|
||||
default = { };
|
||||
};
|
||||
name = mkOption {
|
||||
type = str;
|
||||
default = "Forgejo: Beyond coding. We forge";
|
||||
};
|
||||
prod = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
repo.defaultUnits = mkOption {
|
||||
type = listOf (enum [
|
||||
"repo.code"
|
||||
"repo.releases"
|
||||
"repo.issues"
|
||||
"repo.pulls"
|
||||
"repo.wiki"
|
||||
"repo.projects"
|
||||
"repo.packages"
|
||||
"repo.actions"
|
||||
]);
|
||||
default = [
|
||||
"repo.code"
|
||||
"repo.issues"
|
||||
"repo.pulls"
|
||||
];
|
||||
};
|
||||
repo.disabledUnits = mkOption {
|
||||
type = listOf (enum [
|
||||
"repo.issues"
|
||||
"repo.ext_issues"
|
||||
"repo.pulls"
|
||||
"repo.wiki"
|
||||
"repo.ext_wiki"
|
||||
"repo.projects"
|
||||
"repo.packages"
|
||||
"repo.actions"
|
||||
]);
|
||||
default = [ ];
|
||||
};
|
||||
repo.pushCreate = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
cors.enable = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
cors.domains = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
};
|
||||
cors.methods = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
};
|
||||
ui.defaultTheme = mkOption {
|
||||
type = str;
|
||||
default = "forgejo-auto";
|
||||
};
|
||||
ui.themes = mkOption {
|
||||
type = listOf str;
|
||||
default = [
|
||||
"forgejo-auto"
|
||||
"forgejo-light"
|
||||
"forgejo-dark"
|
||||
"auto"
|
||||
"gitea"
|
||||
"arc-green"
|
||||
];
|
||||
};
|
||||
server.protocol = mkOption {
|
||||
type = enum [ "http" "https" "fcgi" "http+unix" "fcgi+unix" ];
|
||||
default = "http";
|
||||
};
|
||||
server.domain = mkOption {
|
||||
type = str;
|
||||
default = cfg.domain;
|
||||
};
|
||||
server.port = mkOption {
|
||||
type = port;
|
||||
default = cfg.port;
|
||||
};
|
||||
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";
|
||||
};
|
||||
server.url = mkOption {
|
||||
type = str;
|
||||
default = "http://${cfg.settings.server.domain}:${toString cfg.settings.server.port}";
|
||||
};
|
||||
server.offline = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
server.compression = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
server.landingPage = mkOption {
|
||||
type = enum [ "home" "explore" "organizations" "login" str ];
|
||||
default = "home";
|
||||
};
|
||||
service.registration = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
security.allowBypassGiteaEnv = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
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}" = { };
|
||||
|
||||
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";
|
||||
};
|
||||
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
|
||||
|
||||
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 ''
|
||||
$gum log --structured --time timeonly --level warn "UNDECLARED user, please declare it in the config so it's reproducible" username "$username";
|
||||
''}
|
||||
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}";
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,647 +0,0 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.jellyfin;
|
||||
networkConfig = pkgs.writeTextFile {
|
||||
name = "network.json";
|
||||
text = builtins.toJSON cfg.settings.network;
|
||||
};
|
||||
encodingConfig = pkgs.writeTextFile {
|
||||
name = "encoding.json";
|
||||
text = builtins.toJSON cfg.settings.encoding;
|
||||
};
|
||||
systemConfig = pkgs.writeTextFile {
|
||||
name = "encoding.json";
|
||||
text = builtins.toJSON cfg.settings.system;
|
||||
};
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
./jellyseerr.nix
|
||||
];
|
||||
options.homelab.jellyfin = with lib; with lib.types; {
|
||||
enable = mkEnableOption "";
|
||||
user = mkOption {
|
||||
type = str;
|
||||
default = "jellyfin";
|
||||
};
|
||||
package = mkOption {
|
||||
type = package;
|
||||
default = pkgs.jellyfin;
|
||||
};
|
||||
domain = mkOption {
|
||||
type = str;
|
||||
default = "jellyfin." + config.homelab.domain;
|
||||
};
|
||||
port = mkOption {
|
||||
type = port;
|
||||
default = 8096;
|
||||
};
|
||||
data = {
|
||||
root = mkOption {
|
||||
type = path;
|
||||
default = config.homelab.storage + /jellyfin;
|
||||
};
|
||||
};
|
||||
jellyseerr = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
settings = {
|
||||
network = mkOption {
|
||||
type = (submodule {
|
||||
freeformType = (pkgs.formats.json { }).type;
|
||||
options = {
|
||||
AutoDiscovery = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
AutoDiscoveryTracing = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
BaseUrl = mkOption {
|
||||
type = str;
|
||||
default = "https://${cfg.domain}";
|
||||
};
|
||||
CertificatePassword = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
CertificatePath = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
EnableHttps = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
EnableIPV4 = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
EnableIPV6 = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
EnablePublishedServerUriByRequest = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
EnableSSDPTracing = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
EnableRemoteAccess = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
EnableUPnP = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
GatewayMonitorPeriod = mkOption {
|
||||
type = int;
|
||||
default = 60;
|
||||
};
|
||||
HDHomerunPortRange = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
HttpServerPortNumber = mkOption {
|
||||
type = port;
|
||||
default = cfg.port;
|
||||
};
|
||||
HttpsPortNumber = mkOption {
|
||||
type = port;
|
||||
default = cfg.settings.network.PublicHttpsPort;
|
||||
};
|
||||
IgnoreVirtualInterfaces = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
IsRemoteIPFilterBlacklist = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
KnownProxies = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
LocalNetworkAddresses = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
LocalNetworkSubnets = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
PublicHttpsPort = mkOption {
|
||||
type = port;
|
||||
default = 8920;
|
||||
};
|
||||
PublicPort = mkOption {
|
||||
type = port;
|
||||
default = cfg.settings.network.HttpServerPortNumber;
|
||||
};
|
||||
PublishedServerUriBySubnet = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
RequireHttps = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
RemoteIPFilter = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
SSDPTracingFilter = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
TrustAllIP6Interfaces = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
UDPPortRange = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
UDPSendCount = mkOption {
|
||||
type = int;
|
||||
default = 2;
|
||||
};
|
||||
UDPSendDelay = mkOption {
|
||||
type = int;
|
||||
default = 100;
|
||||
};
|
||||
UPnPCreateHttpPortMap = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
VirtualInterfacenNames = mkOption {
|
||||
type = str;
|
||||
default = "vEthernet*";
|
||||
};
|
||||
};
|
||||
});
|
||||
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;
|
||||
};
|
||||
};
|
||||
});
|
||||
default = { };
|
||||
};
|
||||
system = mkOption {
|
||||
type = (submodule {
|
||||
freeformType = (pkgs.formats.json { }).type;
|
||||
options = {
|
||||
ActivityLogRetentionDays = mkOption {
|
||||
type = int;
|
||||
default = 30;
|
||||
};
|
||||
AllowClientLogUpload = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
CodecsUsed = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
ContentTypes = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
CorsHost.string = mkOption {
|
||||
type = listOf str;
|
||||
default = [ "*" ];
|
||||
};
|
||||
DisableLiveTvChannelUserDataName = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
DisplaySpecialsWithinSeasons = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
EnableCaseSensitiveItemIds = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
EnableExternalContentInSuggestions = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
EnableFolderView = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
EnableGroupingIntoCollections = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
EnableMetrics = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
EnableNormalizedItemByNameIds = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
EnableSlowResponseWarning = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
ImageExtractionTimeoutMs = mkOption {
|
||||
type = int;
|
||||
default = 0;
|
||||
};
|
||||
ImageSavingConvention = mkOption {
|
||||
type = str;
|
||||
default = "Legacy";
|
||||
};
|
||||
IsPortAuthorized = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
IsStartupWizardCompleted = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
LibraryMetadataRefreshConcurrency = mkOption {
|
||||
type = int;
|
||||
default = 0;
|
||||
};
|
||||
LibraryMonitorDelay = mkOption {
|
||||
type = int;
|
||||
default = 60;
|
||||
};
|
||||
LogFileRetentionDays = mkOption {
|
||||
type = int;
|
||||
default = 3;
|
||||
};
|
||||
MaxAudiobookResume = mkOption {
|
||||
type = int;
|
||||
default = 5;
|
||||
};
|
||||
MaxResumePct = mkOption {
|
||||
type = int;
|
||||
default = 90;
|
||||
};
|
||||
MetadataCountryCode = mkOption {
|
||||
type = str;
|
||||
default = "US";
|
||||
};
|
||||
MetadataNetworkPath = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
MetadataOptions.MetadataOptions = mkOption {
|
||||
default = [
|
||||
{
|
||||
ItemType = "Book";
|
||||
}
|
||||
{
|
||||
ItemType = "Movie";
|
||||
}
|
||||
{
|
||||
ItemType = "MusicVideo";
|
||||
DisabledMetadataFetchers.string = [ "The Open Movie Database" ];
|
||||
DisabledImageFetchers.string = [ "The Open Movie Database" ];
|
||||
}
|
||||
{
|
||||
ItemType = "Series";
|
||||
}
|
||||
{
|
||||
ItemType = "MusicAlbum";
|
||||
DisabledMetadataFetchers.string = [ "TheAudioDB" ];
|
||||
}
|
||||
{
|
||||
ItemType = "MusicArtist";
|
||||
DisabledMetadataFetchers.string = [ "TheAudioDB" ];
|
||||
}
|
||||
{
|
||||
ItemType = "BoxSet";
|
||||
}
|
||||
{
|
||||
ItemType = "Season";
|
||||
}
|
||||
{
|
||||
ItemType = "Episode";
|
||||
}
|
||||
];
|
||||
type = listOf (submodule {
|
||||
options = {
|
||||
ItemType = mkOption {
|
||||
default = "Movie";
|
||||
type = str;
|
||||
};
|
||||
DisabledMetadataSavers.string = mkOption {
|
||||
default = [ ];
|
||||
type = listOf str;
|
||||
};
|
||||
LocalMetadataReaderOrder.string = mkOption {
|
||||
default = [ ];
|
||||
type = listOf str;
|
||||
};
|
||||
DisabledMetadataFetchers.string = mkOption {
|
||||
default = [ ];
|
||||
type = listOf str;
|
||||
};
|
||||
MetadataFetcherOrder.string = mkOption {
|
||||
default = [ ];
|
||||
type = listOf str;
|
||||
};
|
||||
DisabledImageFetchers.string = mkOption {
|
||||
default = [ ];
|
||||
type = listOf str;
|
||||
};
|
||||
ImageFetcherOrder.string = mkOption {
|
||||
default = [ ];
|
||||
type = listOf str;
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
MetadataPath = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
MinAudiobookResume = mkOption {
|
||||
type = int;
|
||||
default = 5;
|
||||
};
|
||||
MinResumeDurationSeconds = mkOption {
|
||||
type = int;
|
||||
default = 300;
|
||||
};
|
||||
MinResumePct = mkOption {
|
||||
type = int;
|
||||
default = 5;
|
||||
};
|
||||
PathSubstitutions = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
PluginRepositories.RepositoryInfo = mkOption {
|
||||
default = [{
|
||||
Name = "Jellyfin Stable";
|
||||
Url = "https://repo.jellyfin.org/releases/plugin/manifest-stable.json";
|
||||
Enabled = true;
|
||||
}];
|
||||
type = listOf (submodule {
|
||||
options = {
|
||||
Name = mkOption {
|
||||
type = str;
|
||||
};
|
||||
Url = mkOption {
|
||||
type = str;
|
||||
};
|
||||
Enabled = mkOption {
|
||||
default = true;
|
||||
type = bool;
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
PreferredMetadataLanguage = mkOption {
|
||||
type = str;
|
||||
default = "en";
|
||||
};
|
||||
QuickConnectAvailable = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
RemoteClientBitrateLimit = mkOption {
|
||||
type = int;
|
||||
default = 0;
|
||||
};
|
||||
RemoveOldPlugins = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
SaveMetadataHidden = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
ServerName = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
SkipDeserializationForBasicTypes = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
SlowResponseThreshold = mkOption {
|
||||
type = int;
|
||||
default = 500;
|
||||
};
|
||||
SortRemoveCharacters.string = mkOption {
|
||||
type = listOf str;
|
||||
default = [ "," "&" "-" "{" "}" "'" ];
|
||||
};
|
||||
SortRemoveWords.string = mkOption {
|
||||
type = listOf str;
|
||||
default = [ "the" "a" "an" ];
|
||||
};
|
||||
SortReplaceCharacters.string = mkOption {
|
||||
type = listOf str;
|
||||
default = [ "." "+" "%" ];
|
||||
};
|
||||
UICulture = mkOption {
|
||||
type = str;
|
||||
default = "en-US";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.jellyfin = {
|
||||
enable = true;
|
||||
package = cfg.package;
|
||||
user = cfg.user;
|
||||
group = cfg.user;
|
||||
openFirewall = true;
|
||||
};
|
||||
|
||||
homelab.jellyseerr.enable = cfg.jellyseerr;
|
||||
|
||||
systemd.services."homelab-jellyfin-config" = {
|
||||
script = ''
|
||||
jellyfin_dir="/var/lib/jellyfin";
|
||||
|
||||
function network_file() {
|
||||
echo '<?xml version="1.0" enconding="utf-8"?>';
|
||||
echo '<NetworkConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">';
|
||||
cat ${networkConfig} | ${pkgs.yq-go}/bin/yq --input-format json --output-format xml;
|
||||
echo '</NetworkConfiguration>';
|
||||
}
|
||||
function encoding_file() {
|
||||
echo '<?xml version="1.0" enconding="utf-8"?>';
|
||||
echo '<EncodingOptions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">';
|
||||
cat ${encodingConfig} | ${pkgs.yq-go}/bin/yq --input-format json --output-format xml;
|
||||
echo '</EncodingOptions>';
|
||||
}
|
||||
function system_file() {
|
||||
echo '<?xml version="1.0" enconding="utf-8"?>';
|
||||
echo '<ServerConfiguraion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">';
|
||||
cat ${systemConfig} | ${pkgs.yq-go}/bin/yq --input-format json --output-format xml;
|
||||
echo '</ServerConfiguraion>';
|
||||
}
|
||||
|
||||
mkdir -p $jellyfin_dir/config;
|
||||
|
||||
touch "$jellyfin_dir/config/network.xml";
|
||||
echo "$(network_file)" > "$jellyfin_dir/config/network.xml";
|
||||
|
||||
touch "$jellyfin_dir/config/encoding.xml";
|
||||
echo "$(encoding_file)" > "$jellyfin_dir/config/encoding.xml";
|
||||
|
||||
touch "$jellyfin_dir/config/system.xml";
|
||||
echo "$(system_file)" > "$jellyfin_dir/config/system.xml";
|
||||
'';
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "jellyfin.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.jellyseerr;
|
||||
in
|
||||
{
|
||||
imports = [ ];
|
||||
options.homelab.jellyseerr = with lib; with lib.types; {
|
||||
enable = mkEnableOption "";
|
||||
domain = mkOption {
|
||||
type = str;
|
||||
default = "jellyseerr." + config.homelab.domain;
|
||||
};
|
||||
port = mkOption {
|
||||
type = port;
|
||||
default = config.homelab.jellyfin.port + 10;
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.jellyseerr = {
|
||||
enable = true;
|
||||
port = cfg.port;
|
||||
openFirewall = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.network;
|
||||
in
|
||||
{
|
||||
imports = [ ];
|
||||
options.homelab.network = with lib; with lib.types; {
|
||||
enable = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
hostName = mkOption {
|
||||
type = str;
|
||||
default = config.homelab.name;
|
||||
};
|
||||
interface = mkOption {
|
||||
type = str;
|
||||
};
|
||||
localIp = mkOption {
|
||||
type = str;
|
||||
default = config.homelab.localIp;
|
||||
};
|
||||
defaultGateway = mkOption {
|
||||
type = str;
|
||||
default = "192.168.1.1";
|
||||
};
|
||||
nameservers = mkOption {
|
||||
type = listOf str;
|
||||
default = [ "1.1.1.1" "8.8.8.8" ];
|
||||
};
|
||||
portForwarding = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
openssh = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
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;
|
||||
}];
|
||||
defaultGateway = cfg.defaultGateway;
|
||||
nameservers = [
|
||||
(if config.homelab.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;
|
||||
|
||||
services.openssh.enable = cfg.openssh;
|
||||
};
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.nextcloud;
|
||||
in
|
||||
{
|
||||
imports = [ ];
|
||||
options.homelab.nextcloud = with lib; with lib.types; {
|
||||
enable = mkEnableOption "";
|
||||
user = mkOption {
|
||||
type = str;
|
||||
default = "nextcloud";
|
||||
};
|
||||
package = mkOption {
|
||||
type = package;
|
||||
default = pkgs.nextcloud28;
|
||||
};
|
||||
domain = mkOption {
|
||||
type = str;
|
||||
default = "nextcloud." + config.homelab.domain;
|
||||
};
|
||||
port = mkOption {
|
||||
type = port;
|
||||
default = 3030;
|
||||
};
|
||||
data = {
|
||||
root = mkOption {
|
||||
type = path;
|
||||
default = config.homelab.storage + /nextcloud;
|
||||
};
|
||||
};
|
||||
configureRedis = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
settings = {
|
||||
admin.user = mkOption {
|
||||
type = str;
|
||||
default = cfg.user;
|
||||
};
|
||||
admin.passwordFile = mkOption {
|
||||
type = path;
|
||||
};
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.nextcloud = {
|
||||
config = {
|
||||
adminuser = cfg.settings.admin.user;
|
||||
adminpassFile = toString cfg.settings.admin.passwordFile;
|
||||
};
|
||||
configureRedis = cfg.configureRedis;
|
||||
enable = true;
|
||||
home = toString cfg.data.root;
|
||||
hostName = cfg.domain;
|
||||
https = true;
|
||||
package = cfg.package;
|
||||
# phpPackage = pkgs.php;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.photoprism;
|
||||
in
|
||||
{
|
||||
imports = [ ];
|
||||
options.homelab.photoprism = with lib; with lib.types; {
|
||||
enable = mkEnableOption "";
|
||||
user = mkOption {
|
||||
type = str;
|
||||
default = "photoprism";
|
||||
};
|
||||
domain = mkOption {
|
||||
type = str;
|
||||
default = "photoprism." + config.homelab.domain;
|
||||
};
|
||||
port = mkOption {
|
||||
type = port;
|
||||
default = 2342;
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.photoprism = {
|
||||
enable = true;
|
||||
port = cfg.port;
|
||||
settings = {
|
||||
PHOTOPRISM_HTTP_PORT = cfg.port;
|
||||
PHOTOPRISM_SITE_URL = cfg.domain;
|
||||
PHOTOPRISM_DISABLE_TLS = true;
|
||||
PHOTOPRISM_ADMIN_USER = cfg.user;
|
||||
PHOTOPRISM_ADMIN_PASSWORD = cfg.user;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.tailscale;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
./network.nix
|
||||
];
|
||||
options.homelab.tailscale = with lib; with lib.types; {
|
||||
enable = mkEnableOption "";
|
||||
mode = mkOption {
|
||||
type = enum [
|
||||
"client"
|
||||
"server"
|
||||
"both"
|
||||
];
|
||||
default = "both";
|
||||
};
|
||||
exitNode = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
settings = { };
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.tailscale = {
|
||||
enable = true;
|
||||
useRoutingFeatures = cfg.mode;
|
||||
};
|
||||
|
||||
homelab.network = lib.mkIf cfg.exitNode { portForwarding = lib.mkDefault true; };
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user