refactor: rename "homelab" to "server"

This commit is contained in:
Gustavo "Guz" L. de Mello
2024-03-03 11:32:07 -03:00
parent 0b61402d46
commit d236078a13
12 changed files with 44 additions and 46 deletions

View File

@@ -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));
};
};
};
}

View File

@@ -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;
};
};
}

View File

@@ -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;
};
};
};
}

View File

@@ -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;
};
};
};
}

View File

@@ -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";
};
};
};
}

View File

@@ -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;
};
};
}

View File

@@ -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;
};
}

View File

@@ -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;
};
};
}

View File

@@ -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;
};
};
};
}

View File

@@ -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; };
};
}