278 lines
7.6 KiB
Nix
278 lines
7.6 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,
|
|
serviceName ? name,
|
|
}:
|
|
let
|
|
cfg = config.${namespace}.${domain}.${name};
|
|
|
|
upstreamUrl =
|
|
if cfg.reverseProxy.upstreamUrl != null then
|
|
cfg.reverseProxy.upstreamUrl
|
|
else
|
|
"http://127.0.0.1:${toString cfg.port}";
|
|
|
|
fqdn = "${cfg.reverseProxy.subdomain}.${cfg.reverseProxy.domain}";
|
|
|
|
defaultConfig = {
|
|
# Caddy reverse proxy: when reverseProxy.enable = true, contribute this
|
|
# service's virtual host block to the Caddy config. The TLS wildcard
|
|
# cert is handled via a (cloudflare_tls) snippet defined in globalConfig.
|
|
# services.caddy.virtualHosts.${fqdn} = lib.mkIf cfg.reverseProxy.enable {
|
|
# extraConfig = ''
|
|
# import cloudflare_tls
|
|
# reverse_proxy ${upstreamUrl}
|
|
# ${cfg.reverseProxy.extraCaddyConfig}
|
|
# '';
|
|
# };
|
|
|
|
# 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} = { };
|
|
};
|
|
|
|
systemd.services.${serviceName} = {
|
|
requires = [
|
|
"media-nas-main.mount"
|
|
# "openvpn-us.protonvpn.udp.service"
|
|
];
|
|
after = lib.mkForce [
|
|
"media-nas-main.mount"
|
|
# "openvpn-us.protonvpn.udp.service"
|
|
];
|
|
# serviceConfig = {
|
|
# NetworkNamespacePath = lib.mkIf cfg.enableVpn "/run/netns/vpn";
|
|
# # Consider also setting DNS *inside* the netns (see note below).
|
|
# };
|
|
};
|
|
|
|
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
|
|
{ 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/appdata" "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";
|
|
|
|
enableVpn = mkBoolOpt true "Enable routing through VPN";
|
|
|
|
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 name;
|
|
}
|
|
// 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 = name: {
|
|
enable = mkBoolOpt false "Enable Caddy reverse proxy for this service";
|
|
|
|
subdomain = mkOpt types.str name "Subdomain for the service (default: service name)";
|
|
|
|
domain = mkOpt types.str "mjallen.dev" "Base domain for the reverse proxy";
|
|
|
|
# Override the upstream URL if the backend is not on localhost at cfg.port.
|
|
# Leave empty to use http://127.0.0.1:<port> automatically.
|
|
upstreamUrl =
|
|
mkOpt (types.nullOr types.str) null
|
|
"Override upstream URL (e.g. for services on a different host). Defaults to http://127.0.0.1:<port>.";
|
|
|
|
# Extra Caddyfile directives inserted inside the virtual host block.
|
|
extraCaddyConfig = mkOpt types.lines "" "Extra Caddyfile directives for this virtual host block";
|
|
};
|
|
|
|
# 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
|