refactor: moved server module configs out of default.nix files

This commit is contained in:
Leyla Becker 2025-10-25 02:56:07 -05:00
parent 89793fca6a
commit 30a042d709
14 changed files with 381 additions and 367 deletions

View file

@ -0,0 +1,20 @@
{
lib,
config,
...
}: let
const = import ./const.nix;
dataDirectory = const.dataDirectory;
in {
config = lib.mkIf config.services.actual.enable {
systemd.tmpfiles.rules = [
"d ${dataDirectory} 2770 actual actual"
];
services.actual = {
settings = {
ACTUAL_DATA_DIR = dataDirectory;
};
};
};
}

View file

@ -1,26 +1,8 @@
{
lib,
config,
...
}: let
const = import ./const.nix;
dataDirectory = const.dataDirectory;
in {
imports = [
./actual.nix
./proxy.nix
./fail2ban.nix
./impermanence.nix
];
config = lib.mkIf config.services.actual.enable {
systemd.tmpfiles.rules = [
"d ${dataDirectory} 2770 actual actual"
];
services.actual = {
settings = {
ACTUAL_DATA_DIR = dataDirectory;
};
};
};
}

View file

@ -1,53 +1,9 @@
{
lib,
config,
...
}: let
const = import ./const.nix;
httpPort = const.httpPort;
sshPort = const.sshPort;
db_user = "forgejo";
in {
imports = [
./forgejo.nix
./proxy.nix
./database.nix
./fail2ban.nix
./impermanence.nix
];
config = lib.mkIf config.services.forgejo.enable {
assertions = [
{
assertion = config.services.forgejo.settings.server.BUILTIN_SSH_SERVER_USER == config.users.users.git.name;
message = "Forgejo BUILTIN_SSH_SERVER_USER hardcoded value does not match expected git user name";
}
];
services.forgejo = {
database = {
type = "postgres";
socket = "/run/postgresql";
};
lfs.enable = true;
settings = {
server = {
DOMAIN = config.services.forgejo.reverseProxy.domain;
HTTP_PORT = httpPort;
START_SSH_SERVER = true;
SSH_LISTEN_PORT = sshPort;
SSH_PORT = 22;
BUILTIN_SSH_SERVER_USER = "git";
ROOT_URL = "https://git.jan-leila.com";
};
service = {
DISABLE_REGISTRATION = true;
};
database = {
DB_TYPE = "postgres";
NAME = db_user;
USER = db_user;
};
};
};
};
}

View file

@ -0,0 +1,46 @@
{
lib,
config,
...
}: let
const = import ./const.nix;
httpPort = const.httpPort;
sshPort = const.sshPort;
db_user = "forgejo";
in {
config = lib.mkIf config.services.forgejo.enable {
assertions = [
{
assertion = config.services.forgejo.settings.server.BUILTIN_SSH_SERVER_USER == config.users.users.git.name;
message = "Forgejo BUILTIN_SSH_SERVER_USER hardcoded value does not match expected git user name";
}
];
services.forgejo = {
database = {
type = "postgres";
socket = "/run/postgresql";
};
lfs.enable = true;
settings = {
server = {
DOMAIN = config.services.forgejo.reverseProxy.domain;
HTTP_PORT = httpPort;
START_SSH_SERVER = true;
SSH_LISTEN_PORT = sshPort;
SSH_PORT = 22;
BUILTIN_SSH_SERVER_USER = "git";
ROOT_URL = "https://git.jan-leila.com";
};
service = {
DISABLE_REGISTRATION = true;
};
database = {
DB_TYPE = "postgres";
NAME = db_user;
USER = db_user;
};
};
};
};
}

View file

@ -1,112 +1,10 @@
{
lib,
config,
...
}: {
imports = [
./home-assistant.nix
./proxy.nix
./database.nix
./fail2ban.nix
./impermanence.nix
./extensions
];
options.services.home-assistant = {
database = lib.mkOption {
type = lib.types.enum [
"builtin"
"postgres"
];
description = "what database do we want to use";
default = "builtin";
};
extensions = {
sonos = {
enable = lib.mkEnableOption "enable the sonos plugin";
port = lib.mkOption {
type = lib.types.int;
default = 1400;
description = "what port to use for sonos discovery";
};
};
jellyfin = {
enable = lib.mkEnableOption "enable the jellyfin plugin";
};
wyoming = {
enable = lib.mkEnableOption "enable wyoming";
};
};
};
config = lib.mkIf config.services.home-assistant.enable (lib.mkMerge [
{
services.home-assistant = {
configDir = "/var/lib/hass";
extraComponents = [
"default_config"
"esphome"
"met"
"radio_browser"
"isal"
"zha"
"webostv"
"tailscale"
"syncthing"
"analytics_insights"
"unifi"
"openweathermap"
"ollama"
"mobile_app"
"logbook"
"ssdp"
"usb"
"webhook"
"bluetooth"
"dhcp"
"energy"
"history"
"backup"
"assist_pipeline"
"conversation"
"sun"
"zeroconf"
"cpuspeed"
];
config = {
http = {
server_port = 8123;
use_x_forwarded_for = true;
trusted_proxies = ["127.0.0.1" "::1"];
ip_ban_enabled = true;
login_attempts_threshold = 10;
};
homeassistant = {
external_url = "https://${config.services.home-assistant.domain}";
# internal_url = "http://192.168.1.2:8123";
};
recorder.db_url = "postgresql://@/${config.services.home-assistant.configDir}";
"automation manual" = [];
"automation ui" = "!include automations.yaml";
mobile_app = {};
};
extraPackages = python3Packages:
with python3Packages; [
hassil
numpy
gtts
];
};
# TODO: configure /var/lib/hass/secrets.yaml via sops
networking.firewall.allowedUDPPorts = [
1900
];
systemd.tmpfiles.rules = [
"f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass"
];
}
]);
}

View file

@ -0,0 +1,104 @@
{
lib,
config,
...
}: {
options.services.home-assistant = {
database = lib.mkOption {
type = lib.types.enum [
"builtin"
"postgres"
];
description = "what database do we want to use";
default = "builtin";
};
extensions = {
sonos = {
enable = lib.mkEnableOption "enable the sonos plugin";
port = lib.mkOption {
type = lib.types.int;
default = 1400;
description = "what port to use for sonos discovery";
};
};
jellyfin = {
enable = lib.mkEnableOption "enable the jellyfin plugin";
};
wyoming = {
enable = lib.mkEnableOption "enable wyoming";
};
};
};
config = lib.mkIf config.services.home-assistant.enable (lib.mkMerge [
{
services.home-assistant = {
configDir = "/var/lib/hass";
extraComponents = [
"default_config"
"esphome"
"met"
"radio_browser"
"isal"
"zha"
"webostv"
"tailscale"
"syncthing"
"analytics_insights"
"unifi"
"openweathermap"
"ollama"
"mobile_app"
"logbook"
"ssdp"
"usb"
"webhook"
"bluetooth"
"dhcp"
"energy"
"history"
"backup"
"assist_pipeline"
"conversation"
"sun"
"zeroconf"
"cpuspeed"
];
config = {
http = {
server_port = 8123;
use_x_forwarded_for = true;
trusted_proxies = ["127.0.0.1" "::1"];
ip_ban_enabled = true;
login_attempts_threshold = 10;
};
homeassistant = {
external_url = "https://${config.services.home-assistant.domain}";
# internal_url = "http://192.168.1.2:8123";
};
recorder.db_url = "postgresql://@/${config.services.home-assistant.configDir}";
"automation manual" = [];
"automation ui" = "!include automations.yaml";
mobile_app = {};
};
extraPackages = python3Packages:
with python3Packages; [
hassil
numpy
gtts
];
};
# TODO: configure /var/lib/hass/secrets.yaml via sops
networking.firewall.allowedUDPPorts = [
1900
];
systemd.tmpfiles.rules = [
"f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass"
];
}
]);
}

View file

@ -1,38 +1,8 @@
{
lib,
pkgs,
config,
...
}: let
jellyfinPort = 8096;
dlanPort = 1900;
in {
imports = [
./jellyfin.nix
./proxy.nix
./fail2ban.nix
./impermanence.nix
];
options.services.jellyfin = {
media_directory = lib.mkOption {
type = lib.types.str;
description = "directory jellyfin media will be hosted at";
default = "/srv/jellyfin/media";
};
};
config = lib.mkIf config.services.jellyfin.enable {
environment.systemPackages = [
pkgs.jellyfin
pkgs.jellyfin-web
pkgs.jellyfin-ffmpeg
];
networking.firewall.allowedTCPPorts = [jellyfinPort dlanPort];
systemd.tmpfiles.rules = [
"d ${config.services.jellyfin.media_directory} 2770 jellyfin jellyfin_media"
"A ${config.services.jellyfin.media_directory} - - - - u:jellyfin:rwX,g:jellyfin_media:rwX,o::-"
];
};
}

View file

@ -0,0 +1,32 @@
{
lib,
pkgs,
config,
...
}: let
jellyfinPort = 8096;
dlanPort = 1900;
in {
options.services.jellyfin = {
media_directory = lib.mkOption {
type = lib.types.str;
description = "directory jellyfin media will be hosted at";
default = "/srv/jellyfin/media";
};
};
config = lib.mkIf config.services.jellyfin.enable {
environment.systemPackages = [
pkgs.jellyfin
pkgs.jellyfin-web
pkgs.jellyfin-ffmpeg
];
networking.firewall.allowedTCPPorts = [jellyfinPort dlanPort];
systemd.tmpfiles.rules = [
"d ${config.services.jellyfin.media_directory} 2770 jellyfin jellyfin_media"
"A ${config.services.jellyfin.media_directory} - - - - u:jellyfin:rwX,g:jellyfin_media:rwX,o::-"
];
};
}

View file

@ -1,90 +1,6 @@
{
config,
lib,
...
}: let
export_directory = config.host.network_storage.export_directory;
in {
imports = [
./network_storage.nix
./nfs.nix
];
options = {
host.network_storage = {
enable = lib.mkEnableOption "is this machine going to export network storage";
export_directory = lib.mkOption {
type = lib.types.path;
description = "what are exports going to be stored in";
default = "/exports";
};
directories = lib.mkOption {
type = lib.types.listOf (lib.types.submodule ({config, ...}: {
options = {
folder = lib.mkOption {
type = lib.types.str;
description = "what is the name of this export directory";
};
bind = lib.mkOption {
type = lib.types.nullOr lib.types.path;
description = "is this directory bound to anywhere";
default = null;
};
user = lib.mkOption {
type = lib.types.str;
description = "what user owns this directory";
default = "nouser";
};
group = lib.mkOption {
type = lib.types.str;
description = "what group owns this directory";
default = "nogroup";
};
_directory = lib.mkOption {
internal = true;
readOnly = true;
type = lib.types.path;
default = "${export_directory}/${config.folder}";
};
};
}));
description = "list of directory names to export";
};
};
};
config = lib.mkIf config.host.network_storage.enable (lib.mkMerge [
{
# create any folders that we need to have for our exports
systemd.tmpfiles.rules =
[
"d ${config.host.network_storage.export_directory} 2775 nobody nogroup -"
]
++ (
builtins.map (
directory: "d ${directory._directory} 2770 ${directory.user} ${directory.group}"
)
config.host.network_storage.directories
);
# set up any bind mounts that we need for our exports
fileSystems = builtins.listToAttrs (
builtins.map (directory:
lib.attrsets.nameValuePair directory._directory {
device = directory.bind;
options = ["bind"];
}) (
builtins.filter (directory: directory.bind != null) config.host.network_storage.directories
)
);
}
# (lib.mkIf config.host.impermanence.enable {
# environment.persistence."/persist/system/root" = {
# enable = true;
# hideMounts = true;
# directories = [
# config.host.network_storage.export_directory
# ];
# };
# })
]);
}

View file

@ -0,0 +1,86 @@
{
config,
lib,
...
}: let
export_directory = config.host.network_storage.export_directory;
in {
options = {
host.network_storage = {
enable = lib.mkEnableOption "is this machine going to export network storage";
export_directory = lib.mkOption {
type = lib.types.path;
description = "what are exports going to be stored in";
default = "/exports";
};
directories = lib.mkOption {
type = lib.types.listOf (lib.types.submodule ({config, ...}: {
options = {
folder = lib.mkOption {
type = lib.types.str;
description = "what is the name of this export directory";
};
bind = lib.mkOption {
type = lib.types.nullOr lib.types.path;
description = "is this directory bound to anywhere";
default = null;
};
user = lib.mkOption {
type = lib.types.str;
description = "what user owns this directory";
default = "nouser";
};
group = lib.mkOption {
type = lib.types.str;
description = "what group owns this directory";
default = "nogroup";
};
_directory = lib.mkOption {
internal = true;
readOnly = true;
type = lib.types.path;
default = "${export_directory}/${config.folder}";
};
};
}));
description = "list of directory names to export";
};
};
};
config = lib.mkIf config.host.network_storage.enable (lib.mkMerge [
{
# create any folders that we need to have for our exports
systemd.tmpfiles.rules =
[
"d ${config.host.network_storage.export_directory} 2775 nobody nogroup -"
]
++ (
builtins.map (
directory: "d ${directory._directory} 2770 ${directory.user} ${directory.group}"
)
config.host.network_storage.directories
);
# set up any bind mounts that we need for our exports
fileSystems = builtins.listToAttrs (
builtins.map (directory:
lib.attrsets.nameValuePair directory._directory {
device = directory.bind;
options = ["bind"];
}) (
builtins.filter (directory: directory.bind != null) config.host.network_storage.directories
)
);
}
# (lib.mkIf config.host.impermanence.enable {
# environment.persistence."/persist/system/root" = {
# enable = true;
# hideMounts = true;
# directories = [
# config.host.network_storage.export_directory
# ];
# };
# })
]);
}

View file

@ -1,34 +1,9 @@
{
config,
lib,
...
}: {
imports = [
./paperless.nix
./proxy.nix
./database.nix
./fail2ban.nix
./impermanence.nix
];
options.services.paperless = {
database = {
user = lib.mkOption {
type = lib.types.str;
description = "what is the user and database that we are going to use for paperless";
default = "paperless";
};
};
};
config = lib.mkIf config.services.paperless.enable {
services.paperless = {
configureTika = true;
settings = {
PAPERLESS_DBENGINE = "postgresql";
PAPERLESS_DBHOST = "/run/postgresql";
PAPERLESS_DBNAME = config.services.paperless.database.user;
PAPERLESS_DBUSER = config.services.paperless.database.user;
};
};
};
}

View file

@ -0,0 +1,27 @@
{
config,
lib,
...
}: {
options.services.paperless = {
database = {
user = lib.mkOption {
type = lib.types.str;
description = "what is the user and database that we are going to use for paperless";
default = "paperless";
};
};
};
config = lib.mkIf config.services.paperless.enable {
services.paperless = {
configureTika = true;
settings = {
PAPERLESS_DBENGINE = "postgresql";
PAPERLESS_DBHOST = "/run/postgresql";
PAPERLESS_DBNAME = config.services.paperless.database.user;
PAPERLESS_DBUSER = config.services.paperless.database.user;
};
};
};
}

View file

@ -1,63 +1,6 @@
{
config,
lib,
inputs,
...
}: {
imports = [
./searx.nix
./proxy.nix
];
config = lib.mkIf config.services.searx.enable {
sops.secrets = {
"services/searx" = {
sopsFile = "${inputs.secrets}/defiant-services.yaml";
};
};
services.searx = {
environmentFile = config.sops.secrets."services/searx".path;
# Rate limiting
limiterSettings = {
real_ip = {
x_for = 1;
ipv4_prefix = 32;
ipv6_prefix = 56;
};
botdetection = {
ip_limit = {
filter_link_local = true;
link_token = true;
};
};
};
settings = {
server = {
port = 8083;
secret_key = "@SEARXNG_SECRET@";
};
# Search engine settings
search = {
safe_search = 2;
autocomplete_min = 2;
autocomplete = "duckduckgo";
};
# Enabled plugins
enabled_plugins = [
"Basic Calculator"
"Hash plugin"
"Tor check plugin"
"Open Access DOI rewrite"
"Hostnames plugin"
"Unit converter plugin"
"Tracker URL remover"
];
};
};
};
}

View file

@ -0,0 +1,59 @@
{
config,
lib,
inputs,
...
}: {
config = lib.mkIf config.services.searx.enable {
sops.secrets = {
"services/searx" = {
sopsFile = "${inputs.secrets}/defiant-services.yaml";
};
};
services.searx = {
environmentFile = config.sops.secrets."services/searx".path;
# Rate limiting
limiterSettings = {
real_ip = {
x_for = 1;
ipv4_prefix = 32;
ipv6_prefix = 56;
};
botdetection = {
ip_limit = {
filter_link_local = true;
link_token = true;
};
};
};
settings = {
server = {
port = 8083;
secret_key = "@SEARXNG_SECRET@";
};
# Search engine settings
search = {
safe_search = 2;
autocomplete_min = 2;
autocomplete = "duckduckgo";
};
# Enabled plugins
enabled_plugins = [
"Basic Calculator"
"Hash plugin"
"Tor check plugin"
"Open Access DOI rewrite"
"Hostnames plugin"
"Unit converter plugin"
"Tracker URL remover"
];
};
};
};
}