Files
nix-config/lib/module/default.nix
mjallen18 479ac18f20 some sops
2025-12-19 13:32:07 -06:00

235 lines
6.2 KiB
Nix

{ inputs, lib, namespace }:
let
inherit (inputs.nixpkgs.lib)
mapAttrs
mkOption
types
toUpper
substring
stringLength
mkDefault
mkForce
;
base64Lib = import ../base64 { inherit inputs; };
in
rec {
# Conditionally enable modules based on system
enableForSystem =
system: modules:
builtins.filter (
mod: mod.systems or [ ] == [ ] || builtins.elem system (mod.systems or [ ])
) modules;
# Create a module with common options
mkModule =
{
name,
description ? "",
options ? { },
moduleConfig ? { },
domain ? "services",
config
}:
let
cfg = config.${namespace}.${domain}.${name};
# Create reverse proxy configuration using mkReverseProxy
reverseProxyConfig = lib.${namespace}.mkReverseProxy {
inherit name;
subdomain = cfg.reverseProxy.subdomain;
url = "http://${config.${namespace}.network.ipv4.address}:${toString cfg.port}";
middlewares = cfg.reverseProxy.middlewares;
};
defaultConfig = {
${namespace}.services.traefik = lib.mkIf cfg.reverseProxy.enable {
reverseProxies = [ reverseProxyConfig ];
};
# Open firewall
networking.firewall = lib.mkIf cfg.openFirewall {
allowedTCPPorts = [ cfg.port ];
allowedUDPPorts = [ cfg.port ];
};
users = lib.mkIf cfg.createUser {
users.${name} = {
isSystemUser = true;
group = name;
home = cfg.configDir;
};
groups.${name} = { };
};
services = {
postgresql = lib.mkIf cfg.configureDb {
enable = true;
ensureDatabases = [ name ];
ensureUsers = [
{
name = name;
ensureDBOwnership = true;
}
];
};
redis.servers.${name} = lib.mkIf cfg.redis.enable {
enable = true;
port = cfg.redis.port;
};
};
# systemd.tmpfiles.rules = [
# "d ${cfg.configDir} 0700 ${name} ${name} - -"
# # "d ${cfg.configDir}/server-files 0775 ${name} ${name} - -"
# # "d ${cfg.configDir}/user-files 0775 ${name} ${name} - -"
# ];
} // moduleConfig;
in
{ config, lib, ... }:
{
options.${namespace}.${domain}.${name} = lib.mkOption {
type = lib.types.submodule {
options = {
enable = lib.mkEnableOption description;
port = mkOpt types.int 80 "Port for ${name} to be hosted on";
configDir = mkOpt types.str "/media/nas/main/nix-app-data" "Path to the config dir";
dataDir = mkOpt types.str "/media/nas/main" "Path to the data dir";
createUser = mkBoolOpt false "create a user for this module/service";
configureDb = mkBoolOpt false "Manage db for this service";
environmentFile = mkOpt types.str "" "Environment File";
puid = mkOpt types.str "911" "default user id";
pgid = mkOpt types.str "1000" "default group id";
timeZone = mkOpt types.str "America/Chicago" "default timezone";
listenAddress = mkOpt types.str "0.0.0.0" "Environment File";
openFirewall = mkBoolOpt true "Open the firewall";
redis = {
enable = lib.mkEnableOption "enable redis";
port = mkOpt types.int 80 "Port for ${name} redis to be hosted on";
};
hashedPassword = mkOpt (types.nullOr types.str) "$y$j9T$EkPXmsmIMFFZ.WRrBYCxS1$P0kwo6e4.WM5DsqUcEqWC3MrZp5KfCjxffraMFZWu06" "Hashed password for code-server authentication";
extraEnvironment = mkOpt (types.attrsOf types.str) { } "Extra environment variables for code-server";
reverseProxy = mkReverseProxyOpt;
}
// options;
};
default = { };
};
config = lib.mkIf cfg.enable defaultConfig;
};
# container
mkContainer =
{
name,
localAddress ? "127.0.0.1",
ports ? [ "80" ],
bindMounts ? { },
config ? { },
}:
{ lib, ... }:
{
containers.${name} = {
inherit localAddress bindMounts;
config = config // {
networking = {
firewall = {
enable = true;
allowedTCPPorts = ports;
};
# Use systemd-resolved inside the container
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
useHostResolvConf = lib.mkForce false;
};
services.resolved.enable = true;
system.stateVersion = "23.11";
};
autoStart = lib.mkDefault true;
privateNetwork = lib.mkDefault true;
hostAddress = lib.mkDefault "10.0.1.3";
};
networking = {
nat.forwardPorts = map (port: {
destination = lib.mkDefault "${localAddress}:${toString port}";
sourcePort = lib.mkDefault port;
}) ports;
firewall = {
allowedTCPPorts = ports;
allowedUDPPorts = ports;
};
};
};
# Migrated mjallen utilities
# Option creation helpers
mkOpt =
type: default: description:
mkOption { inherit type default description; };
mkOpt' = type: default: mkOpt type default null;
mkBoolOpt = mkOpt types.bool;
mkBoolOpt' = mkOpt' types.bool;
mkReverseProxyOpt = {
enable = mkBoolOpt false "Enable reverse proxy support";
subdomain = mkOpt types.str "" "subdomain of the service";
middlewares = mkOpt (types.listOf types.str) [ ] "List of middlewares to use";
};
# Standard enable/disable patterns
enabled = {
enable = true;
};
disabled = {
enable = false;
};
# String utilities
capitalize =
s:
let
len = stringLength s;
in
if len == 0 then "" else (toUpper (substring 0 1 s)) + (substring 1 len s);
# Boolean utilities
boolToNum = bool: if bool then 1 else 0;
# Attribute manipulation utilities
default-attrs = mapAttrs (_key: mkDefault);
force-attrs = mapAttrs (_key: mkForce);
nested-default-attrs = mapAttrs (_key: default-attrs);
nested-force-attrs = mapAttrs (_key: force-attrs);
}
// base64Lib