style: alejandra $(fd -e nix)

This commit is contained in:
Kat Inskip 2024-03-13 15:08:42 -07:00
parent 97d9eecd3c
commit e63304937d
Signed by: kat
GPG key ID: 465E64DECEA8CF0F
91 changed files with 1422 additions and 1102 deletions

1
.gitignore vendored
View file

@ -6,3 +6,4 @@
.terraform .terraform
.DS_Store .DS_Store
.envrc.conf .envrc.conf
.idea

View file

@ -45,7 +45,7 @@ in {
cron = "0 0 * * *"; cron = "0 0 * * *";
} }
]; ];
workflow_dispatch = { }; workflow_dispatch = {};
}; };
}; };
@ -65,7 +65,7 @@ in {
displayName = "flake update build"; displayName = "flake update build";
environment = ["CACHIX_SIGNING_KEY" "GITHUB_REF"]; environment = ["CACHIX_SIGNING_KEY" "GITHUB_REF"];
command = let command = let
filteredHosts = [ "hakurei" "reimu" "aya" "tei" "litterbox" "mediabox" ]; filteredHosts = ["hakurei" "reimu" "aya" "tei" "litterbox" "mediabox"];
gcBetweenHosts = false; gcBetweenHosts = false;
nodeBuildString = concatMapStringsSep " && " (node: "nix build --show-trace -Lf . nixosConfigurations.${node}.config.system.build.toplevel -o result-${node}" + optionalString gcBetweenHosts " && nix-collect-garbage -d") filteredHosts; nodeBuildString = concatMapStringsSep " && " (node: "nix build --show-trace -Lf . nixosConfigurations.${node}.config.system.build.toplevel -o result-${node}" + optionalString gcBetweenHosts " && nix-collect-garbage -d") filteredHosts;
hostPath = builtins.getEnv "PATH"; hostPath = builtins.getEnv "PATH";

View file

@ -12,17 +12,19 @@
(hasSuffix ".adoc" path || baseNameOf path == "docinfo.html") (hasSuffix ".adoc" path || baseNameOf path == "docinfo.html")
|| type == "directory"; || type == "directory";
}; };
in stdenvNoCC.mkDerivation { in
stdenvNoCC.mkDerivation {
pname = "genso-docs"; pname = "genso-docs";
version = "dev"; version = "dev";
inherit src; inherit src;
ASCIIDOCTOR_OPTS = [ ASCIIDOCTOR_OPTS = [
"-a" "docinfo=shared" "-a"
"docinfo=shared"
]; ];
nativeBuildInputs = [ asciidoctor ]; nativeBuildInputs = [asciidoctor];
passAsFile = [ "buildCommand" ]; passAsFile = ["buildCommand"];
buildCommand = '' buildCommand = ''
install -d "$out" install -d "$out"
ASCIIDOCTOR_SRCS=( ASCIIDOCTOR_SRCS=(
@ -34,4 +36,4 @@ in stdenvNoCC.mkDerivation {
-a inc="$src/_inc/" \ -a inc="$src/_inc/" \
-b html -R "$src" -D "$out" "''${ASCIIDOCTOR_SRCS[@]}" -b html -R "$src" -D "$out" "''${ASCIIDOCTOR_SRCS[@]}"
''; '';
} }

View file

@ -10,16 +10,15 @@
templateUsers = filterAttrs (_: userIs "peeps") templateSystem.config.users.users; templateUsers = filterAttrs (_: userIs "peeps") templateSystem.config.users.users;
mkNodeUsers = users: let mkNodeUsers = users: let
nodeUsers = mapAttrsToList (_: mkNodeUser) templateUsers; nodeUsers = mapAttrsToList (_: mkNodeUser) templateUsers;
in sortOn (user: user.uid) nodeUsers; in
sortOn (user: user.uid) nodeUsers;
mkNodeUser = user: { mkNodeUser = user: {
inherit (user) name uid; inherit (user) name uid;
authorizedKeys = user.openssh.authorizedKeys.keys; authorizedKeys = user.openssh.authorizedKeys.keys;
}; };
mkNode = { mkNode = {name}: {
name,
}: {
users = mkNodeUsers templateUsers; users = mkNodeUsers templateUsers;
}; };
in { in {
reisen = mkNode { name = "reisen"; }; reisen = mkNode {name = "reisen";};
} }

View file

@ -11,7 +11,7 @@
inherit (config.services) tailscale; inherit (config.services) tailscale;
inherit (config) networking; inherit (config) networking;
cfg = config.networking.access; cfg = config.networking.access;
cidrModule = { config, ... }: { cidrModule = {config, ...}: {
options = with lib.types; { options = with lib.types; {
all = mkOption { all = mkOption {
type = listOf str; type = listOf str;
@ -19,11 +19,11 @@
}; };
v4 = mkOption { v4 = mkOption {
type = listOf str; type = listOf str;
default = [ ]; default = [];
}; };
v6 = mkOption { v6 = mkOption {
type = listOf str; type = listOf str;
default = [ ]; default = [];
}; };
}; };
config.all = mkOptionDefault ( config.all = mkOptionDefault (
@ -35,10 +35,12 @@ in {
options.networking.access = with lib.types; { options.networking.access = with lib.types; {
cidrForNetwork = mkOption { cidrForNetwork = mkOption {
type = attrsOf (submodule cidrModule); type = attrsOf (submodule cidrModule);
default = { }; default = {};
}; };
localaddrs = { localaddrs = {
enable = mkEnableOption "localaddrs" // { enable =
mkEnableOption "localaddrs"
// {
default = networking.firewall.interfaces.local.nftables.enable; default = networking.firewall.interfaces.local.nftables.enable;
}; };
stateDir = mkOption { stateDir = mkOption {
@ -88,7 +90,8 @@ in {
localaddrs = { localaddrs = {
nftablesInclude = mkBefore ('' nftablesInclude = mkBefore (''
define localrange6 = 2001:568::/29 define localrange6 = 2001:568::/29
'' + optionalString cfg.localaddrs.enable '' ''
+ optionalString cfg.localaddrs.enable ''
include "${cfg.localaddrs.stateDir}/*.nft" include "${cfg.localaddrs.stateDir}/*.nft"
''); '');
reloadScript = let reloadScript = let
@ -101,7 +104,7 @@ in {
}; };
moduleArgAttrs = { moduleArgAttrs = {
inherit (cfg) cidrForNetwork localaddrs; inherit (cfg) cidrForNetwork localaddrs;
mkSnakeOil = pkgs.callPackage ../../packages/snakeoil.nix { }; mkSnakeOil = pkgs.callPackage ../../packages/snakeoil.nix {};
}; };
}; };
@ -111,7 +114,8 @@ in {
interfaces.local = { interfaces.local = {
nftables.conditions = [ nftables.conditions = [
"ip saddr { ${concatStringsSep ", " cfg.cidrForNetwork.local.v4} }" "ip saddr { ${concatStringsSep ", " cfg.cidrForNetwork.local.v4} }"
(mkIf networking.enableIPv6 (
mkIf networking.enableIPv6
"ip6 saddr { $localrange6, ${concatStringsSep ", " cfg.cidrForNetwork.local.v6} }" "ip6 saddr { $localrange6, ${concatStringsSep ", " cfg.cidrForNetwork.local.v6} }"
) )
]; ];
@ -169,12 +173,12 @@ in {
in { in {
localaddrs = mkIf cfg.localaddrs.enable { localaddrs = mkIf cfg.localaddrs.enable {
unitConfig = { unitConfig = {
After = [ "network-online.target" ]; After = ["network-online.target"];
}; };
serviceConfig = rec { serviceConfig = rec {
StateDirectory = "localaddrs"; StateDirectory = "localaddrs";
ExecStart = mkMerge [ ExecStart = mkMerge [
[ "${localaddrs}" ] ["${localaddrs}"]
(mkIf networking.nftables.enable (mkAfter [ (mkIf networking.nftables.enable (mkAfter [
"${localaddrs-nftables}" "${localaddrs-nftables}"
])) ]))
@ -188,7 +192,7 @@ in {
}; };
}; };
nftables = mkIf (networking.nftables.enable && cfg.localaddrs.enable) rec { nftables = mkIf (networking.nftables.enable && cfg.localaddrs.enable) rec {
wants = [ "localaddrs.service" ]; wants = ["localaddrs.service"];
serviceConfig = { serviceConfig = {
ExecReload = mkBefore [ ExecReload = mkBefore [
"+${cfg.localaddrs.reloadScript}" "+${cfg.localaddrs.reloadScript}"
@ -196,7 +200,7 @@ in {
}; };
}; };
nginx = mkIf (config.services.nginx.enable && cfg.localaddrs.enable) rec { nginx = mkIf (config.services.nginx.enable && cfg.localaddrs.enable) rec {
wants = [ "localaddrs.service" ]; wants = ["localaddrs.service"];
after = wants; after = wants;
serviceConfig = { serviceConfig = {
ExecReload = mkBefore [ ExecReload = mkBefore [

View file

@ -1,48 +1,62 @@
{ pkgs, config, utils, lib, ... }: let {
pkgs,
config,
utils,
lib,
...
}: let
inherit (lib.attrsets) mapAttrsToList mapAttrs' nameValuePair filterAttrsRecursive; inherit (lib.attrsets) mapAttrsToList mapAttrs' nameValuePair filterAttrsRecursive;
inherit (lib.lists) singleton; inherit (lib.lists) singleton;
inherit (lib.modules) mkIf mkMerge mkForce; inherit (lib.modules) mkIf mkMerge mkForce;
inherit (lib.options) mkOption mkEnableOption; inherit (lib.options) mkOption mkEnableOption;
cfg = config.services.cloudflared; cfg = config.services.cloudflared;
settingsFormat = pkgs.formats.json { }; settingsFormat = pkgs.formats.json {};
in { in {
options.services.cloudflared = with lib.types; { options.services.cloudflared = with lib.types; {
tunnels = let tunnels = let
tunnelModule = { config, ... }: { tunnelModule = {config, ...}: {
options = { options = {
extraTunnel = { extraTunnel = {
enable = mkEnableOption "extra tunnels" // { enable =
default = config.extraTunnel.ingress != { }; mkEnableOption "extra tunnels"
// {
default = config.extraTunnel.ingress != {};
}; };
ingress = mkOption { ingress = mkOption {
inherit (settingsFormat) type; inherit (settingsFormat) type;
default = { }; default = {};
}; };
}; };
}; };
}; };
in mkOption { in
mkOption {
type = attrsOf (submodule tunnelModule); type = attrsOf (submodule tunnelModule);
}; };
}; };
config.systemd.services = let config.systemd.services = let
filterConfig = filterAttrsRecursive (_: v: ! builtins.elem v [ null [ ] { } ]); filterConfig = filterAttrsRecursive (_: v: ! builtins.elem v [null [] {}]);
mapIngress = hostname: ingress: { mapIngress = hostname: ingress:
{
inherit hostname; inherit hostname;
} // filterConfig (filterConfig ingress); }
in mkIf cfg.enable (mapAttrs' (uuid: tunnel: let // filterConfig (filterConfig ingress);
in
mkIf cfg.enable (mapAttrs' (uuid: tunnel: let
RuntimeDirectory = "cloudflared-tunnel-${uuid}"; RuntimeDirectory = "cloudflared-tunnel-${uuid}";
configPath = "/run/${RuntimeDirectory}/config.yml"; configPath = "/run/${RuntimeDirectory}/config.yml";
settings = { settings = {
tunnel = uuid; tunnel = uuid;
credentials-file = tunnel.credentialsFile; credentials-file = tunnel.credentialsFile;
ingress = mapAttrsToList mapIngress tunnel.ingress ingress =
mapAttrsToList mapIngress tunnel.ingress
++ mapAttrsToList mapIngress tunnel.extraTunnel.ingress ++ mapAttrsToList mapIngress tunnel.extraTunnel.ingress
++ singleton { service = tunnel.default; }; ++ singleton {service = tunnel.default;};
}; };
in nameValuePair "cloudflared-tunnel-${uuid}" (mkMerge [ in
nameValuePair "cloudflared-tunnel-${uuid}" (mkMerge [
{ {
after = mkIf config.services.tailscale.enable [ "tailscale-autoconnect.service" ]; after = mkIf config.services.tailscale.enable ["tailscale-autoconnect.service"];
serviceConfig = { serviceConfig = {
RestartSec = 10; RestartSec = 10;
}; };
@ -60,5 +74,6 @@ in {
]; ];
}; };
}) })
])) cfg.tunnels); ]))
cfg.tunnels);
} }

View file

@ -11,7 +11,7 @@
cfg = config.services.github-runners; cfg = config.services.github-runners;
nixosConfig = config; nixosConfig = config;
enabledRunners = filterAttrs (_: runner: runner.enable) cfg; enabledRunners = filterAttrs (_: runner: runner.enable) cfg;
runnerModule = { config, ... }: { runnerModule = {config, ...}: {
options = with lib.types; { options = with lib.types; {
networkNamespace.name = mkOption { networkNamespace.name = mkOption {
type = nullOr str; type = nullOr str;
@ -19,7 +19,7 @@
}; };
serviceSettings = mkOption { serviceSettings = mkOption {
type = unmerged.type; type = unmerged.type;
default = { }; default = {};
}; };
}; };
config = { config = {
@ -58,8 +58,10 @@ in {
}; };
}; };
config = { config = {
systemd.services = mapAttrs' (name: runner: nameValuePair "github-runner-${name}" ( systemd.services = mapAttrs' (name: runner:
nameValuePair "github-runner-${name}" (
unmerged.merge runner.serviceSettings unmerged.merge runner.serviceSettings
)) enabledRunners; ))
enabledRunners;
}; };
} }

View file

@ -17,27 +17,41 @@ in {
default = config.networking.domain; default = config.networking.domain;
}; };
homekit = { homekit = {
enable = mkEnableOption "homekit" // { enable =
default = cfg.config.homekit or [ ] != [ ]; mkEnableOption "homekit"
// {
default = cfg.config.homekit or [] != [];
}; };
openFirewall = mkEnableOption "homekit ports" // { openFirewall =
mkEnableOption "homekit ports"
// {
default = cfg.openFirewall; default = cfg.openFirewall;
}; };
}; };
googleAssistant.enable = mkEnableOption "Google Assistant" // { googleAssistant.enable =
default = cfg.config.google_assistant or { } != { }; mkEnableOption "Google Assistant"
// {
default = cfg.config.google_assistant or {} != {};
}; };
androidTv.enable = mkEnableOption "Android TV" // { androidTv.enable =
mkEnableOption "Android TV"
// {
default = elem "androidtv" cfg.extraComponents; default = elem "androidtv" cfg.extraComponents;
}; };
brother.enable = mkEnableOption "brother" // { brother.enable =
mkEnableOption "brother"
// {
default = elem "brother" cfg.extraComponents; default = elem "brother" cfg.extraComponents;
}; };
cast = { cast = {
enable = mkEnableOption "Chromecast" // { enable =
mkEnableOption "Chromecast"
// {
default = elem "cast" cfg.extraComponents; default = elem "cast" cfg.extraComponents;
}; };
openFirewall = mkEnableOption "Chromecast ports" // { openFirewall =
mkEnableOption "Chromecast ports"
// {
default = cfg.openFirewall; default = cfg.openFirewall;
}; };
}; };
@ -50,7 +64,7 @@ in {
config = { config = {
networking.firewall = let networking.firewall = let
homekitTcp = mkIf cfg.homekit.enable ( homekitTcp = mkIf cfg.homekit.enable (
map ({ port, ... }: port) cfg.config.homekit or [ ] map ({port, ...}: port) cfg.config.homekit or []
); );
castUdpRanges = mkIf cfg.cast.enable [ castUdpRanges = mkIf cfg.cast.enable [
@ -59,7 +73,8 @@ in {
to = 60999; to = 60999;
} }
]; ];
in mkIf cfg.enable { in
mkIf cfg.enable {
interfaces.local = { interfaces.local = {
allowedTCPPorts = mkIf (!cfg.homekit.openFirewall) homekitTcp; allowedTCPPorts = mkIf (!cfg.homekit.openFirewall) homekitTcp;
allowedUDPPortRanges = mkIf (!cfg.cast.openFirewall) castUdpRanges; allowedUDPPortRanges = mkIf (!cfg.cast.openFirewall) castUdpRanges;
@ -72,8 +87,9 @@ in {
services.avahi = mkIf (cfg.enable && cfg.homekit.enable) { services.avahi = mkIf (cfg.enable && cfg.homekit.enable) {
enable = mkDefault true; enable = mkDefault true;
publish.enable = let publish.enable = let
homekitNames = map (homekit: toLower homekit.name) cfg.config.homekit or [ ]; homekitNames = map (homekit: toLower homekit.name) cfg.config.homekit or [];
in mkIf (elem config.networking.hostName homekitNames) false; in
mkIf (elem config.networking.hostName homekitNames) false;
}; };
systemd.services.home-assistant = mkIf (cfg.enable && cfg.mutableUiConfig) { systemd.services.home-assistant = mkIf (cfg.enable && cfg.mutableUiConfig) {
@ -101,7 +117,8 @@ in {
use_x_forwarded_for = "true"; use_x_forwarded_for = "true";
trusted_proxies = let trusted_proxies = let
inherit (config.networking.access) cidrForNetwork; inherit (config.networking.access) cidrForNetwork;
in cidrForNetwork.loopback.all in
cidrForNetwork.loopback.all
++ cidrForNetwork.local.all ++ cidrForNetwork.local.all
++ optionals config.services.tailscale.enable cidrForNetwork.tail.all ++ optionals config.services.tailscale.enable cidrForNetwork.tail.all
++ [ ++ [
@ -157,30 +174,40 @@ in {
package = let package = let
inherit (cfg.package) python; inherit (cfg.package) python;
# https://github.com/pysnmp/pysnmp/issues/51 # https://github.com/pysnmp/pysnmp/issues/51
needsPyasn1pin = if lib.versionOlder python.pkgs.pysnmplib.version "6.0" needsPyasn1pin =
if lib.versionOlder python.pkgs.pysnmplib.version "6.0"
then true then true
else lib.warn "pyasn1 pin likely no longer needed" false; else lib.warn "pyasn1 pin likely no longer needed" false;
pyasn1prefix = "${python.pkgs.pysnmp-pyasn1}/${python.sitePackages}"; pyasn1prefix = "${python.pkgs.pysnmp-pyasn1}/${python.sitePackages}";
home-assistant = pkgs.home-assistant.override { home-assistant = pkgs.home-assistant.override {
packageOverrides = self: super: { packageOverrides = self: super: {
brother = super.brother.overridePythonAttrs (old: { brother = super.brother.overridePythonAttrs (old: {
dontCheckRuntimeDeps = if old.dontCheckRuntimeDeps or false dontCheckRuntimeDeps =
if old.dontCheckRuntimeDeps or false
then lib.warn "brother override no longer needed" true then lib.warn "brother override no longer needed" true
else true; else true;
}); });
mpd2 = super.mpd2.overridePythonAttrs (old: { mpd2 = super.mpd2.overridePythonAttrs (old: {
patches = old.patches or [ ] ++ [ patches =
old.patches
or []
++ [
../../packages/mpd2-skip-flaky-test.patch ../../packages/mpd2-skip-flaky-test.patch
]; ];
disabledTests = unique (old.disabledTests or [ ] ++ [ disabledTests = unique (old.disabledTests
or []
++ [
"test_idle_timeout" "test_idle_timeout"
]); ]);
}); });
}; };
}; };
in home-assistant.overrideAttrs (old: { in
home-assistant.overrideAttrs (old: {
makeWrapperArgs = old.makeWrapperArgs ++ optional (cfg.brother.enable && needsPyasn1pin) "--prefix PYTHONPATH : ${pyasn1prefix}"; makeWrapperArgs = old.makeWrapperArgs ++ optional (cfg.brother.enable && needsPyasn1pin) "--prefix PYTHONPATH : ${pyasn1prefix}";
disabledTests = unique (old.disabledTests or [ ] ++ [ disabledTests = unique (old.disabledTests
or []
++ [
"test_check_config" "test_check_config"
]); ]);
}); });
@ -189,14 +216,18 @@ in {
inherit (lib.lists) head; inherit (lib.lists) head;
inherit (lib.attrsets) attrNames filterAttrs; inherit (lib.attrsets) attrNames filterAttrs;
inherit (config.systemd.services.home-assistant.serviceConfig) ExecStart; inherit (config.systemd.services.home-assistant.serviceConfig) ExecStart;
isHassDrv = drv: context: hasSuffix "-${cfg.package.name}.drv" drv && context.outputs or [ ] == [ "out" ]; isHassDrv = drv: context: hasSuffix "-${cfg.package.name}.drv" drv && context.outputs or [] == ["out"];
drvs = filterAttrs isHassDrv (builtins.getContext ExecStart); drvs = filterAttrs isHassDrv (builtins.getContext ExecStart);
isImpure = builtins ? currentSystem; isImpure = builtins ? currentSystem;
in mkIf cfg.enable (mkOptionDefault ( in
if isImpure then import (head (attrNames drvs)) mkIf cfg.enable (mkOptionDefault (
if isImpure
then import (head (attrNames drvs))
else removeSuffix "/bin/hass" (head (splitString " " ExecStart)) else removeSuffix "/bin/hass" (head (splitString " " ExecStart))
)); ));
extraPackages = python3Packages: with python3Packages; mkMerge [ extraPackages = python3Packages:
with python3Packages;
mkMerge [
[ [
psycopg2 psycopg2
securetar securetar
@ -232,8 +263,8 @@ in {
"google_assistant" "google_assistant"
"google_cloud" "google_cloud"
]) ])
(map ({ platform, ... }: platform) cfg.config.media_player or [ ]) (map ({platform, ...}: platform) cfg.config.media_player or [])
(map ({ platform, ... }: platform) cfg.config.tts or [ ]) (map ({platform, ...}: platform) cfg.config.tts or [])
]; ];
}; };
} }

View file

@ -1,7 +1,4 @@
{ {lib, ...}: let
lib,
...
}: let
inherit (lib.options) mkOption; inherit (lib.options) mkOption;
in { in {
options.services.jackett = with lib.types; { options.services.jackett = with lib.types; {

View file

@ -60,13 +60,14 @@ in {
services.kanidm = { services.kanidm = {
server.unencrypted = { server.unencrypted = {
domain = mkBefore [ cfg.server.frontend.domain ]; domain = mkBefore [cfg.server.frontend.domain];
package = let package = let
cert = mkSnakeOil { cert = mkSnakeOil {
name = "kanidm-cert"; name = "kanidm-cert";
inherit (cfg.server.unencrypted) domain; inherit (cfg.server.unencrypted) domain;
}; };
in mkOptionDefault cert; in
mkOptionDefault cert;
}; };
clientSettings = mkIf cfg.enableServer { clientSettings = mkIf cfg.enableServer {
uri = mkDefault cfg.serverSettings.origin; uri = mkDefault cfg.serverSettings.origin;

View file

@ -1,7 +1,4 @@
{ {lib, ...}: let
lib,
...
}: let
inherit (lib.options) mkOption; inherit (lib.options) mkOption;
in { in {
options.services.lidarr = with lib.types; { options.services.lidarr = with lib.types; {

View file

@ -8,7 +8,7 @@
inherit (lib.modules) mkIf mkMerge mkDefault mkOptionDefault; inherit (lib.modules) mkIf mkMerge mkDefault mkOptionDefault;
inherit (lib.lists) singleton; inherit (lib.lists) singleton;
cfg = config.services.mediatomb; cfg = config.services.mediatomb;
mediaDirModule = { config, ... }: { mediaDirModule = {config, ...}: {
options = with lib.types; { options = with lib.types; {
mountPoint = mkOption { mountPoint = mkOption {
type = nullOr str; type = nullOr str;
@ -26,14 +26,21 @@
paths = let paths = let
paths = map (path: "${config.path}/${path}") config.subdirectories; paths = map (path: "${config.path}/${path}") config.subdirectories;
path = singleton config.path; path = singleton config.path;
in mkOptionDefault (if config.subdirectories != null then paths else path); in
mkOptionDefault (
if config.subdirectories != null
then paths
else path
);
recursive = mkDefault true; recursive = mkDefault true;
hidden-files = mkDefault false; hidden-files = mkDefault false;
}; };
}; };
in { in {
options.services.mediatomb = with lib.types; { options.services.mediatomb = with lib.types; {
confine = mkEnableOption "containment" // { confine =
mkEnableOption "containment"
// {
default = true; default = true;
}; };
mediaDirectories = mkOption { mediaDirectories = mkOption {
@ -47,9 +54,13 @@ in {
}; };
config.systemd.services.mediatomb = mkIf cfg.enable { config.systemd.services.mediatomb = mkIf cfg.enable {
confinement.enable = mkIf cfg.confine (mkDefault true); confinement.enable = mkIf cfg.confine (mkDefault true);
bindsTo = map (dir: mkIf (dir.mountPoint != null) bindsTo =
map (
dir:
mkIf (dir.mountPoint != null)
"${utils.escapeSystemdPath dir.mountPoint}.mount" "${utils.escapeSystemdPath dir.mountPoint}.mount"
) cfg.mediaDirectories; )
cfg.mediaDirectories;
unitConfig.RequiresMountsFor = mkMerge ( unitConfig.RequiresMountsFor = mkMerge (
map (dir: dir.paths) cfg.mediaDirectories map (dir: dir.paths) cfg.mediaDirectories
); );

View file

@ -8,18 +8,19 @@
in { in {
options.services.mosquitto = with lib.types; { options.services.mosquitto = with lib.types; {
listeners = let listeners = let
listenerModule = { ... }: { listenerModule = {...}: {
options = { options = {
openFirewall = mkEnableOption "firewall"; openFirewall = mkEnableOption "firewall";
}; };
}; };
in mkOption { in
mkOption {
type = listOf (submodule listenerModule); type = listOf (submodule listenerModule);
}; };
}; };
config = { config = {
networking.firewall.allowedTCPPorts = mkIf cfg.enable (mkMerge ( networking.firewall.allowedTCPPorts = mkIf cfg.enable (mkMerge (
map (listener: mkIf listener.openFirewall [ listener.port ]) cfg.listeners map (listener: mkIf listener.openFirewall [listener.port]) cfg.listeners
)); ));
}; };
} }

View file

@ -19,7 +19,12 @@
enabledNamespaces = filter (ns: ns.enable) (attrValues networking.namespaces); enabledNamespaces = filter (ns: ns.enable) (attrValues networking.namespaces);
ip = "${pkgs.iproute2}/bin/ip"; ip = "${pkgs.iproute2}/bin/ip";
ip-n = namespace: "${ip} -n ${escapeShellArg namespace.name}"; ip-n = namespace: "${ip} -n ${escapeShellArg namespace.name}";
namespaceInterfaceModule = { config, namespace, name, ... }: { namespaceInterfaceModule = {
config,
namespace,
name,
...
}: {
options = with lib.types; { options = with lib.types; {
name = mkOption { name = mkOption {
type = str; type = str;
@ -41,8 +46,8 @@
}; };
config = { config = {
serviceSettings = rec { serviceSettings = rec {
bindsTo = [ "${namespace.unitName}.service" ]; bindsTo = ["${namespace.unitName}.service"];
partOf = [ "${namespace.unitName}.target" ]; partOf = ["${namespace.unitName}.target"];
after = bindsTo; after = bindsTo;
stopIfChanged = false; stopIfChanged = false;
restartIfChanged = false; restartIfChanged = false;
@ -63,7 +68,11 @@
}; };
}; };
}; };
groupModule = { config, namespace, ... }: { groupModule = {
config,
namespace,
...
}: {
options = with lib.types; { options = with lib.types; {
id = mkOption { id = mkOption {
type = int; type = int;
@ -78,8 +87,8 @@
}; };
config = { config = {
serviceSettings = rec { serviceSettings = rec {
bindsTo = [ "${namespace.unitName}.service" ]; bindsTo = ["${namespace.unitName}.service"];
partOf = [ "${namespace.unitName}.target" ]; partOf = ["${namespace.unitName}.target"];
after = bindsTo; after = bindsTo;
stopIfChanged = false; stopIfChanged = false;
restartIfChanged = false; restartIfChanged = false;
@ -100,15 +109,21 @@
}; };
}; };
}; };
namespaceModule = { config, name, ... }: let namespaceModule = {
config,
name,
...
}: let
linkGroupServices = optional (config.linkGroup != null) "${config.linkGroup.serviceName}.service"; linkGroupServices = optional (config.linkGroup != null) "${config.linkGroup.serviceName}.service";
interfaceServices = mapAttrsToList (_: interface: "${interface.serviceName}.service") config.interfaces; interfaceServices = mapAttrsToList (_: interface: "${interface.serviceName}.service") config.interfaces;
submoduleArgs = { ... }: { submoduleArgs = {...}: {
config._module.args.namespace = config; config._module.args.namespace = config;
}; };
in { in {
options = with lib.types; { options = with lib.types; {
enable = mkEnableOption "network namespace" // { enable =
mkEnableOption "network namespace"
// {
default = true; default = true;
}; };
resolvConf = mkOption { resolvConf = mkOption {
@ -186,8 +201,9 @@
groupModule groupModule
submoduleArgs submoduleArgs
]; ];
idOrModule = coercedTo int (id: { inherit id; }) module; idOrModule = coercedTo int (id: {inherit id;}) module;
in nullOr idOrModule; in
nullOr idOrModule;
default = null; default = null;
}; };
interfaces = mkOption { interfaces = mkOption {
@ -195,7 +211,7 @@
namespaceInterfaceModule namespaceInterfaceModule
submoduleArgs submoduleArgs
]); ]);
default = { }; default = {};
}; };
path = mkOption { path = mkOption {
type = path; type = path;
@ -226,8 +242,8 @@
}; };
config = { config = {
serviceSettings = { serviceSettings = {
wants = [ "network.target" ]; wants = ["network.target"];
after = [ "network.target" ]; after = ["network.target"];
stopIfChanged = false; stopIfChanged = false;
restartIfChanged = false; restartIfChanged = false;
serviceConfig = { serviceConfig = {
@ -245,12 +261,12 @@
}; };
}; };
targetSettings = { targetSettings = {
wantedBy = [ "multi-user.target" ]; wantedBy = ["multi-user.target"];
bindsTo = [ "${config.unitName}.service" ]; bindsTo = ["${config.unitName}.service"];
requires = linkGroupServices ++ interfaceServices; requires = linkGroupServices ++ interfaceServices;
wants = mkMerge [ wants = mkMerge [
(mkIf config.dhcpcd.enable [ "${config.dhcpcd.serviceName}.service" ]) (mkIf config.dhcpcd.enable ["${config.dhcpcd.serviceName}.service"])
(mkIf config.nftables.enable [ "${config.nftables.serviceName}.service" ]) (mkIf config.nftables.enable ["${config.nftables.serviceName}.service"])
]; ];
}; };
configFiles = { configFiles = {
@ -312,7 +328,8 @@
addrs6 = access.cidrForNetwork.local.v6 ++ optionals tailscale.enable access.cidrForNetwork.tail.v6; addrs6 = access.cidrForNetwork.local.v6 ++ optionals tailscale.enable access.cidrForNetwork.tail.v6;
daddr4 = ''{ ${concatStringsSep ", " addrs4} }''; daddr4 = ''{ ${concatStringsSep ", " addrs4} }'';
daddr6 = ''{ ${concatStringsSep ", " addrs6} }''; daddr6 = ''{ ${concatStringsSep ", " addrs6} }'';
in mkIf config.nftables.rejectLocaladdrs (mkMerge [ in
mkIf config.nftables.rejectLocaladdrs (mkMerge [
''ct state { established, related } accept'' ''ct state { established, related } accept''
'' ''
ip daddr ${daddr4} ip protocol tcp reject with tcp reset ip daddr ${daddr4} ip protocol tcp reject with tcp reset
@ -324,9 +341,9 @@
'') '')
]); ]);
serviceSettings = rec { serviceSettings = rec {
bindsTo = [ "${config.unitName}.service" ]; bindsTo = ["${config.unitName}.service"];
partOf = [ "${config.unitName}.target" ]; partOf = ["${config.unitName}.target"];
wants = mkIf config.nftables.rejectLocaladdrs [ "localaddrs.service" ]; wants = mkIf config.nftables.rejectLocaladdrs ["localaddrs.service"];
after = mkMerge [ after = mkMerge [
bindsTo bindsTo
wants wants
@ -346,7 +363,7 @@
"${pkgs.nftables}/bin/nft -f ${config.configPath}/rules.nft" "${pkgs.nftables}/bin/nft -f ${config.configPath}/rules.nft"
]; ];
ExecReload = mkMerge [ ExecReload = mkMerge [
(mkIf config.nftables.rejectLocaladdrs [ "+${access.localaddrs.reloadScript}" ]) (mkIf config.nftables.rejectLocaladdrs ["+${access.localaddrs.reloadScript}"])
[ [
"${pkgs.nftables}/bin/nft flush ruleset" "${pkgs.nftables}/bin/nft flush ruleset"
"${pkgs.nftables}/bin/nft -f ${config.configPath}/rules.nft" "${pkgs.nftables}/bin/nft -f ${config.configPath}/rules.nft"
@ -360,10 +377,13 @@
}; };
dhcpcd = { dhcpcd = {
serviceSettings = rec { serviceSettings = rec {
bindsTo = [ "${config.unitName}.service" ]; bindsTo = ["${config.unitName}.service"];
partOf = [ "${config.unitName}.target" ]; partOf = ["${config.unitName}.target"];
wants = linkGroupServices ++ interfaceServices; wants = linkGroupServices ++ interfaceServices;
after = bindsTo ++ wants ++ [ after =
bindsTo
++ wants
++ [
(mkIf config.nftables.enable "${config.nftables.serviceName}.service") (mkIf config.nftables.enable "${config.nftables.serviceName}.service")
]; ];
stopIfChanged = false; stopIfChanged = false;
@ -407,13 +427,19 @@
}; };
}; };
}; };
serviceModule = { config, name, ... }: let serviceModule = {
config,
name,
...
}: let
cfg = config.networkNamespace; cfg = config.networkNamespace;
hasNs = cfg.name != null; hasNs = cfg.name != null;
ns = networking.namespaces.${cfg.name}; ns = networking.namespaces.${cfg.name};
in { in {
options.networkNamespace = with lib.types; { options.networkNamespace = with lib.types; {
enable = mkEnableOption "netns" // { enable =
mkEnableOption "netns"
// {
default = cfg.name != null; default = cfg.name != null;
}; };
bindResolvConf = mkOption { bindResolvConf = mkOption {
@ -446,15 +472,13 @@
path = mkDefault ( path = mkDefault (
ns.path ns.path
); );
bindResolvConf = mkDefault ( bindResolvConf = mkDefault "${ns.configPath}/resolv.conf";
"${ns.configPath}/resolv.conf"
);
}) })
]; ];
} }
(mkIf cfg.enable rec { (mkIf cfg.enable rec {
wants = mkIf hasNs [ "${ns.unitName}.target" ]; wants = mkIf hasNs ["${ns.unitName}.target"];
bindsTo = mkIf hasNs [ "${ns.unitName}.service" ]; bindsTo = mkIf hasNs ["${ns.unitName}.service"];
after = mkMerge [ after = mkMerge [
bindsTo bindsTo
(mkIf (hasNs && cfg.afterOnline) [ (mkIf (hasNs && cfg.afterOnline) [
@ -475,7 +499,7 @@ in {
options = with lib.types; { options = with lib.types; {
networking.namespaces = mkOption { networking.namespaces = mkOption {
type = attrsOf (submodule namespaceModule); type = attrsOf (submodule namespaceModule);
default = { }; default = {};
}; };
systemd.services = mkOption { systemd.services = mkOption {
type = attrsOf (submodule serviceModule); type = attrsOf (submodule serviceModule);
@ -483,19 +507,25 @@ in {
}; };
config = { config = {
systemd = { systemd = {
services = listToAttrs (concatMap (ns: services = listToAttrs (concatMap (
ns:
singleton (nameValuePair ns.unitName (unmerged.merge ns.serviceSettings)) singleton (nameValuePair ns.unitName (unmerged.merge ns.serviceSettings))
++ optional (ns.linkGroup != null) (nameValuePair ns.linkGroup.serviceName (unmerged.merge ns.linkGroup.serviceSettings)) ++ optional (ns.linkGroup != null) (nameValuePair ns.linkGroup.serviceName (unmerged.merge ns.linkGroup.serviceSettings))
++ mapAttrsToList (_: interface: nameValuePair interface.serviceName (unmerged.merge interface.serviceSettings)) ns.interfaces ++ mapAttrsToList (_: interface: nameValuePair interface.serviceName (unmerged.merge interface.serviceSettings)) ns.interfaces
++ optional ns.dhcpcd.enable (nameValuePair ns.dhcpcd.serviceName (unmerged.merge ns.dhcpcd.serviceSettings)) ++ optional ns.dhcpcd.enable (nameValuePair ns.dhcpcd.serviceName (unmerged.merge ns.dhcpcd.serviceSettings))
++ optional ns.nftables.enable (nameValuePair ns.nftables.serviceName (unmerged.merge ns.nftables.serviceSettings)) ++ optional ns.nftables.enable (nameValuePair ns.nftables.serviceName (unmerged.merge ns.nftables.serviceSettings))
) enabledNamespaces); )
targets = listToAttrs (map (ns: nameValuePair ns.unitName ( enabledNamespaces);
targets = listToAttrs (map (ns:
nameValuePair ns.unitName (
unmerged.merge ns.targetSettings unmerged.merge ns.targetSettings
)) enabledNamespaces); ))
enabledNamespaces);
}; };
environment.etc = mkMerge (map (ns: environment.etc = mkMerge (map (
ns:
mapAttrs' (name: file: nameValuePair "${ns.configDir}/${name}" (unmerged.merge file)) ns.configFiles mapAttrs' (name: file: nameValuePair "${ns.configDir}/${name}" (unmerged.merge file)) ns.configFiles
) enabledNamespaces); )
enabledNamespaces);
}; };
} }

View file

@ -8,15 +8,19 @@
inherit (lib.modules) mkIf mkMerge mkOptionDefault; inherit (lib.modules) mkIf mkMerge mkOptionDefault;
inherit (inputs.self.lib.lib) eui64; inherit (inputs.self.lib.lib) eui64;
inherit (config) networking services; inherit (config) networking services;
networkModule = { config, ... }: { networkModule = {config, ...}: {
options = with lib.types; { options = with lib.types; {
mdns = { mdns = {
enable = mkEnableOption "SLAAC" // { enable =
mkEnableOption "SLAAC"
// {
default = config.matchConfig.Type or null == "ether" && services.resolved.enable; default = config.matchConfig.Type or null == "ether" && services.resolved.enable;
}; };
}; };
slaac = { slaac = {
enable = mkEnableOption "SLAAC" // { enable =
mkEnableOption "SLAAC"
// {
default = config.matchConfig.Type or null == "ether" && networking.enableIPv6; default = config.matchConfig.Type or null == "ether" && networking.enableIPv6;
}; };
postfix = mkOption { postfix = mkOption {

View file

@ -1,6 +1,8 @@
{ lib, config, ... }: {
lib,
let config,
...
}: let
inherit (lib) types; inherit (lib) types;
inherit (lib.options) mkOption mkEnableOption; inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf; inherit (lib.modules) mkIf;
@ -13,9 +15,11 @@ let
doDocker = config.virtualisation.docker.enable && cfg.generateDockerRules; doDocker = config.virtualisation.docker.enable && cfg.generateDockerRules;
mkPorts = cond: ports: ranges: action: let mkPorts = cond: ports: ranges: action: let
portStrings = (map (range: "${toString range.from}-${toString range.to}") ranges) portStrings =
(map (range: "${toString range.from}-${toString range.to}") ranges)
++ (map toString ports); ++ (map toString ports);
in optionalString (portStrings != []) '' in
optionalString (portStrings != []) ''
${cond} dport { ${concatStringsSep "," portStrings} } ${action} ${cond} dport { ${concatStringsSep "," portStrings} } ${action}
''; '';
@ -39,10 +43,13 @@ let
${mkPorts "udp" fwcfg.allowedUDPPorts fwcfg.allowedUDPPortRanges "accept"} ${mkPorts "udp" fwcfg.allowedUDPPorts fwcfg.allowedUDPPortRanges "accept"}
${ ${
concatStringsSep "\n" (mapAttrsToList (name: ifcfg: concatMapStringsSep "\n" (cond: concatStringsSep "\n" (mapAttrsToList (name: ifcfg:
concatMapStringsSep "\n" (
cond:
mkPorts "${cond} tcp" ifcfg.allowedTCPPorts ifcfg.allowedTCPPortRanges "accept" mkPorts "${cond} tcp" ifcfg.allowedTCPPorts ifcfg.allowedTCPPortRanges "accept"
+ mkPorts "${cond} udp" ifcfg.allowedUDPPorts ifcfg.allowedUDPPortRanges "accept" + mkPorts "${cond} udp" ifcfg.allowedUDPPorts ifcfg.allowedUDPPortRanges "accept"
) (optionals ifcfg.nftables.enable ifcfg.nftables.conditions)) fwcfg.interfaces) ) (optionals ifcfg.nftables.enable ifcfg.nftables.conditions))
fwcfg.interfaces)
} }
# DHCPv6 # DHCPv6
@ -85,13 +92,22 @@ let
''} ''}
${cfg.extraConfig} ${cfg.extraConfig}
''; '';
interfaceModule = { config, name, ... }: { interfaceModule = {
config,
name,
...
}: {
options = { options = {
nftables = { nftables = {
enable = mkEnableOption "nftables firewall" // { enable =
mkEnableOption "nftables firewall"
// {
default = default =
config.allowedTCPPorts != [ ] || config.allowedTCPPortRanges != [ ] config.allowedTCPPorts
|| config.allowedUDPPorts != [ ] || config.allowedUDPPortRanges != [ ]; != []
|| config.allowedTCPPortRanges != []
|| config.allowedUDPPorts != []
|| config.allowedUDPPortRanges != [];
}; };
conditions = mkOption { conditions = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
@ -100,7 +116,6 @@ let
}; };
}; };
}; };
in { in {
options = { options = {
networking.nftables = { networking.nftables = {

View file

@ -9,7 +9,7 @@
inherit (lib.lists) optionals; inherit (lib.lists) optionals;
inherit (config.services) tailscale; inherit (config.services) tailscale;
inherit (config.networking.access) cidrForNetwork localaddrs; inherit (config.networking.access) cidrForNetwork localaddrs;
localModule = { config, ... }: { localModule = {config, ...}: {
options.local = with lib.types; { options.local = with lib.types; {
enable = mkOption { enable = mkOption {
type = bool; type = bool;
@ -37,16 +37,23 @@
cidrForNetwork.loopback.all cidrForNetwork.loopback.all
++ cidrForNetwork.local.all ++ cidrForNetwork.local.all
++ optionals tailscale.enable cidrForNetwork.tail.all; ++ optionals tailscale.enable cidrForNetwork.tail.all;
allows = concatMapStringsSep "\n" mkAllow allowAddresses + optionalString localaddrs.enable '' allows =
concatMapStringsSep "\n" mkAllow allowAddresses
+ optionalString localaddrs.enable ''
include ${localaddrs.stateDir}/*.nginx.conf; include ${localaddrs.stateDir}/*.nginx.conf;
''; '';
in mkBefore '' in
mkBefore ''
${allows} ${allows}
deny all; deny all;
''; '';
}; };
}; };
locationModule = { config, virtualHost, ... }: { locationModule = {
config,
virtualHost,
...
}: {
imports = [ imports = [
localModule localModule
]; ];
@ -58,13 +65,13 @@
emitDenyGlobal = virtualHost.local.emitDenyGlobal; emitDenyGlobal = virtualHost.local.emitDenyGlobal;
}; };
}; };
hostModule = { config, ... }: { hostModule = {config, ...}: {
imports = [ localModule ]; imports = [localModule];
options = with lib.types; { options = with lib.types; {
locations = mkOption { locations = mkOption {
type = attrsOf (submoduleWith { type = attrsOf (submoduleWith {
modules = [ locationModule ]; modules = [locationModule];
shorthandOnlyDefinesConfig = true; shorthandOnlyDefinesConfig = true;
specialArgs = { specialArgs = {
virtualHost = config; virtualHost = config;
@ -83,7 +90,7 @@ in {
options = with lib.types; { options = with lib.types; {
services.nginx.virtualHosts = mkOption { services.nginx.virtualHosts = mkOption {
type = attrsOf (submoduleWith { type = attrsOf (submoduleWith {
modules = [ hostModule ]; modules = [hostModule];
shorthandOnlyDefinesConfig = true; shorthandOnlyDefinesConfig = true;
specialArgs = { specialArgs = {
nixosConfig = config; nixosConfig = config;

View file

@ -2,13 +2,12 @@
config, config,
lib, lib,
... ...
}: }: let
let
inherit (lib.options) mkOption mkEnableOption; inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf mkMerge mkBefore mkDefault; inherit (lib.modules) mkIf mkMerge mkBefore mkDefault;
inherit (config) networking; inherit (config) networking;
inherit (config.services) vouch-proxy tailscale; inherit (config.services) vouch-proxy tailscale;
vouchModule = { config, ... }: { vouchModule = {config, ...}: {
options = with lib.types; { options = with lib.types; {
vouch = { vouch = {
enable = mkEnableOption "vouch auth proxy"; enable = mkEnableOption "vouch auth proxy";
@ -49,15 +48,20 @@ let
vouch = mkIf vouch-proxy.enable { vouch = mkIf vouch-proxy.enable {
proxyOrigin = let proxyOrigin = let
inherit (vouch-proxy.settings.vouch) listen port; inherit (vouch-proxy.settings.vouch) listen port;
host = if listen == "0.0.0.0" || listen == "[::]" then "localhost" else listen; host =
in mkDefault "http://${host}:${toString port}"; if listen == "0.0.0.0" || listen == "[::]"
then "localhost"
else listen;
in
mkDefault "http://${host}:${toString port}";
authUrl = mkDefault vouch-proxy.authUrl; authUrl = mkDefault vouch-proxy.authUrl;
url = mkDefault vouch-proxy.url; url = mkDefault vouch-proxy.url;
doubleProxy = mkDefault false; doubleProxy = mkDefault false;
}; };
} }
{ {
vouch.proxyOrigin = mkIf (tailscale.enable && !vouch-proxy.enable) (mkDefault vouch.proxyOrigin = mkIf (tailscale.enable && !vouch-proxy.enable) (
mkDefault
"http://login.tail.${networking.domain}" "http://login.tail.${networking.domain}"
); );
} }
@ -96,7 +100,8 @@ let
set $vouch_url $vouch_scheme://${config.vouch.tailDomain}; set $vouch_url $vouch_scheme://${config.vouch.tailDomain};
} }
''; '';
in mkMerge [ in
mkMerge [
(mkBefore '' (mkBefore ''
set $vouch_url ${config.vouch.url}; set $vouch_url ${config.vouch.url};
set $vouch_scheme $scheme; set $vouch_scheme $scheme;

View file

@ -1,10 +1,7 @@
{ {lib, ...}: let
lib,
...
}: let
inherit (lib.modules) mkIf; inherit (lib.modules) mkIf;
inherit (lib.options) mkOption mkEnableOption; inherit (lib.options) mkOption mkEnableOption;
wsModule = { config, ... }: { wsModule = {config, ...}: {
options = with lib.types; { options = with lib.types; {
proxy.websocket.enable = mkEnableOption "websocket proxy"; proxy.websocket.enable = mkEnableOption "websocket proxy";
}; };
@ -16,8 +13,8 @@
''; '';
}; };
}; };
hostModule = { config, ... }: { hostModule = {config, ...}: {
imports = [ wsModule ]; imports = [wsModule];
options = with lib.types; { options = with lib.types; {
locations = mkOption { locations = mkOption {

View file

@ -1,7 +1,4 @@
{ {lib, ...}: let
lib,
...
}: let
inherit (lib.options) mkOption; inherit (lib.options) mkOption;
in { in {
options.services.plex = with lib.types; { options.services.plex = with lib.types; {

View file

@ -1,11 +1,12 @@
{ config, lib, ... }: {
config,
with lib; lib,
...
let }:
with lib; let
cfg = config.networking.policyrouting; cfg = config.networking.policyrouting;
ruleOpts = { ... }: { ruleOpts = {...}: {
options = { options = {
prio = mkOption { prio = mkOption {
type = types.int; type = types.int;
@ -15,37 +16,44 @@ let
}; };
}; };
}; };
in {
in
{
options = { options = {
networking.policyrouting = { networking.policyrouting = {
enable = mkEnableOption "Declarative Policy-Routing"; enable = mkEnableOption "Declarative Policy-Routing";
rules = mkOption { rules = mkOption {
type = with types; listOf (submodule ruleOpts); type = with types; listOf (submodule ruleOpts);
default = [ ]; default = [];
}; };
rules6 = mkOption { rules6 = mkOption {
type = with types; listOf (submodule ruleOpts); type = with types; listOf (submodule ruleOpts);
default = [ ]; default = [];
}; };
rules4 = mkOption { rules4 = mkOption {
type = with types; listOf (submodule ruleOpts); type = with types; listOf (submodule ruleOpts);
default = [ ]; default = [];
}; };
}; };
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
networking.policyrouting.rules = [ networking.policyrouting.rules = [
{ rule = "lookup main"; prio = 32000; } {
rule = "lookup main";
prio = 32000;
}
]; ];
networking.localCommands = '' networking.localCommands = ''
set -x set -x
ip -6 rule flush ip -6 rule flush
ip -4 rule flush ip -4 rule flush
${concatMapStringsSep "\n" ({ prio, rule }: "ip -6 rule add ${rule} prio ${toString prio}") (cfg.rules ++ cfg.rules6)} ${concatMapStringsSep "\n" ({
${concatMapStringsSep "\n" ({ prio, rule }: "ip -4 rule add ${rule} prio ${toString prio}") (cfg.rules ++ cfg.rules4)} prio,
rule,
}: "ip -6 rule add ${rule} prio ${toString prio}") (cfg.rules ++ cfg.rules6)}
${concatMapStringsSep "\n" ({
prio,
rule,
}: "ip -4 rule add ${rule} prio ${toString prio}") (cfg.rules ++ cfg.rules4)}
''; '';
}; };
} }

View file

@ -10,19 +10,24 @@
inherit (config) networking; inherit (config) networking;
cfg = config.services.postgresql; cfg = config.services.postgresql;
formatHost = host: formatHost = host:
if hasInfix "/" host then host if hasInfix "/" host
else if hasInfix ":" host then "${host}/128" then host
else if hasInfix "." host then "${host}/32" else if hasInfix ":" host
then "${host}/128"
else if hasInfix "." host
then "${host}/32"
else throw "unsupported IP address ${host}"; else throw "unsupported IP address ${host}";
ensureUserModule = { config, ... }: { ensureUserModule = {config, ...}: {
options = with lib.types; { options = with lib.types; {
authentication = { authentication = {
enable = mkEnableOption "TCP connections" // { enable =
default = config.authentication.hosts != [ ]; mkEnableOption "TCP connections"
// {
default = config.authentication.hosts != [];
}; };
hosts = mkOption { hosts = mkOption {
type = listOf str; type = listOf str;
default = [ ]; default = [];
}; };
method = mkOption { method = mkOption {
type = str; type = str;
@ -47,13 +52,15 @@
authentication = { authentication = {
hosts = let hosts = let
inherit (networking.access) cidrForNetwork; inherit (networking.access) cidrForNetwork;
in mkMerge [ in
mkMerge [
(mkIf config.authentication.tailscale.allow cidrForNetwork.tail.all) (mkIf config.authentication.tailscale.allow cidrForNetwork.tail.all)
(mkIf config.authentication.local.allow (cidrForNetwork.loopback.all ++ cidrForNetwork.local.all)) (mkIf config.authentication.local.allow (cidrForNetwork.loopback.all ++ cidrForNetwork.local.all))
]; ];
authentication = mkMerge (map (host: '' authentication = mkMerge (map (host: ''
host ${config.authentication.database} ${config.name} ${formatHost host} ${config.authentication.method} host ${config.authentication.database} ${config.name} ${formatHost host} ${config.authentication.method}
'') config.authentication.hosts); '')
config.authentication.hosts);
}; };
authentication.database = mkIf config.ensureDBOwnership ( authentication.database = mkIf config.ensureDBOwnership (
mkOptionDefault config.name mkOptionDefault config.name
@ -70,11 +77,13 @@ in {
enableTCPIP = mkIf (any (user: user.authentication.enable) cfg.ensureUsers) ( enableTCPIP = mkIf (any (user: user.authentication.enable) cfg.ensureUsers) (
mkDefault true mkDefault true
); );
authentication = mkMerge (map (user: authentication = mkMerge (map (
user:
mkIf user.authentication.enable user.authentication.authentication mkIf user.authentication.enable user.authentication.authentication
) cfg.ensureUsers); )
cfg.ensureUsers);
}; };
config.networking.firewall.interfaces.local = mkIf cfg.enable { config.networking.firewall.interfaces.local = mkIf cfg.enable {
allowedTCPPorts = mkIf (any (user: user.authentication.local.allow) cfg.ensureUsers) [ cfg.port ]; allowedTCPPorts = mkIf (any (user: user.authentication.local.allow) cfg.ensureUsers) [cfg.port];
}; };
} }

View file

@ -1,7 +1,4 @@
{ {lib, ...}: let
lib,
...
}: let
inherit (lib.options) mkOption; inherit (lib.options) mkOption;
in { in {
options.services.prowlarr = with lib.types; { options.services.prowlarr = with lib.types; {

View file

@ -1,7 +1,4 @@
{ {lib, ...}: let
lib,
...
}: let
inherit (lib.options) mkOption; inherit (lib.options) mkOption;
in { in {
options.services.radarr = with lib.types; { options.services.radarr = with lib.types; {

View file

@ -1,7 +1,4 @@
{ {lib, ...}: let
lib,
...
}: let
inherit (lib.options) mkOption; inherit (lib.options) mkOption;
in { in {
options.services.readarr = with lib.types; { options.services.readarr = with lib.types; {

View file

@ -11,14 +11,17 @@
inherit (config.services) samba-wsdd; inherit (config.services) samba-wsdd;
cfg = config.services.samba; cfg = config.services.samba;
settingValue = value: settingValue = value:
if builtins.isList value then concatMapStringsSep ", " settingValue value if builtins.isList value
else if value == true then "yes" then concatMapStringsSep ", " settingValue value
else if value == false then "no" else if value == true
then "yes"
else if value == false
then "no"
else toString value; else toString value;
in { in {
options.services.samba = with lib.types; let options.services.samba = with lib.types; let
settingPrimitive = oneOf [ str int bool ]; settingPrimitive = oneOf [str int bool];
settingType = oneOf [ settingPrimitive (listOf settingPrimitive) ]; settingType = oneOf [settingPrimitive (listOf settingPrimitive)];
in { in {
ldap = { ldap = {
enable = mkEnableOption "LDAP"; enable = mkEnableOption "LDAP";
@ -64,7 +67,11 @@ in {
}; };
}; };
idmap = let idmap = let
idmapModule = { config, name, ... }: { idmapModule = {
config,
name,
...
}: {
options = { options = {
backend = mkOption { backend = mkOption {
type = str; type = str;
@ -89,7 +96,7 @@ in {
}; };
settings = mkOption { settings = mkOption {
type = attrsOf settingType; type = attrsOf settingType;
default = { }; default = {};
}; };
}; };
config = { config = {
@ -117,7 +124,7 @@ in {
}; };
settings = mkOption { settings = mkOption {
type = attrsOf settingType; type = attrsOf settingType;
default = { }; default = {};
}; };
}; };
@ -161,13 +168,14 @@ in {
"usershare owner only" = mkOptionDefault true; "usershare owner only" = mkOptionDefault true;
"usershare template share" = mkOptionDefault cfg.usershare.templateShare; "usershare template share" = mkOptionDefault cfg.usershare.templateShare;
"usershare path" = mkOptionDefault cfg.usershare.path; "usershare path" = mkOptionDefault cfg.usershare.path;
"usershare prefix allow list" = mkOptionDefault [ cfg.usershare.path ]; "usershare prefix allow list" = mkOptionDefault [cfg.usershare.path];
}) })
(mkIf cfg.guest.enable { (mkIf cfg.guest.enable {
"map to guest" = mkOptionDefault "Bad User"; "map to guest" = mkOptionDefault "Bad User";
"guest account" = mkOptionDefault cfg.guest.user; "guest account" = mkOptionDefault cfg.guest.user;
}) })
] ++ mapAttrsToList (_: idmap: mapAttrs' (key: value: nameValuePair "idmap config ${idmap.domain} : ${key}" (mkOptionDefault value)) idmap.settings) cfg.idmap.domains); ]
++ mapAttrsToList (_: idmap: mapAttrs' (key: value: nameValuePair "idmap config ${idmap.domain} : ${key}" (mkOptionDefault value)) idmap.settings) cfg.idmap.domains);
extraConfig = mkMerge (mapAttrsToList (key: value: ''${key} = ${settingValue value}'') cfg.settings); extraConfig = mkMerge (mapAttrsToList (key: value: ''${key} = ${settingValue value}'') cfg.settings);
shares.${cfg.usershare.templateShare} = mkIf cfg.usershare.enable { shares.${cfg.usershare.templateShare} = mkIf cfg.usershare.enable {
"-valid" = false; "-valid" = false;
@ -194,12 +202,12 @@ in {
networking.firewall.interfaces.local = { networking.firewall.interfaces.local = {
allowedTCPPorts = mkMerge [ allowedTCPPorts = mkMerge [
(mkIf (cfg.enable && !cfg.openFirewall) [ 139 445 ]) (mkIf (cfg.enable && !cfg.openFirewall) [139 445])
(mkIf (samba-wsdd.enable && !samba-wsdd.openFirewall) [ 5357 ]) (mkIf (samba-wsdd.enable && !samba-wsdd.openFirewall) [5357])
]; ];
allowedUDPPorts = mkMerge [ allowedUDPPorts = mkMerge [
(mkIf (cfg.enable && !cfg.openFirewall) [ 137 138 ]) (mkIf (cfg.enable && !cfg.openFirewall) [137 138])
(mkIf (samba-wsdd.enable && !samba-wsdd.openFirewall) [ 3702 ]) (mkIf (samba-wsdd.enable && !samba-wsdd.openFirewall) [3702])
]; ];
}; };
}; };

View file

@ -1,7 +1,4 @@
{ {lib, ...}: let
lib,
...
}: let
inherit (lib.options) mkOption; inherit (lib.options) mkOption;
in { in {
options.services.sonarr = with lib.types; { options.services.sonarr = with lib.types; {

View file

@ -76,7 +76,8 @@ in {
inherit owner; inherit owner;
inherit (shared) group mode; inherit (shared) group mode;
}; };
setupFiles = singleton { setupFiles =
singleton {
${cfg.rootDir} = toplevel; ${cfg.rootDir} = toplevel;
${cfg.binDir} = toplevel; ${cfg.binDir} = toplevel;
${cfg.binDir + "/users"} = shared; ${cfg.binDir + "/users"} = shared;
@ -84,11 +85,14 @@ in {
${cfg.sharedDataDir} = shared; ${cfg.sharedDataDir} = shared;
${cfg.workingDir} = toplevel; ${cfg.workingDir} = toplevel;
${cfg.sharedWorkingDir} = shared; ${cfg.sharedWorkingDir} = shared;
} ++ map (owner: { }
++ map (owner: {
${cfg.dataDir + "/${owner}"} = personal owner; ${cfg.dataDir + "/${owner}"} = personal owner;
${cfg.workingDir + "/${owner}"} = personal owner; ${cfg.workingDir + "/${owner}"} = personal owner;
}) cfg.users; })
userBinFiles = listToAttrs (map (user: nameValuePair "${cfg.binDir}/users/${user}.bat" { cfg.users;
userBinFiles = listToAttrs (map (user:
nameValuePair "${cfg.binDir}/users/${user}.bat" {
inherit (toplevel) owner group; inherit (toplevel) owner group;
mode = "0755"; mode = "0755";
type = "copy"; type = "copy";
@ -99,7 +103,8 @@ in {
setx GENSO_STEAM_USER ${user} setx GENSO_STEAM_USER ${user}
''; '';
}; };
}) cfg.users); })
cfg.users);
in { in {
enable = mkIf (cfg.enable || cfg.setup) true; enable = mkIf (cfg.enable || cfg.setup) true;
files = mkMerge [ files = mkMerge [

View file

@ -14,7 +14,11 @@
inherit (lib.meta) getExe; inherit (lib.meta) getExe;
inherit (config.services.steam) accountSwitch; inherit (config.services.steam) accountSwitch;
cfg = config.services.steam.beatsaber; cfg = config.services.steam.beatsaber;
versionModule = { config, name, ... }: { versionModule = {
config,
name,
...
}: {
options = with lib.types; { options = with lib.types; {
version = mkOption { version = mkOption {
type = str; type = str;
@ -23,7 +27,8 @@
}; };
}; };
mkSharePath = path: mkWinPath ( mkSharePath = path:
mkWinPath (
"%GENSO_SMB_SHARED_MOUNT%" "%GENSO_SMB_SHARED_MOUNT%"
+ "/${accountSwitch.sharePath}" + "/${accountSwitch.sharePath}"
+ "/${removePrefix (accountSwitch.rootDir + "/") path}" + "/${removePrefix (accountSwitch.rootDir + "/") path}"
@ -102,7 +107,9 @@
in { in {
options.services.steam.beatsaber = with lib.types; { options.services.steam.beatsaber = with lib.types; {
enable = mkEnableOption "beatsaber scripts"; enable = mkEnableOption "beatsaber scripts";
setup = mkEnableOption "beatsaber data" // { setup =
mkEnableOption "beatsaber data"
// {
default = accountSwitch.setup; default = accountSwitch.setup;
}; };
group = mkOption { group = mkOption {
@ -114,7 +121,7 @@ in {
}; };
versions = mkOption { versions = mkOption {
type = attrsOf (submodule versionModule); type = attrsOf (submodule versionModule);
default = { }; default = {};
}; };
users = mkOption { users = mkOption {
type = listOf str; type = listOf str;
@ -127,7 +134,7 @@ in {
bsUsers = filterAttrs (_: userIs cfg.group) config.users.users; bsUsers = filterAttrs (_: userIs cfg.group) config.users.users;
allVersions = mapAttrsToList (_: version: version.version) cfg.versions; allVersions = mapAttrsToList (_: version: version.version) cfg.versions;
in { in {
defaultVersion = mkIf (allVersions != [ ]) (mkOptionDefault ( defaultVersion = mkIf (allVersions != []) (mkOptionDefault (
head allVersions head allVersions
)); ));
users = mkOptionDefault ( users = mkOptionDefault (
@ -140,10 +147,12 @@ in {
mkbeatsabersh mkbeatsabersh
]; ];
}; };
systemd.services = mkIf cfg.setup (listToAttrs (map (user: nameValuePair "steam-setup-beatsaber-${user}" { systemd.services = mkIf cfg.setup (listToAttrs (map (user:
nameValuePair "steam-setup-beatsaber-${user}" {
script = mkMerge (mapAttrsToList (_: version: '' script = mkMerge (mapAttrsToList (_: version: ''
${getExe mkbeatsaber} ${version.version} ${user} ${getExe mkbeatsaber} ${version.version} ${user}
'') cfg.versions); '')
cfg.versions);
path = [ path = [
pkgs.coreutils pkgs.coreutils
]; ];
@ -157,7 +166,8 @@ in {
RemainAfterExit = mkOptionDefault true; RemainAfterExit = mkOptionDefault true;
User = mkOptionDefault user; User = mkOptionDefault user;
}; };
}) cfg.users)); })
cfg.users));
services.tmpfiles = let services.tmpfiles = let
toplevel = { toplevel = {
owner = mkDefault "admin"; owner = mkDefault "admin";
@ -187,30 +197,42 @@ in {
"AppData" "AppData"
"UserData" "UserData"
]; ];
setupFiles = [ setupFiles =
[
{ {
"${accountSwitch.sharedDataDir}/BeatSaber" = toplevel; "${accountSwitch.sharedDataDir}/BeatSaber" = toplevel;
"${accountSwitch.binDir}/beatsaber" = shared; "${accountSwitch.binDir}/beatsaber" = shared;
} }
(listToAttrs ( (listToAttrs (
map (folder: map (
folder:
nameValuePair "${accountSwitch.sharedDataDir}/BeatSaber/${folder}" shared nameValuePair "${accountSwitch.sharedDataDir}/BeatSaber/${folder}" shared
) sharedFolders )
sharedFolders
)) ))
] ++ concatMap (owner: ]
++ concatMap (
owner:
singleton { singleton {
"${accountSwitch.dataDir}/${owner}/BeatSaber" = personal owner; "${accountSwitch.dataDir}/${owner}/BeatSaber" = personal owner;
"${accountSwitch.dataDir}/${owner}/BeatSaber/AppData" = personal owner; "${accountSwitch.dataDir}/${owner}/BeatSaber/AppData" = personal owner;
"${accountSwitch.dataDir}/${owner}/BeatSaber/UserData" = personal owner; "${accountSwitch.dataDir}/${owner}/BeatSaber/UserData" = personal owner;
} ++ mapAttrsToList (_: version: { }
++ mapAttrsToList (_: version: {
"${accountSwitch.dataDir}/${owner}/BeatSaber/${version.version}" = personal owner; "${accountSwitch.dataDir}/${owner}/BeatSaber/${version.version}" = personal owner;
}) cfg.versions })
) accountSwitch.users cfg.versions
)
accountSwitch.users
++ mapAttrsToList (_: version: { ++ mapAttrsToList (_: version: {
"${accountSwitch.sharedDataDir}/BeatSaber/${version.version}" = shared; "${accountSwitch.sharedDataDir}/BeatSaber/${version.version}" = shared;
}) cfg.versions; })
versionBinFiles = mapAttrs' (_: version: nameValuePair cfg.versions;
"${accountSwitch.binDir}/beatsaber/${replaceStrings [ "." ] [ "_" ] version.version}.bat" versionBinFiles =
mapAttrs' (
_: version:
nameValuePair
"${accountSwitch.binDir}/beatsaber/${replaceStrings ["."] ["_"] version.version}.bat"
{ {
inherit (bin) owner group mode type; inherit (bin) owner group mode type;
src = pkgs.writeTextFile { src = pkgs.writeTextFile {
@ -221,8 +243,10 @@ in {
''; '';
}; };
} }
) cfg.versions; )
binFiles = { cfg.versions;
binFiles =
{
"${accountSwitch.binDir}/beatsaber/mount.bat" = { "${accountSwitch.binDir}/beatsaber/mount.bat" = {
inherit (bin) owner group mode type; inherit (bin) owner group mode type;
src = pkgs.writeTextFile { src = pkgs.writeTextFile {
@ -257,7 +281,8 @@ in {
executable = true; executable = true;
}; };
}; };
} // versionBinFiles; }
// versionBinFiles;
in { in {
enable = mkIf (cfg.enable || cfg.setup) true; enable = mkIf (cfg.enable || cfg.setup) true;
files = mkMerge [ files = mkMerge [

View file

@ -18,9 +18,15 @@
systemdFiles = filter (file: file.systemd.enable) files; systemdFiles = filter (file: file.systemd.enable) files;
setupFiles = filter (file: !file.systemd.enable) files; setupFiles = filter (file: !file.systemd.enable) files;
bindFiles = filter (file: file.type == "bind") files; bindFiles = filter (file: file.type == "bind") files;
fileModule = { config, name, ... }: { fileModule = {
config,
name,
...
}: {
options = with lib.types; { options = with lib.types; {
enable = mkEnableOption "file" // { enable =
mkEnableOption "file"
// {
default = true; default = true;
}; };
mkdirParent = mkEnableOption "mkdir"; mkdirParent = mkEnableOption "mkdir";
@ -32,8 +38,11 @@
default = name; default = name;
}; };
type = mkOption { type = mkOption {
type = enum [ "directory" "symlink" "link" "copy" "bind" ]; type = enum ["directory" "symlink" "link" "copy" "bind"];
default = if config.src != null then "symlink" else "directory"; default =
if config.src != null
then "symlink"
else "directory";
}; };
mode = mkOption { mode = mkOption {
type = str; type = str;
@ -71,7 +80,7 @@
}; };
config = let config = let
acls = concatStringsSep "," config.acls; acls = concatStringsSep "," config.acls;
enableAcls = config.type == "directory" && config.acls != [ ]; enableAcls = config.type == "directory" && config.acls != [];
systemdAclRule = "a+ ${config.path} - - - - ${acls}"; systemdAclRule = "a+ ${config.path} - - - - ${acls}";
systemdRule = { systemdRule = {
directory = [ directory = [
@ -168,7 +177,7 @@
systemd = { systemd = {
rules = mkMerge [ rules = mkMerge [
systemdRule.${config.type} systemdRule.${config.type}
(mkIf enableAcls [ systemdAclRule ]) (mkIf enableAcls [systemdAclRule])
]; ];
mountSettings = mkIf (config.type == "bind") { mountSettings = mkIf (config.type == "bind") {
enable = mkDefault config.enable; enable = mkDefault config.enable;
@ -191,16 +200,21 @@
}; };
in { in {
options.services.tmpfiles = with lib.types; { options.services.tmpfiles = with lib.types; {
enable = mkEnableOption "extended tmpfiles" // { enable =
default = cfg.files != { }; mkEnableOption "extended tmpfiles"
// {
default = cfg.files != {};
}; };
user = mkOption { user = mkOption {
type = str; type = str;
default = if config.proxmoxLXC.privileged or true then "root" else "admin"; default =
if config.proxmoxLXC.privileged or true
then "root"
else "admin";
}; };
files = mkOption { files = mkOption {
type = attrsOf (submodule fileModule); type = attrsOf (submodule fileModule);
default = { }; default = {};
}; };
}; };
config = { config = {
@ -209,15 +223,19 @@ in {
map (file: file.systemd.rules) systemdFiles map (file: file.systemd.rules) systemdFiles
); );
services.tmpfiles = { services.tmpfiles = {
path = [ pkgs.coreutils pkgs.acl ]; path = [pkgs.coreutils pkgs.acl];
script = mkMerge ( script = mkMerge (
[ '' [
''
EXITCODE=0 EXITCODE=0
'' ] ''
]
++ map (file: file.setup.script) setupFiles ++ map (file: file.setup.script) setupFiles
++ [ '' ++ [
''
exit $EXITCODE exit $EXITCODE
'' ] ''
]
); );
wantedBy = [ wantedBy = [
"sysinit.target" "sysinit.target"

View file

@ -13,28 +13,33 @@
userMatchBlock = user: let userMatchBlock = user: let
inherit (user.openssh) matchBlock; inherit (user.openssh) matchBlock;
criteria = mapAttrsToList toSshdCriteria matchBlock.criteria; criteria = mapAttrsToList toSshdCriteria matchBlock.criteria;
in mkAfter '' in
mkAfter ''
Match ${concatStringsSep " " criteria} Match ${concatStringsSep " " criteria}
${matchBlock.settingsConfig} ${matchBlock.settingsConfig}
''; '';
userModule = { config, ... }: let userModule = {config, ...}: let
toSshdValue = value: toSshdValue = value:
if value == true then "yes" if value == true
else if value == false then "no" then "yes"
else if value == false
then "no"
else toString value; else toString value;
toSshdConf = key: value: "${key} ${toSshdValue value}"; toSshdConf = key: value: "${key} ${toSshdValue value}";
in { in {
options = with lib.types; { options = with lib.types; {
openssh.matchBlock = { openssh.matchBlock = {
enable = mkEnableOption "match block" // { enable =
default = config.openssh.matchBlock.settings != { }; mkEnableOption "match block"
// {
default = config.openssh.matchBlock.settings != {};
}; };
criteria = mkOption { criteria = mkOption {
type = attrsOf str; type = attrsOf str;
}; };
settings = mkOption { settings = mkOption {
type = attrsOf (oneOf [ str path bool int ]); type = attrsOf (oneOf [str path bool int]);
default = { }; default = {};
}; };
settingsConfig = mkOption { settingsConfig = mkOption {
type = lines; type = lines;

View file

@ -5,11 +5,20 @@
lib, lib,
... ...
}: let }: let
inherit (lib) mkIf mkMerge mkDefault mkOptionDefault mkOption mkEnableOption types inherit
getExe; (lib)
mkIf
mkMerge
mkDefault
mkOptionDefault
mkOption
mkEnableOption
types
getExe
;
nixosConfig = config; nixosConfig = config;
cfg = config.services.vouch-proxy; cfg = config.services.vouch-proxy;
settingsFormat = pkgs.formats.json { }; settingsFormat = pkgs.formats.json {};
in { in {
options.services.vouch-proxy = with types; { options.services.vouch-proxy = with types; {
enable = mkEnableOption "vouch"; enable = mkEnableOption "vouch";
@ -35,7 +44,7 @@ in {
}; };
enableSettingsSecrets = mkEnableOption "genJqSecretsReplacementSnippet"; enableSettingsSecrets = mkEnableOption "genJqSecretsReplacementSnippet";
settings = let settings = let
settingsModule = { ... }: { settingsModule = {...}: {
freeformType = settingsFormat.type; freeformType = settingsFormat.type;
options = { options = {
vouch = { vouch = {
@ -98,13 +107,14 @@ in {
}; };
}; };
}; };
in mkOption { in
mkOption {
type = submodule settingsModule; type = submodule settingsModule;
default = { }; default = {};
}; };
extraSettings = mkOption { extraSettings = mkOption {
inherit (settingsFormat) type; inherit (settingsFormat) type;
default = { }; default = {};
}; };
settingsPath = mkOption { settingsPath = mkOption {
type = path; type = path;
@ -116,10 +126,12 @@ in {
cfg.settings cfg.settings
cfg.extraSettings cfg.extraSettings
]; ];
settingsPath = if cfg.enableSettingsSecrets settingsPath =
if cfg.enableSettingsSecrets
then "/run/vouch-proxy/vouch-config.json" then "/run/vouch-proxy/vouch-config.json"
else settingsFormat.generate "vouch-config.json" settings; else settingsFormat.generate "vouch-config.json" settings;
in mkMerge [ in
mkMerge [
{ {
services.vouch-proxy = { services.vouch-proxy = {
settingsPath = mkOptionDefault settingsPath; settingsPath = mkOptionDefault settingsPath;
@ -128,14 +140,15 @@ in {
(mkIf cfg.enable { (mkIf cfg.enable {
systemd.services.vouch-proxy = { systemd.services.vouch-proxy = {
description = "Vouch-proxy"; description = "Vouch-proxy";
after = [ "network.target" ]; after = ["network.target"];
wantedBy = [ "multi-user.target" ]; wantedBy = ["multi-user.target"];
serviceConfig = { serviceConfig = {
ExecStartPre = let ExecStartPre = let
preprocess = pkgs.writeShellScript "vouch-proxy-prestart" ( preprocess = pkgs.writeShellScript "vouch-proxy-prestart" (
utils.genJqSecretsReplacementSnippet settings cfg.settingsPath utils.genJqSecretsReplacementSnippet settings cfg.settingsPath
); );
in mkIf cfg.enableSettingsSecrets [ in
mkIf cfg.enableSettingsSecrets [
"${preprocess}" "${preprocess}"
]; ];
ExecStart = [ ExecStart = [

View file

@ -3,8 +3,7 @@
meta, meta,
lib, lib,
... ...
}: }: let
let
inherit (lib.options) mkOption mkEnableOption; inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf mkMerge mkBefore mkDefault; inherit (lib.modules) mkIf mkMerge mkBefore mkDefault;
inherit (lib.strings) optionalString concatStringsSep; inherit (lib.strings) optionalString concatStringsSep;
@ -56,7 +55,9 @@ in {
type = str; type = str;
}; };
preread = { preread = {
enable = mkEnableOption "ssl preread" // { enable =
mkEnableOption "ssl preread"
// {
default = true; default = true;
}; };
port = mkOption { port = mkOption {
@ -65,7 +66,9 @@ in {
}; };
}; };
kerberos = { kerberos = {
enable = mkEnableOption "proxy kerberos" // { enable =
mkEnableOption "proxy kerberos"
// {
default = true; default = true;
}; };
ports = { ports = {
@ -86,7 +89,10 @@ in {
proxyPass = mkOption { proxyPass = mkOption {
type = str; type = str;
default = let default = let
scheme = if access.port == 443 then "https" else "http"; scheme =
if access.port == 443
then "https"
else "http";
in "${scheme}://${access.host}:${toString access.port}"; in "${scheme}://${access.host}:${toString access.port}";
}; };
domain = mkOption { domain = mkOption {
@ -130,7 +136,7 @@ in {
port = mkDefault access.ldapPort; port = mkDefault access.ldapPort;
useACMEHost = mkDefault access.useACMEHost; useACMEHost = mkDefault access.useACMEHost;
}; };
resolver.addresses = mkIf access.preread.enable [ "[::1]" "127.0.0.1:5353" ]; resolver.addresses = mkIf access.preread.enable ["[::1]" "127.0.0.1:5353"];
defaultSSLListenPort = mkIf access.preread.enable access.preread.port; defaultSSLListenPort = mkIf access.preread.enable access.preread.port;
streamConfig = let streamConfig = let
preread = '' preread = ''
@ -174,7 +180,8 @@ in {
proxy_pass ${access.host}:${toString access.kerberos.ports.kpasswd}; proxy_pass ${access.host}:${toString access.kerberos.ports.kpasswd};
} }
''; '';
in mkMerge [ in
mkMerge [
(mkIf access.preread.enable preread) (mkIf access.preread.enable preread)
(mkIf access.kerberos.enable kerberos) (mkIf access.kerberos.enable kerberos)
]; ];
@ -207,7 +214,7 @@ in {
local.enable = true; local.enable = true;
inherit locations; inherit locations;
}; };
${ldap.domain} = { config, ... }: { ${ldap.domain} = {config, ...}: {
useACMEHost = mkDefault virtualHosts.${access.domain}.useACMEHost; useACMEHost = mkDefault virtualHosts.${access.domain}.useACMEHost;
addSSL = mkDefault (config.useACMEHost != null); addSSL = mkDefault (config.useACMEHost != null);
globalRedirect = access.domain; globalRedirect = access.domain;

View file

@ -12,7 +12,9 @@
freepbx = config.lib.access.systemFor "freepbx"; freepbx = config.lib.access.systemFor "freepbx";
in { in {
options.services.nginx.access.freepbx = with lib.types; { options.services.nginx.access.freepbx = with lib.types; {
global.enable = mkEnableOption "global access" // { global.enable =
mkEnableOption "global access"
// {
default = access.useACMEHost != null; default = access.useACMEHost != null;
}; };
host = mkOption { host = mkOption {
@ -94,7 +96,8 @@ in {
}; };
"${access.domain}@ucp" = { "${access.domain}@ucp" = {
serverName = access.domain; serverName = access.domain;
listen = concatMap (addr: [ listen =
concatMap (addr: [
{ {
inherit addr; inherit addr;
port = access.ucpPort; port = access.ucpPort;
@ -104,7 +107,8 @@ in {
port = access.ucpSslPort; port = access.ucpSslPort;
ssl = true; ssl = true;
}) })
]) nginx.defaultListenAddresses; ])
nginx.defaultListenAddresses;
proxy.websocket.enable = true; proxy.websocket.enable = true;
local.enable = mkDefault (!access.global.enable); local.enable = mkDefault (!access.global.enable);
addSSL = mkDefault (access.useACMEHost != null); addSSL = mkDefault (access.useACMEHost != null);
@ -116,7 +120,8 @@ in {
inherit extraConfig; inherit extraConfig;
}; };
${access.localDomain} = { ${access.localDomain} = {
listen = concatMap (addr: [ listen =
concatMap (addr: [
{ {
inherit addr; inherit addr;
port = nginx.defaultHTTPListenPort; port = nginx.defaultHTTPListenPort;
@ -135,8 +140,9 @@ in {
port = access.ucpSslPort; port = access.ucpSslPort;
ssl = true; ssl = true;
}) })
]) nginx.defaultListenAddresses; ])
serverAliases = mkIf tailscale.enable [ access.tailDomain ]; nginx.defaultListenAddresses;
serverAliases = mkIf tailscale.enable [access.tailDomain];
useACMEHost = mkDefault access.useACMEHost; useACMEHost = mkDefault access.useACMEHost;
addSSL = mkDefault (access.useACMEHost != null); addSSL = mkDefault (access.useACMEHost != null);
kTLS = mkDefault true; kTLS = mkDefault true;
@ -146,7 +152,7 @@ in {
}; };
}; };
config.networking.firewall = let config.networking.firewall = let
websocketPorts = [ access.ucpPort ] ++ optional (access.useACMEHost != null) access.ucpSslPort; websocketPorts = [access.ucpPort] ++ optional (access.useACMEHost != null) access.ucpSslPort;
in { in {
interfaces.local.allowedTCPPorts = websocketPorts; interfaces.local.allowedTCPPorts = websocketPorts;
allowedTCPPorts = mkIf access.global.enable websocketPorts; allowedTCPPorts = mkIf access.global.enable websocketPorts;

View file

@ -1,7 +1,4 @@
{ {lib, ...}: let
lib,
...
}: let
inherit (lib.modules) mkDefault; inherit (lib.modules) mkDefault;
in { in {
networking = { networking = {

View file

@ -34,12 +34,14 @@ in {
url = mkOptionDefault "http://localhost:${toString cfg.port}"; url = mkOptionDefault "http://localhost:${toString cfg.port}";
}; };
virtualHosts = let virtualHosts = let
invidiousDomains = [ invidiousDomains =
[
access.domain access.domain
access.localDomain access.localDomain
] ++ optional tailscale.enable access.tailDomain; ]
++ optional tailscale.enable access.tailDomain;
contentSecurityPolicy' = "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; manifest-src 'self'; media-src 'self' blob: https://*.googlevideo.com:443 https://*.youtube.com:443; child-src 'self' blob:; frame-src 'self'; frame-ancestors 'none'"; contentSecurityPolicy' = "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; manifest-src 'self'; media-src 'self' blob: https://*.googlevideo.com:443 https://*.youtube.com:443; child-src 'self' blob:; frame-src 'self'; frame-ancestors 'none'";
contentSecurityPolicy = replaceStrings [ "'self'" ] [ "'self' ${concatStringsSep " " invidiousDomains}" ] contentSecurityPolicy'; contentSecurityPolicy = replaceStrings ["'self'"] ["'self' ${concatStringsSep " " invidiousDomains}"] contentSecurityPolicy';
extraConfig = '' extraConfig = ''
# Some players don't reopen a socket and playback stops totally instead of resuming after an extended pause # Some players don't reopen a socket and playback stops totally instead of resuming after an extended pause
send_timeout 100m; send_timeout 100m;
@ -56,14 +58,14 @@ in {
''; '';
}; };
in { in {
${access.domain} = { config, ... }: { ${access.domain} = {config, ...}: {
vouch.enable = true; vouch.enable = true;
locations."/" = location; locations."/" = location;
kTLS = mkDefault true; kTLS = mkDefault true;
inherit extraConfig; inherit extraConfig;
}; };
${access.localDomain} = { config, ... }: { ${access.localDomain} = {config, ...}: {
serverAliases = mkIf tailscale.enable [ access.tailDomain ]; serverAliases = mkIf tailscale.enable [access.tailDomain];
local.enable = true; local.enable = true;
locations."/" = mkMerge [ locations."/" = mkMerge [
location location

View file

@ -3,8 +3,7 @@
meta, meta,
lib, lib,
... ...
}: }: let
let
inherit (lib.options) mkOption; inherit (lib.options) mkOption;
inherit (lib.modules) mkIf mkMerge mkDefault mkOptionDefault; inherit (lib.modules) mkIf mkMerge mkDefault mkOptionDefault;
inherit (config) networking; inherit (config) networking;

View file

@ -64,8 +64,9 @@ in {
inherit extraConfig; inherit extraConfig;
}; };
}; };
streamListen = { config, ... }: { streamListen = {config, ...}: {
listen = concatMap (addr: [ listen =
concatMap (addr: [
(mkIf config.addSSL { (mkIf config.addSSL {
inherit addr; inherit addr;
port = nginx.defaultSSLListenPort; port = nginx.defaultSSLListenPort;
@ -79,24 +80,31 @@ in {
inherit addr; inherit addr;
port = access.streamPort; port = access.streamPort;
} }
]) nginx.defaultListenAddresses; ])
nginx.defaultListenAddresses;
}; };
in { in {
${access.domain} = mkMerge [ { ${access.domain} = mkMerge [
{
vouch.enable = true; vouch.enable = true;
kTLS = mkDefault true; kTLS = mkDefault true;
inherit (access) useACMEHost; inherit (access) useACMEHost;
addSSL = mkDefault (access.useACMEHost != null); addSSL = mkDefault (access.useACMEHost != null);
inherit locations; inherit locations;
} streamListen ]; }
${access.localDomain} = mkMerge [ { streamListen
serverAliases = mkIf config.services.tailscale.enable [ access.tailDomain ]; ];
${access.localDomain} = mkMerge [
{
serverAliases = mkIf config.services.tailscale.enable [access.tailDomain];
inherit (virtualHosts.${access.domain}) useACMEHost; inherit (virtualHosts.${access.domain}) useACMEHost;
addSSL = mkDefault addSSL; addSSL = mkDefault addSSL;
kTLS = mkDefault true; kTLS = mkDefault true;
local.enable = true; local.enable = true;
inherit locations; inherit locations;
} streamListen ]; }
streamListen
];
}; };
}; };
config.networking.firewall.allowedTCPPorts = [ config.networking.firewall.allowedTCPPorts = [

View file

@ -2,8 +2,7 @@
config, config,
lib, lib,
... ...
}: }: let
let
inherit (lib.options) mkOption mkEnableOption; inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf mkMerge; inherit (lib.modules) mkIf mkMerge;
inherit (lib.strings) concatMapStringsSep optionalString; inherit (lib.strings) concatMapStringsSep optionalString;
@ -18,7 +17,9 @@ let
cidrForNetwork.loopback.all cidrForNetwork.loopback.all
++ cidrForNetwork.local.all ++ cidrForNetwork.local.all
++ optionals tailscale.enable cidrForNetwork.tail.all; ++ optionals tailscale.enable cidrForNetwork.tail.all;
allows = concatMapStringsSep "\n" mkAllow allowAddresses + optionalString localaddrs.enable '' allows =
concatMapStringsSep "\n" mkAllow allowAddresses
+ optionalString localaddrs.enable ''
include ${localaddrs.stateDir}/*.nginx.conf; include ${localaddrs.stateDir}/*.nginx.conf;
''; '';
in '' in ''
@ -61,7 +62,8 @@ in {
proxy_ssl on; proxy_ssl on;
proxy_ssl_verify off; proxy_ssl_verify off;
''; '';
in mkIf access.enable (mkMerge [ in
mkIf access.enable (mkMerge [
'' ''
server { server {
listen 0.0.0.0:389; listen 0.0.0.0:389;

View file

@ -70,10 +70,12 @@ in {
plex-external = mkIf (access.externalPort != null) { plex-external = mkIf (access.externalPort != null) {
serverName = mkDefault access.domain; serverName = mkDefault access.domain;
default = mkDefault true; default = mkDefault true;
listen = map (addr: { listen =
map (addr: {
inherit addr; inherit addr;
port = access.externalPort; port = access.externalPort;
}) nginx.defaultListenAddresses; })
nginx.defaultListenAddresses;
locations."/" = location; locations."/" = location;
inherit extraConfig; inherit extraConfig;
}; };

View file

@ -14,10 +14,11 @@
proxyPass = "https://reisen.local.${config.networking.domain}:8006/"; proxyPass = "https://reisen.local.${config.networking.domain}:8006/";
unencrypted = mkSnakeOil { unencrypted = mkSnakeOil {
name = "prox-local-cert"; name = "prox-local-cert";
domain = singleton "prox.local.${config.networking.domain}" domain =
singleton "prox.local.${config.networking.domain}"
++ optional tailscale.enable "prox.tail.${config.networking.domain}"; ++ optional tailscale.enable "prox.tail.${config.networking.domain}";
}; };
sslHost = { config, ... }: { sslHost = {config, ...}: {
sslCertificate = mkIf (!config.enableACME && config.useACMEHost == null) unencrypted.fullchain; sslCertificate = mkIf (!config.enableACME && config.useACMEHost == null) unencrypted.fullchain;
sslCertificateKey = mkIf (!config.enableACME && config.useACMEHost == null) unencrypted.key; sslCertificateKey = mkIf (!config.enableACME && config.useACMEHost == null) unencrypted.key;
}; };
@ -91,7 +92,8 @@ in {
${access.domain} = { ${access.domain} = {
inherit locations extraConfig; inherit locations extraConfig;
}; };
${access.localDomain} = mkMerge [ { ${access.localDomain} = mkMerge [
{
inherit (virtualHosts.${access.domain}) useACMEHost; inherit (virtualHosts.${access.domain}) useACMEHost;
local.enable = mkDefault true; local.enable = mkDefault true;
forceSSL = mkDefault true; forceSSL = mkDefault true;
@ -99,8 +101,11 @@ in {
proxy.websocket.enable = true; proxy.websocket.enable = true;
inherit proxyPass extraConfig; inherit proxyPass extraConfig;
}; };
} sslHost ]; }
${access.tailDomain} = mkIf tailscale.enable (mkMerge [ { sslHost
];
${access.tailDomain} = mkIf tailscale.enable (mkMerge [
{
inherit (virtualHosts.${access.domain}) useACMEHost; inherit (virtualHosts.${access.domain}) useACMEHost;
addSSL = mkDefault true; addSSL = mkDefault true;
local.enable = mkDefault true; local.enable = mkDefault true;
@ -108,7 +113,9 @@ in {
proxy.websocket.enable = true; proxy.websocket.enable = true;
inherit proxyPass extraConfig; inherit proxyPass extraConfig;
}; };
} sslHost ]); }
sslHost
]);
}; };
config.sops.secrets.access-proxmox = { config.sops.secrets.access-proxmox = {

View file

@ -10,7 +10,9 @@
in { in {
options.services.nginx.access.unifi = with lib.types; { options.services.nginx.access.unifi = with lib.types; {
global = { global = {
enable = mkEnableOption "global access" // { enable =
mkEnableOption "global access"
// {
default = access.useACMEHost != null; default = access.useACMEHost != null;
}; };
management = mkEnableOption "global management port access"; management = mkEnableOption "global management port access";
@ -59,11 +61,13 @@ in {
}; };
in { in {
"${access.domain}@management" = mkIf access.global.management { "${access.domain}@management" = mkIf access.global.management {
listen = map (addr: { listen =
map (addr: {
inherit addr; inherit addr;
port = access.managementPort; port = access.managementPort;
ssl = true; ssl = true;
}) nginx.defaultListenAddresses; })
nginx.defaultListenAddresses;
serverName = access.domain; serverName = access.domain;
default = mkDefault true; default = mkDefault true;
forceSSL = mkDefault true; forceSSL = mkDefault true;
@ -81,7 +85,7 @@ in {
inherit locations extraConfig; inherit locations extraConfig;
}; };
${access.localDomain} = { ${access.localDomain} = {
serverAliases = mkIf tailscale.enable [ access.tailDomain ]; serverAliases = mkIf tailscale.enable [access.tailDomain];
useACMEHost = mkDefault access.useACMEHost; useACMEHost = mkDefault access.useACMEHost;
addSSL = mkDefault (access.useACMEHost != null); addSSL = mkDefault (access.useACMEHost != null);
kTLS = mkDefault true; kTLS = mkDefault true;
@ -91,7 +95,7 @@ in {
}; };
}; };
config.networking.firewall = { config.networking.firewall = {
interfaces.local.allowedTCPPorts = [ access.managementPort ]; interfaces.local.allowedTCPPorts = [access.managementPort];
allowedTCPPorts = mkIf access.global.management [ access.managementPort ]; allowedTCPPorts = mkIf access.global.management [access.managementPort];
}; };
} }

View file

@ -35,8 +35,12 @@ in {
access.vouch = mkIf cfg.enable { access.vouch = mkIf cfg.enable {
url = let url = let
inherit (cfg.settings.vouch) listen; inherit (cfg.settings.vouch) listen;
host = if listen == "0.0.0.0" || listen == "[::]" then "localhost" else listen; host =
in mkOptionDefault "http://${host}:${toString cfg.port}"; if listen == "0.0.0.0" || listen == "[::]"
then "localhost"
else listen;
in
mkOptionDefault "http://${host}:${toString cfg.port}";
}; };
virtualHosts = let virtualHosts = let
locations = { locations = {
@ -46,15 +50,18 @@ in {
proxy_redirect default; proxy_redirect default;
''; '';
}; };
"/validate" = { config, ... }: { "/validate" = {config, ...}: {
proxyPass = mkDefault (access.url + "/validate"); proxyPass = mkDefault (access.url + "/validate");
recommendedProxySettings = mkDefault false; recommendedProxySettings = mkDefault false;
extraConfig = if config.local.trusted then '' extraConfig =
if config.local.trusted
then ''
if ($http_x_host = ''') { if ($http_x_host = ''') {
set $http_x_host $host; set $http_x_host $host;
} }
proxy_set_header Host $http_x_host; proxy_set_header Host $http_x_host;
'' else '' ''
else ''
proxy_set_header Host $host; proxy_set_header Host $host;
''; '';
}; };

View file

@ -2,8 +2,7 @@
config, config,
lib, lib,
... ...
}: }: let
let
inherit (lib.options) mkOption; inherit (lib.options) mkOption;
inherit (lib.modules) mkIf mkDefault mkOptionDefault; inherit (lib.modules) mkIf mkDefault mkOptionDefault;
cfg = config.services.zigbee2mqtt; cfg = config.services.zigbee2mqtt;
@ -46,7 +45,7 @@ in {
locations."/" = location; locations."/" = location;
}; };
${access.localDomain} = { ${access.localDomain} = {
serverAliases = mkIf config.services.tailscale.enable [ access.tailDomain ]; serverAliases = mkIf config.services.tailscale.enable [access.tailDomain];
local.enable = true; local.enable = true;
locations."/" = location; locations."/" = location;
}; };

View file

@ -8,18 +8,30 @@
inherit (lib.lists) head optional; inherit (lib.lists) head optional;
cfg = config.security.acme; cfg = config.security.acme;
mkHash = with builtins; val: substring 0 20 (hashString "sha256" val); mkHash = with builtins; val: substring 0 20 (hashString "sha256" val);
mkAccountHash = { server ? null, keyType, email }: mkHash "${toString server} ${keyType} ${email}"; mkAccountHash = {
server ? null,
keyType,
email,
}:
mkHash "${toString server} ${keyType} ${email}";
mkHost = server: head (splitString "/" (removePrefix "https://" server)); mkHost = server: head (splitString "/" (removePrefix "https://" server));
mkAccountDir = { server ? null, email, keyType }: concatStringsSep "/" ([ mkAccountDir = {
server ? null,
email,
keyType,
}:
concatStringsSep "/" ([
accountDirRoot accountDirRoot
(mkAccountHash { inherit server email keyType; }) (mkAccountHash {inherit server email keyType;})
] ++ optional (server != null) ( ]
++ optional (server != null) (
mkHost server mkHost server
) ++ [ )
++ [
cfg.defaults.email cfg.defaults.email
]); ]);
accountDirRoot = "/var/lib/acme/.lego/accounts"; accountDirRoot = "/var/lib/acme/.lego/accounts";
addr = concatStringsSep "@" [ "gensokyo" "arcn.mx" ]; addr = concatStringsSep "@" ["gensokyo" "arcn.mx"];
in { in {
security.acme = { security.acme = {
acceptTerms = true; acceptTerms = true;
@ -35,16 +47,19 @@ in {
}; };
}; };
sops.secrets = let sops.secrets = let
accountDir = mkAccountDir { inherit (cfg.defaults) server email keyType; }; accountDir = mkAccountDir {inherit (cfg.defaults) server email keyType;};
acmeSecret = { acmeSecret = {
sopsFile = mkDefault ./secrets/acme.yaml; sopsFile = mkDefault ./secrets/acme.yaml;
owner = "acme"; owner = "acme";
group = "nginx"; group = "nginx";
}; };
in { in {
acme_account_key = mkMerge [ acmeSecret { acme_account_key = mkMerge [
acmeSecret
{
path = accountDir + "/keys/${cfg.defaults.email}.key"; path = accountDir + "/keys/${cfg.defaults.email}.key";
} ]; }
];
acme_cloudflare_email = acmeSecret; acme_cloudflare_email = acmeSecret;
acme_cloudflare_token = acmeSecret; acme_cloudflare_token = acmeSecret;
}; };

View file

@ -26,7 +26,7 @@ in {
daemon = "avahi-daemon.service"; daemon = "avahi-daemon.service";
avahi-daemon-watchdog = pkgs.writeShellScript "avahi-daemon-watchdog" '' avahi-daemon-watchdog = pkgs.writeShellScript "avahi-daemon-watchdog" ''
set -eu set -eu
export PATH="$PATH:${makeBinPath [ config.systemd.package pkgs.coreutils pkgs.gnugrep ]}" export PATH="$PATH:${makeBinPath [config.systemd.package pkgs.coreutils pkgs.gnugrep]}"
while read -r line; do while read -r line; do
if [[ $line = *"Host name conflict"* ]]; then if [[ $line = *"Host name conflict"* ]]; then
if systemctl is-active ${daemon} > /dev/null; then if systemctl is-active ${daemon} > /dev/null; then
@ -38,14 +38,15 @@ in {
fi fi
done < <(journalctl -o cat -feu ${daemon} | grep -F 'Host name conflict, retrying with ') done < <(journalctl -o cat -feu ${daemon} | grep -F 'Host name conflict, retrying with ')
''; '';
in mkIf (cfg.enable && cfg.publish.enable) { in
mkIf (cfg.enable && cfg.publish.enable) {
avahi-daemon = { avahi-daemon = {
serviceConfig = { serviceConfig = {
inherit RestartSec; inherit RestartSec;
}; };
}; };
avahi-daemon-watchdog = { avahi-daemon-watchdog = {
wantedBy = [ daemon ]; wantedBy = [daemon];
serviceConfig = { serviceConfig = {
Type = mkOptionDefault "exec"; Type = mkOptionDefault "exec";
ExecStart = [ ExecStart = [

View file

@ -28,8 +28,7 @@
users.users.root = { users.users.root = {
hashedPassword = "$6$i28yOXoo$/WokLdKds5ZHtJHcuyGrH2WaDQQk/2Pj0xRGLgS8UcmY2oMv3fw2j/85PRpsJJwCB2GBRYRK5LlvdTleHd3mB."; hashedPassword = "$6$i28yOXoo$/WokLdKds5ZHtJHcuyGrH2WaDQQk/2Pj0xRGLgS8UcmY2oMv3fw2j/85PRpsJJwCB2GBRYRK5LlvdTleHd3mB.";
openssh.authorizedKeys.keys = with pkgs.lib; openssh.authorizedKeys.keys = with pkgs.lib; (concatLists (mapAttrsToList
(concatLists (mapAttrsToList
(name: user: (name: user:
if elem "wheel" user.extraGroups if elem "wheel" user.extraGroups
then user.openssh.authorizedKeys.keys then user.openssh.authorizedKeys.keys

View file

@ -1,3 +1,3 @@
{ config, ... }: { {config, ...}: {
documentation.nixos.enable = false; documentation.nixos.enable = false;
} }

View file

@ -1,5 +1,7 @@
{ config, pkgs, ... }:
{ {
environment.systemPackages = [ pkgs.buildPackages.buildPackages.kitty.terminfo ]; config,
pkgs,
...
}: {
environment.systemPackages = [pkgs.buildPackages.buildPackages.kitty.terminfo];
} }

View file

@ -1,4 +1,10 @@
{ config, options, lib, inputs, ... }: let {
config,
options,
lib,
inputs,
...
}: let
inherit (lib.modules) mkIf mkDefault; inherit (lib.modules) mkIf mkDefault;
hasSops = options ? sops; hasSops = options ? sops;
in { in {
@ -25,7 +31,8 @@ in {
experimental-features = lib.optional (lib.versionAtLeast config.nix.package.version "2.4") "nix-command flakes"; experimental-features = lib.optional (lib.versionAtLeast config.nix.package.version "2.4") "nix-command flakes";
substituters = [ substituters = [
"https://gensokyo-infrastructure.cachix.org" "https://gensokyo-infrastructure.cachix.org"
"https://arc.cachix.org" "https://kittywitch.cachix.org" "https://arc.cachix.org"
"https://kittywitch.cachix.org"
"https://nix-community.cachix.org" "https://nix-community.cachix.org"
]; ];
trusted-public-keys = [ trusted-public-keys = [
@ -36,7 +43,7 @@ in {
"ryantrinkle.com-1:JJiAKaRv9mWgpVAz8dwewnZe0AzzEAzPkagE9SP5NWI=" "ryantrinkle.com-1:JJiAKaRv9mWgpVAz8dwewnZe0AzzEAzPkagE9SP5NWI="
]; ];
auto-optimise-store = true; auto-optimise-store = true;
trusted-users = [ "root" "@wheel" ]; trusted-users = ["root" "@wheel"];
}; };
extraOptions = mkIf hasSops '' extraOptions = mkIf hasSops ''
!include ${config.sops.secrets.github-access-token-public.path} !include ${config.sops.secrets.github-access-token-public.path}
@ -47,7 +54,11 @@ in {
options = mkDefault "--delete-older-than 7d"; options = mkDefault "--delete-older-than 7d";
}; };
}; };
${if hasSops then "sops" else null}.secrets.github-access-token-public = { ${
if hasSops
then "sops"
else null
}.secrets.github-access-token-public = {
sopsFile = mkDefault ../secrets/nix.yaml; sopsFile = mkDefault ../secrets/nix.yaml;
group = mkDefault "users"; group = mkDefault "users";
mode = mkDefault "0644"; mode = mkDefault "0644";

View file

@ -1,7 +1,4 @@
{ {inputs, ...}: {
inputs,
...
}: {
nixpkgs = { nixpkgs = {
overlays = [ overlays = [
inputs.arcexprs.overlays.default inputs.arcexprs.overlays.default

View file

@ -1,11 +1,16 @@
{ config, lib, pkgs, ... }:
{ {
environment.systemPackages = with pkgs; [ config,
lib,
pkgs,
...
}: {
environment.systemPackages = with pkgs;
[
neofetch neofetch
smartmontools smartmontools
hddtemp hddtemp
lm_sensors lm_sensors
gnupg gnupg
] ++ (lib.optional config.programs.gnupg.agent.enable pinentry-curses); ]
++ (lib.optional config.programs.gnupg.agent.enable pinentry-curses);
} }

View file

@ -1,6 +1,4 @@
{ config, ... }: {config, ...}: {
{
programs.zsh = { programs.zsh = {
enable = true; enable = true;
enableCompletion = true; enableCompletion = true;

View file

@ -29,7 +29,7 @@ in {
}; };
networking.firewall = { networking.firewall = {
allowedTCPPorts = [publicPort]; allowedTCPPorts = [publicPort];
interfaces.local.allowedTCPPorts = [ 22 ]; interfaces.local.allowedTCPPorts = [22];
}; };
programs.mosh.enable = true; programs.mosh.enable = true;

View file

@ -1,3 +1,3 @@
{ config, ... }: { {config, ...}: {
services.tzupdate.enable = true; services.tzupdate.enable = true;
} }

View file

@ -1,6 +1,4 @@
{ pkgs, ... }: {pkgs, ...}: {
{
environment.systemPackages = [ environment.systemPackages = [
pkgs.buildPackages.rxvt-unicode-unwrapped.terminfo pkgs.buildPackages.rxvt-unicode-unwrapped.terminfo
]; ];

View file

@ -1,12 +1,9 @@
{ {lib, ...}: let
lib,
...
}: let
inherit (lib.modules) mkDefault; inherit (lib.modules) mkDefault;
in { in {
services.bazarr = { services.bazarr = {
enable = mkDefault true; enable = mkDefault true;
listenPort = mkDefault 6767; listenPort = mkDefault 6767;
}; };
users.users.bazarr.extraGroups = [ "kyuuto" ]; users.users.bazarr.extraGroups = ["kyuuto"];
} }

View file

@ -14,26 +14,30 @@ in {
protocol = mkDefault "cloudflare"; protocol = mkDefault "cloudflare";
zone = mkDefault config.networking.domain; zone = mkDefault config.networking.domain;
use = "no"; use = "no";
domains = [ ]; domains = [];
extraConfig = mkMerge [ (mkIf config.networking.enableIPv6 '' extraConfig = mkMerge [
(mkIf config.networking.enableIPv6 ''
usev6=webv6, webv6=https://ipv6.nsupdate.info/myip usev6=webv6, webv6=https://ipv6.nsupdate.info/myip
'') '' '')
''
usev4=webv4, webv4=https://ipv4.nsupdate.info/myip usev4=webv4, webv4=https://ipv4.nsupdate.info/myip
max-interval=1d max-interval=1d
'' ]; ''
];
passwordFile = config.sops.secrets.dyndns_cloudflare_token.path; passwordFile = config.sops.secrets.dyndns_cloudflare_token.path;
}; };
systemd.services.ddclient = mkIf cfg.enable rec { systemd.services.ddclient = mkIf cfg.enable rec {
wants = [ "network-online.target" ]; wants = ["network-online.target"];
after = wants; after = wants;
wantedBy = mkForce [ ]; wantedBy = mkForce [];
serviceConfig = { serviceConfig = {
ExecStartPre = let ExecStartPre = let
inherit (config.systemd.services.ddclient.serviceConfig) RuntimeDirectory; inherit (config.systemd.services.ddclient.serviceConfig) RuntimeDirectory;
prestart-domains = pkgs.writeShellScript "ddclient-prestart-domains" '' prestart-domains = pkgs.writeShellScript "ddclient-prestart-domains" ''
cat ${config.sops.secrets.dyndns_ddclient_domains.path} >> /run/${RuntimeDirectory}/ddclient.conf cat ${config.sops.secrets.dyndns_ddclient_domains.path} >> /run/${RuntimeDirectory}/ddclient.conf
''; '';
in mkAfter [ "!${prestart-domains}" ]; in
mkAfter ["!${prestart-domains}"];
TimeoutStartSec = 90; TimeoutStartSec = 90;
LogFilterPatterns = [ LogFilterPatterns = [
"~WARNING" "~WARNING"

View file

@ -42,28 +42,32 @@ in {
parent = builtins.dirOf downloadDir; parent = builtins.dirOf downloadDir;
hasCompletedSubdir = completedDir != null && hasPrefix parent completedDir; hasCompletedSubdir = completedDir != null && hasPrefix parent completedDir;
completedSubdir = removePrefix parent completedDir; completedSubdir = removePrefix parent completedDir;
download = if hasCompletedSubdir then { download =
if hasCompletedSubdir
then {
path = parent; path = parent;
subdirectories = [ subdirectories = [
(builtins.baseNameOf downloadDir) (builtins.baseNameOf downloadDir)
completedSubdir completedSubdir
]; ];
} else { }
else {
path = downloadDir; path = downloadDir;
}; };
completed = { completed = {
path = cfg.config.move_completed_path; path = cfg.config.move_completed_path;
}; };
in mkIf cfg.enable (mkAfter [ in
mkIf cfg.enable (mkAfter [
download download
(mkIf (completedDir != null && !hasCompletedSubdir) completed) (mkIf (completedDir != null && !hasCompletedSubdir) completed)
]); ]);
users.users = mkIf cfg.enable (mkMerge [ users.users = mkIf cfg.enable (mkMerge [
{ {
deluge.extraGroups = [ "kyuuto" ]; deluge.extraGroups = ["kyuuto"];
} }
(mkIf mediatomb.enable { (mkIf mediatomb.enable {
${mediatomb.user}.extraGroups = [ cfg.group ]; ${mediatomb.user}.extraGroups = [cfg.group];
}) })
]); ]);
} }

View file

@ -14,7 +14,9 @@
genZoneAttrs = prefix: f: listToAttrs (genZone (i: nameValuePair "${prefix}${toString i}" (f i))); genZoneAttrs = prefix: f: listToAttrs (genZone (i: nameValuePair "${prefix}${toString i}" (f i)));
in { in {
options.services.github-runner-zone = with lib.types; { options.services.github-runner-zone = with lib.types; {
enable = mkEnableOption "github-runners.zone" // { enable =
mkEnableOption "github-runners.zone"
// {
default = true; default = true;
}; };
targetName = mkOption { targetName = mkOption {
@ -64,7 +66,7 @@ in {
enable = mkDefault true; enable = mkDefault true;
ephemeral = mkDefault cfg.ephemeral; ephemeral = mkDefault cfg.ephemeral;
replace = mkDefault true; replace = mkDefault true;
extraLabels = [ "ubuntu-latest" ]; extraLabels = ["ubuntu-latest"];
tokenFile = mkDefault config.sops.secrets.github-runner-gensokyo-zone-token.path; tokenFile = mkDefault config.sops.secrets.github-runner-gensokyo-zone-token.path;
url = mkDefault "https://github.com/gensokyo-zone"; url = mkDefault "https://github.com/gensokyo-zone";
group = mkDefault cfg.group; group = mkDefault cfg.group;
@ -73,9 +75,9 @@ in {
}; };
networkNamespace.name = mkIf (cfg.networkNamespace.name != null) (mkDefault cfg.networkNamespace.name); networkNamespace.name = mkIf (cfg.networkNamespace.name != null) (mkDefault cfg.networkNamespace.name);
serviceSettings = { serviceSettings = {
wantedBy = [ "${cfg.targetName}.target" ]; wantedBy = ["${cfg.targetName}.target"];
unitConfig = { unitConfig = {
StopPropagatedFrom = [ "${cfg.targetName}.target" ]; StopPropagatedFrom = ["${cfg.targetName}.target"];
}; };
}; };
serviceOverrides = mkIf (!cfg.dynamicUser) { serviceOverrides = mkIf (!cfg.dynamicUser) {
@ -88,7 +90,8 @@ in {
}; };
}; };
services.github-runners = genZoneAttrs cfg.keyPrefix (i: mkMerge [ services.github-runners = genZoneAttrs cfg.keyPrefix (i:
mkMerge [
(unmerged.merge cfg.runnerSettings) (unmerged.merge cfg.runnerSettings)
{ {
name = mkDefault "${cfg.namePrefix}${toString i}"; name = mkDefault "${cfg.namePrefix}${toString i}";
@ -106,13 +109,13 @@ in {
}; };
}; };
targets.${cfg.targetName} = { targets.${cfg.targetName} = {
wantedBy = [ "multi-user.target" ]; wantedBy = ["multi-user.target"];
}; };
}; };
users = mkIf cfg.enable { users = mkIf cfg.enable {
groups = mkIf (cfg.group != null) { groups = mkIf (cfg.group != null) {
${toString cfg.group} = { }; ${toString cfg.group} = {};
}; };
users = mkMerge [ users = mkMerge [
(mkIf (!cfg.dynamicUser) (genZoneAttrs cfg.userPrefix (i: { (mkIf (!cfg.dynamicUser) (genZoneAttrs cfg.userPrefix (i: {

View file

@ -85,7 +85,8 @@ in {
]; ];
entity_config = {}; entity_config = {};
}; };
homekit = [ { homekit = [
{
name = "Tewi"; name = "Tewi";
port = 21063; port = 21063;
filter = let filter = let
@ -95,7 +96,8 @@ in {
include_entities = "!include homekit_include_entities.yaml"; include_entities = "!include homekit_include_entities.yaml";
}; };
entity_config = "!include homekit_entity_config.yaml"; entity_config = "!include homekit_entity_config.yaml";
} ]; }
];
tts = [ tts = [
{ {
platform = "google_translate"; platform = "google_translate";

View file

@ -1,4 +1,8 @@
{ config, lib, ... }: let {
config,
lib,
...
}: let
inherit (lib.modules) mkIf mkDefault mkForce; inherit (lib.modules) mkIf mkDefault mkForce;
cfg = config.services.invidious; cfg = config.services.invidious;
in { in {
@ -6,12 +10,13 @@ in {
commonSecret = { commonSecret = {
sopsFile = ./secrets/invidious.yaml; sopsFile = ./secrets/invidious.yaml;
owner = "invidious"; owner = "invidious";
}; in { };
in {
invidious_db_password = commonSecret; invidious_db_password = commonSecret;
invidious_hmac_key = commonSecret; invidious_hmac_key = commonSecret;
}; };
networking.firewall.interfaces.local.allowedTCPPorts = [ cfg.port ]; networking.firewall.interfaces.local.allowedTCPPorts = [cfg.port];
users.groups.invidious = {}; users.groups.invidious = {};
users.users.invidious = { users.users.invidious = {
isSystemUser = true; isSystemUser = true;

View file

@ -34,7 +34,7 @@ in {
}; };
gameLibraries = mkOption { gameLibraries = mkOption {
type = listOf str; type = listOf str;
default = [ "PC" ]; default = ["PC"];
}; };
}; };
@ -42,10 +42,19 @@ in {
kyuuto = { kyuuto = {
gameLibraries = [ gameLibraries = [
"PC" "PC"
"Wii" "Gamecube" "N64" "SNES" "NES" "Wii"
"NDS" "GBA" "GBC" "Gamecube"
"PS3" "PS2" "PS1" "N64"
"PSVita" "PSP" "SNES"
"NES"
"NDS"
"GBA"
"GBC"
"PS3"
"PS2"
"PS1"
"PSVita"
"PSP"
"Genesis" "Genesis"
]; ];
}; };
@ -74,7 +83,7 @@ in {
{ {
${cfg.shareDir} = mkMerge [ ${cfg.shareDir} = mkMerge [
shared shared
{ group = "peeps"; } {group = "peeps";}
]; ];
${cfg.transferDir} = shared; ${cfg.transferDir} = shared;
${cfg.libraryDir} = shared; ${cfg.libraryDir} = shared;
@ -108,14 +117,19 @@ in {
}; };
users = let users = let
mapId = id: if config.proxmoxLXC.privileged or true then 100000 + id else id; mapId = id:
if config.proxmoxLXC.privileged or true
then 100000 + id
else id;
mkDummyUsers = { mkDummyUsers = {
name, name,
group ? name, group ? name,
enable ? !config.services.${serviceName}.enable, serviceName ? name, enable ? !config.services.${serviceName}.enable,
serviceName ? name,
uid ? config.ids.uids.${name}, uid ? config.ids.uids.${name},
gid ? config.ids.gids.${group}, gid ? config.ids.gids.${group},
}: mkIf enable { }:
mkIf enable {
users.${name} = { users.${name} = {
group = mkIf (group != null) group; group = mkIf (group != null) group;
uid = mapId uid; uid = mapId uid;
@ -125,11 +139,12 @@ in {
gid = mapId gid; gid = mapId gid;
}; };
}; };
in mkMerge [ in
(mkDummyUsers { name = "deluge"; }) mkMerge [
(mkDummyUsers { name = "radarr"; }) (mkDummyUsers {name = "deluge";})
(mkDummyUsers { name = "sonarr"; }) (mkDummyUsers {name = "radarr";})
(mkDummyUsers { name = "lidarr"; }) (mkDummyUsers {name = "sonarr";})
(mkDummyUsers {name = "lidarr";})
]; ];
}; };
} }

View file

@ -1,4 +1,3 @@
{ {
config, config,
lib, lib,

View file

@ -10,7 +10,9 @@
cfg = kyuuto.opl; cfg = kyuuto.opl;
in { in {
options.kyuuto.opl = with lib.types; { options.kyuuto.opl = with lib.types; {
enable = mkEnableOption "hosting" // { enable =
mkEnableOption "hosting"
// {
default = config.services.samba.enable; default = config.services.samba.enable;
}; };
user = mkOption { user = mkOption {
@ -39,9 +41,12 @@ in {
}; };
shares.opl = let shares.opl = let
inherit (config.networking.access) cidrForNetwork; inherit (config.networking.access) cidrForNetwork;
localAddrs = cidrForNetwork.loopback.all ++ cidrForNetwork.local.all localAddrs =
cidrForNetwork.loopback.all
++ cidrForNetwork.local.all
++ lib.optionals config.services.tailscale.enable cidrForNetwork.tail.all; ++ lib.optionals config.services.tailscale.enable cidrForNetwork.tail.all;
in mkIf cfg.enable { in
mkIf cfg.enable {
comment = "Kyuuto Media OPL"; comment = "Kyuuto Media OPL";
path = cfg.rootDir; path = cfg.rootDir;
writeable = true; writeable = true;

View file

@ -1,4 +1,3 @@
{ {
config, config,
lib, lib,
@ -9,15 +8,19 @@
inherit (config.networking.access) cidrForNetwork; inherit (config.networking.access) cidrForNetwork;
inherit (config) kyuuto; inherit (config) kyuuto;
cfg = config.services.samba; cfg = config.services.samba;
localAddrs = cidrForNetwork.loopback.all ++ cidrForNetwork.local.all localAddrs =
cidrForNetwork.loopback.all
++ cidrForNetwork.local.all
++ optionals config.services.tailscale.enable cidrForNetwork.tail.all; ++ optionals config.services.tailscale.enable cidrForNetwork.tail.all;
guestUsers = mkIf cfg.guest.enable [ cfg.guest.user ]; guestUsers = mkIf cfg.guest.enable [cfg.guest.user];
kyuuto-media = { kyuuto-media = {
"create mask" = "0664"; "create mask" = "0664";
"force directory mode" = "3000"; "force directory mode" = "3000";
"directory mask" = "7775"; "directory mask" = "7775";
}; };
kyuuto-library = kyuuto-media // { kyuuto-library =
kyuuto-media
// {
"acl group control" = true; "acl group control" = true;
}; };
in { in {
@ -35,7 +38,7 @@ in {
public = true; public = true;
"valid users" = mkMerge [ "valid users" = mkMerge [
guestUsers guestUsers
[ "@peeps" ] ["@peeps"]
]; ];
#"guest only" = true; #"guest only" = true;
"hosts allow" = localAddrs; "hosts allow" = localAddrs;
@ -54,10 +57,10 @@ in {
public = true; public = true;
"valid users" = mkMerge [ "valid users" = mkMerge [
guestUsers guestUsers
[ "@kyuuto-peeps" ] ["@kyuuto-peeps"]
]; ];
"read list" = guestUsers; "read list" = guestUsers;
"write list" = [ "@kyuuto-peeps" ]; "write list" = ["@kyuuto-peeps"];
"hosts allow" = localAddrs; "hosts allow" = localAddrs;
} }
]; ];
@ -69,7 +72,7 @@ in {
writeable = true; writeable = true;
public = false; public = false;
browseable = false; browseable = false;
"valid users" = [ "@kyuuto-peeps" ]; "valid users" = ["@kyuuto-peeps"];
} }
]; ];
kyuuto-media = mkMerge [ kyuuto-media = mkMerge [
@ -80,7 +83,7 @@ in {
writeable = true; writeable = true;
public = false; public = false;
browseable = false; browseable = false;
"valid users" = [ "@kyuuto-peeps" ]; "valid users" = ["@kyuuto-peeps"];
} }
]; ];
shared = { shared = {
@ -89,7 +92,7 @@ in {
writeable = true; writeable = true;
public = false; public = false;
browseable = false; browseable = false;
"valid users" = [ "@peeps" ]; "valid users" = ["@peeps"];
"create mask" = "0775"; "create mask" = "0775";
"force create mode" = "0010"; "force create mode" = "0010";
"force directory mode" = "2000"; "force directory mode" = "2000";
@ -99,7 +102,7 @@ in {
writeable = true; writeable = true;
browseable = true; browseable = true;
public = false; public = false;
"valid users" = [ "@peeps" ]; "valid users" = ["@peeps"];
"create mask" = "0664"; "create mask" = "0664";
"force directory mode" = "5000"; "force directory mode" = "5000";
"directory mask" = "7775"; "directory mask" = "7775";
@ -108,5 +111,5 @@ in {
}; };
# give guest users proper access to the transfer share # give guest users proper access to the transfer share
users.users.guest.extraGroups = [ "kyuuto" ]; users.users.guest.extraGroups = ["kyuuto"];
} }

View file

@ -2,5 +2,5 @@ _: {
services.lidarr = { services.lidarr = {
enable = true; enable = true;
}; };
users.users.lidarr.extraGroups = [ "kyuuto" ]; users.users.lidarr.extraGroups = ["kyuuto"];
} }

View file

@ -12,6 +12,6 @@ in {
uuid = mkDefault "082fd344-bf69-5b72-a68f-a5a4d88e76b2"; uuid = mkDefault "082fd344-bf69-5b72-a68f-a5a4d88e76b2";
}; };
config.users.users = mkIf cfg.enable { config.users.users = mkIf cfg.enable {
${cfg.user}.extraGroups = [ "kyuuto" ]; ${cfg.user}.extraGroups = ["kyuuto"];
}; };
} }

View file

@ -29,9 +29,9 @@ in {
idmapd.settings = { idmapd.settings = {
General.Domain = mkDefault config.networking.domain; General.Domain = mkDefault config.networking.domain;
Translation.GSS-Methods = concatStringsSep "," ( Translation.GSS-Methods = concatStringsSep "," (
[ "static" ] ["static"]
++ optional enableLdap "umich_ldap" ++ optional enableLdap "umich_ldap"
++ [ "nsswitch" ] ++ ["nsswitch"]
); );
Static = { Static = {
}; };

View file

@ -1,7 +1,4 @@
{ {lib, ...}: let
lib,
...
}: let
inherit (lib.modules) mkDefault; inherit (lib.modules) mkDefault;
in { in {
services.ombi = { services.ombi = {

View file

@ -1,4 +1,9 @@
{config, lib, pkgs, ...}: let {
config,
lib,
pkgs,
...
}: let
inherit (lib.modules) mkIf mkForce mkDefault; inherit (lib.modules) mkIf mkForce mkDefault;
inherit (lib.strings) escapeShellArg; inherit (lib.strings) escapeShellArg;
cfg = config.services.plex; cfg = config.services.plex;
@ -21,7 +26,8 @@ in {
fi fi
${pkgs.coreutils}/bin/ln -sfT ../Cache "$PLEX_DATADIR/Plex Media Server/Cache" ${pkgs.coreutils}/bin/ln -sfT ../Cache "$PLEX_DATADIR/Plex Media Server/Cache"
''; '';
in mkForce [ in
mkForce [
''!${preStartScript}'' ''!${preStartScript}''
]; ];
# KillMode = "mixed" doesn't behave as expected... # KillMode = "mixed" doesn't behave as expected...

View file

@ -8,7 +8,7 @@
in { in {
services.postgresql = { services.postgresql = {
enable = mkDefault true; enable = mkDefault true;
ensureDatabases = ["hass" "invidious" "dex"]; ensureDatabases = ["hass" "invidious" "dex" "keycloak"];
ensureUsers = [ ensureUsers = [
{ {
name = "hass"; name = "hass";
@ -25,6 +25,11 @@ in {
ensureDBOwnership = true; ensureDBOwnership = true;
authentication.local.allow = true; authentication.local.allow = true;
} }
{
name = "keycloak";
ensureDBOwnership = true;
authentication.local.allow = true;
}
]; ];
}; };

View file

@ -3,5 +3,5 @@ _: {
enable = true; enable = true;
}; };
users.users.radarr.extraGroups = [ "kyuuto" ]; users.users.radarr.extraGroups = ["kyuuto"];
} }

View file

@ -2,5 +2,5 @@ _: {
services.readarr = { services.readarr = {
enable = true; enable = true;
}; };
users.users.readarr.extraGroups = [ "kyuuto" ]; users.users.readarr.extraGroups = ["kyuuto"];
} }

View file

@ -1,7 +1,4 @@
{ {lib, ...}: let
lib,
...
}: let
inherit (lib) mkDefault; inherit (lib) mkDefault;
in { in {
services.kanidm.serverSettings.db_fs_type = mkDefault "zfs"; services.kanidm.serverSettings.db_fs_type = mkDefault "zfs";

View file

@ -7,7 +7,7 @@
inherit (lib.lists) any; inherit (lib.lists) any;
inherit (lib.strings) hasInfix concatMapStringsSep splitString; inherit (lib.strings) hasInfix concatMapStringsSep splitString;
cfg = config.services.samba; cfg = config.services.samba;
hasIpv4 = any (hasInfix ".") config.systemd.network.networks.eth0.address or [ ]; hasIpv4 = any (hasInfix ".") config.systemd.network.networks.eth0.address or [];
in { in {
services.samba = { services.samba = {
enable = mkDefault true; enable = mkDefault true;

View file

@ -1,4 +1,4 @@
postgresql-init: ENC[AES256_GCM,data:fW9g0WKVHTO9blqlEXLJejyQUqC3na/Xh6Il2GNfuX6c2LfRjfFSeour4qt2envtPO+WanGl+ueE1AMck5t02TjqrN4a6DsQpAIGFVE7L4ajp/13Gp308pY4Xu7OKHjkGpzVBATKgLDZkoU8yAkqKZCBEU3d4xegp8pgnsLSpb/LndKiITjhTe2IJOSkIJd9twSsra8JQWRYCW8WjZZ9YOe5nqtU+56b/zb0CxVhhln0jU/3e5s7pfblfou2TnvnFezswjNTIGftNU1wOaxSCA==,iv:hjKNZ4EbPpl5YIcaWJYLKJzxuOmMjL4AtfUeL4vm5QA=,tag:mYcu4cRUnZeLgeISfaxXPQ==,type:str] postgresql-init: ENC[AES256_GCM,data:lbkeMv6PZgB7tEl4VbIYX9VUAgJ6Kcj0jLNyyqxJJcVJPjo1lF2d/i5bFnU1/6aJ2T7ftMW4hefYgrnIMdKXxPPfrHftaEMhl9bfJIsuX2I1CXAasZOhpsmg9Wf2cvXuVYIlqTVssg+3EKW0ejCMdX6OfGdAXvBlio1DQs7YrUc+BjDiEuAUAaaYbz67EYY3dpYQixQGl/8G2w7S897uCXpc1oOh6vbGY4Nl+GGQ7B5xrrbYcdATwfGyYlZYSlIv8feDsLv7Rt+w3o4tTAxcz+8qZ7KZ6sIsu/nUoYeqoT9MJ8uRpWccXKcBVAFSEooUIHUEBA/QsGizAXBgzCnyLDvuv3DOquo2xeMg0kWM8zsF1f9YRyUKqQ==,iv:RKIvggRZlPocygabF0iKNBThBRFG5rlzrIvGjjt7s0o=,tag:U/XUDJs5J8lHB9BJ5/0fFA==,type:str]
sops: sops:
shamir_threshold: 1 shamir_threshold: 1
kms: [] kms: []
@ -33,8 +33,8 @@ sops:
a3l3bUx5NzdqUGd1TEpGY3UvQWt4TU0KB4MAjvI43FaOiGhWTkwPpeMMiAnX4v3L a3l3bUx5NzdqUGd1TEpGY3UvQWt4TU0KB4MAjvI43FaOiGhWTkwPpeMMiAnX4v3L
rLZDdc/vegF10FKTNJdxdq1E7ccMaV1KwjQkJoOJnWe6teKLjGOFkA== rLZDdc/vegF10FKTNJdxdq1E7ccMaV1KwjQkJoOJnWe6teKLjGOFkA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2024-02-19T03:46:45Z" lastmodified: "2024-03-13T21:46:56Z"
mac: ENC[AES256_GCM,data:FMzWnFllHDpgIoDJIKS7aWpUSVNH0+ij0+AIzl3qtjeuzmUUluDtEes6yAR8g/Daq+nxiMRnsse0HfUqZeT0rVVEpqvQB4Wsoq+G9qj8mmEUrHJzjU5rSDWV8uf5F1BsZbvF13VBulh/RWsmWjps+z6vyJ7uM1QjS3hSF2k3hSM=,iv:tpH8XjoTtNzPOOIosObpsvOAzZO7ywK9xjow3xTOJqY=,tag:BTzezbH9zZDZBzy1x+AJ1w==,type:str] mac: ENC[AES256_GCM,data:rEtRHX3PH1B+uoR82lDH3ACKHPbhxy+y7B9YgR6TzPSU4yIaTSqSK51eLJZoUtW6UTl6QDcTrsKDA8lGu9M/Ohfx8ayp6rkX63H/hkl0h6YaQmWDAQoNAAEWqfJ9r8O8tKKpE6qF/rw4c4KpuA5ONufOl9qj1KSgFzz0WHaKtWk=,iv:TUBAe62dmF6FAjZOPaxwzQjWL21TdWQG0YyuXJGgtk8=,tag:dewWivfnZO30Np2gajwLIw==,type:str]
pgp: pgp:
- created_at: "2024-01-19T19:08:55Z" - created_at: "2024-01-19T19:08:55Z"
enc: |- enc: |-

View file

@ -2,5 +2,5 @@ _: {
services.sonarr = { services.sonarr = {
enable = true; enable = true;
}; };
users.users.sonarr.extraGroups = [ "kyuuto" ]; users.users.sonarr.extraGroups = ["kyuuto"];
} }

View file

@ -1,8 +1,13 @@
{ lib, inputs, ... }: with lib; { {
lib,
inputs,
...
}:
with lib; {
imports = [ imports = [
inputs.sops-nix.nixosModules.sops inputs.sops-nix.nixosModules.sops
]; ];
sops = { sops = {
age.sshKeyPaths = mkDefault [ "/etc/ssh/ssh_host_ed25519_key" ]; age.sshKeyPaths = mkDefault ["/etc/ssh/ssh_host_ed25519_key"];
}; };
} }

View file

@ -1,7 +1,4 @@
{ {lib, ...}: let
lib,
...
}: let
inherit (lib.modules) mkDefault; inherit (lib.modules) mkDefault;
in { in {
services.steam.accountSwitch = { services.steam.accountSwitch = {

View file

@ -1,15 +1,12 @@
{ {lib, ...}: let
lib,
...
}: let
inherit (lib.modules) mkDefault; inherit (lib.modules) mkDefault;
in { in {
services.steam.beatsaber = { services.steam.beatsaber = {
enable = mkDefault true; enable = mkDefault true;
defaultVersion = mkDefault "1.29.0"; defaultVersion = mkDefault "1.29.0";
versions = { versions = {
"1.29.0" = { }; "1.29.0" = {};
"1.34.2" = { }; "1.34.2" = {};
}; };
}; };
} }

View file

@ -1,4 +1,4 @@
{ config, ... }: { {config, ...}: {
services.syncthing = { services.syncthing = {
enable = true; enable = true;
relay.enable = true; relay.enable = true;

View file

@ -10,7 +10,8 @@ in {
enable = mkDefault true; enable = mkDefault true;
user = mkDefault "root"; user = mkDefault "root";
mqtt = { mqtt = {
url = mkDefault (if config.services.mosquitto.enable url = mkDefault (
if config.services.mosquitto.enable
then "tcp://localhost:1883" then "tcp://localhost:1883"
else "tcp://mqtt.local.${config.networking.domain}:1883" else "tcp://mqtt.local.${config.networking.domain}:1883"
); );

View file

@ -1,4 +1,8 @@
{config, lib, ...}: let {
config,
lib,
...
}: let
inherit (lib.modules) mkIf mkDefault; inherit (lib.modules) mkIf mkDefault;
cfg = config.services.tautulli; cfg = config.services.tautulli;
in { in {

View file

@ -1,22 +1,22 @@
{ config, ... }: {config, ...}: {
users.users.arc = {name, ...}: {
{
users.users.arc = { name, ... }: {
uid = 8001; uid = 8001;
isNormalUser = true; isNormalUser = true;
autoSubUidGidRange = false; autoSubUidGidRange = false;
group = name; group = name;
extraGroups = [ extraGroups = [
"users" "peeps" "users"
"peeps"
"kyuuto" "kyuuto"
"steamaccount" "beatsaber" "steamaccount"
"beatsaber"
"wheel" "wheel"
]; ];
openssh.authorizedKeys.keys = [ openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ8Z6briIboxIdedPGObEWB6QEQkvxKvnMW/UVU9t/ac mew-pgp" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ8Z6briIboxIdedPGObEWB6QEQkvxKvnMW/UVU9t/ac mew-pgp"
]; ];
}; };
users.groups.arc = { name, ... }: { users.groups.arc = {name, ...}: {
gid = config.users.users.${name}.uid; gid = config.users.users.${name}.uid;
}; };
} }

View file

@ -1,17 +1,16 @@
{ config, ... }: {config, ...}: {
users.users.connieallure = {name, ...}: {
{
users.users.connieallure = { name, ... }: {
uid = 8003; uid = 8003;
isNormalUser = true; isNormalUser = true;
autoSubUidGidRange = false; autoSubUidGidRange = false;
group = name; group = name;
extraGroups = [ extraGroups = [
"users" "peeps" "users"
"peeps"
"kyuuto" "kyuuto"
]; ];
}; };
users.groups.connieallure = { name, ... }: { users.groups.connieallure = {name, ...}: {
gid = config.users.users.${name}.uid; gid = config.users.users.${name}.uid;
}; };
} }

View file

@ -1,18 +1,18 @@
{ config, ... }: {config, ...}: {
users.users.kaosubaloo = {name, ...}: {
{
users.users.kaosubaloo = { name, ... }: {
uid = 8002; uid = 8002;
isNormalUser = true; isNormalUser = true;
autoSubUidGidRange = false; autoSubUidGidRange = false;
group = name; group = name;
extraGroups = [ extraGroups = [
"users" "peeps" "users"
"peeps"
"kyuuto" "kyuuto"
"steamaccount" "beatsaber" "steamaccount"
"beatsaber"
]; ];
}; };
users.groups.kaosubaloo = { name, ... }: { users.groups.kaosubaloo = {name, ...}: {
gid = config.users.users.${name}.uid; gid = config.users.users.${name}.uid;
}; };
} }

View file

@ -1,25 +1,25 @@
{ config, ... }: {config, ...}: {
users.users.kat = {name, ...}: {
{
users.users.kat = { name, ... }: {
uid = 8000; uid = 8000;
isNormalUser = true; isNormalUser = true;
autoSubUidGidRange = false; autoSubUidGidRange = false;
group = name; group = name;
extraGroups = [ extraGroups = [
"users" "peeps" "users"
"peeps"
"kyuuto" "kyuuto"
"steamaccount" "beatsaber" "steamaccount"
"beatsaber"
"wheel" "wheel"
]; ];
openssh.authorizedKeys.keys = [ openssh.authorizedKeys.keys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCocjQqiDIvzq+Qu3jkf7FXw5piwtvZ1Mihw9cVjdVcsra3U2c9WYtYrA3rS50N3p00oUqQm9z1KUrvHzdE+03ZCrvaGdrtYVsaeoCuuvw7qxTQRbItTAEsfRcZLQ5c1v/57HNYNEsjVrt8VukMPRXWgl+lmzh37dd9w45cCY1QPi+JXQQ/4i9Vc3aWSe4X6PHOEMSBHxepnxm5VNHm4PObGcVbjBf0OkunMeztd1YYA9sEPyEK3b8IHxDl34e5t6NDLCIDz0N/UgzCxSxoz+YJ0feQuZtud/YLkuQcMxW2dSGvnJ0nYy7SA5DkW1oqcy6CGDndHl5StOlJ1IF9aGh0gGkx5SRrV7HOGvapR60RphKrR5zQbFFka99kvSQgOZqSB3CGDEQGHv8dXKXIFlzX78jjWDOBT67vA/M9BK9FS2iNnBF5x6shJ9SU5IK4ySxq8qvN7Us8emkN3pyO8yqgsSOzzJT1JmWUAx0tZWG/BwKcFBHfceAPQl6pwxx28TM3BTBRYdzPJLTkAy48y6iXW6UYdfAPlShy79IYjQtEThTuIiEzdzgYdros0x3PDniuAP0KOKMgbikr0gRa6zahPjf0qqBnHeLB6nHAfaVzI0aNbhOg2bdOueE1FX0x48sjKqjOpjlIfq4WeZp9REr2YHEsoLFOBfgId5P3BPtpBQ== yubikey5" "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCocjQqiDIvzq+Qu3jkf7FXw5piwtvZ1Mihw9cVjdVcsra3U2c9WYtYrA3rS50N3p00oUqQm9z1KUrvHzdE+03ZCrvaGdrtYVsaeoCuuvw7qxTQRbItTAEsfRcZLQ5c1v/57HNYNEsjVrt8VukMPRXWgl+lmzh37dd9w45cCY1QPi+JXQQ/4i9Vc3aWSe4X6PHOEMSBHxepnxm5VNHm4PObGcVbjBf0OkunMeztd1YYA9sEPyEK3b8IHxDl34e5t6NDLCIDz0N/UgzCxSxoz+YJ0feQuZtud/YLkuQcMxW2dSGvnJ0nYy7SA5DkW1oqcy6CGDndHl5StOlJ1IF9aGh0gGkx5SRrV7HOGvapR60RphKrR5zQbFFka99kvSQgOZqSB3CGDEQGHv8dXKXIFlzX78jjWDOBT67vA/M9BK9FS2iNnBF5x6shJ9SU5IK4ySxq8qvN7Us8emkN3pyO8yqgsSOzzJT1JmWUAx0tZWG/BwKcFBHfceAPQl6pwxx28TM3BTBRYdzPJLTkAy48y6iXW6UYdfAPlShy79IYjQtEThTuIiEzdzgYdros0x3PDniuAP0KOKMgbikr0gRa6zahPjf0qqBnHeLB6nHAfaVzI0aNbhOg2bdOueE1FX0x48sjKqjOpjlIfq4WeZp9REr2YHEsoLFOBfgId5P3BPtpBQ== yubikey5"
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDPsu3vNsvBb/G+wALpstD/DnoRZ3fipAs00jtl8rzDuv96RlS7AJr4aNvG6Pt2D9SYn2wVLaiw+76mz2gOycH9/N+VCvL4/0MN9uqj+7XIcxNRo0gHVOblmi2bOXcmGKh3eRwHj1xyDwRxo9WIuBEP2bPpDPz75OXRtEdlTgvky7siSguQxJu03cb0p9hNAYhUoohNXyWW2CjDCLUQVE1+QRVUzsKq3KkPy0cHYgmZC1gRSMQyKpMt72L5tayLz3Tp/zrshucc+QO5IJeZdqMxsNAcvALsysT1J5EqxZoYH9VpWLRhSgVD6Nvn853pycJAlXQxgOCpSD3/v/JbgUe5NE+ci0o7NMy5IiHUv2gQMRIEhwBHlRGwokUPL9upx0lsjaEiPya5xQqqDKRom87xytM778ANS5CuMdQMWg9qVbpHZUHMjA0QmNkjPgq71pUDXHk5L4mZuS8wVjyjnvlw68yIJuHEc8P7QiLcjvRHFS2L9Ck8NRmPDTQXlQi9kk6LmMyu6fdevR/kZL21b+xO1e2DMyxBbNDTot8luppiiL8adgUDMwptpIne7JCWB1o9NFCbXUVgwuCCYBif6pOGSc6bGo1JTAKMflRlcy6Mi3t5H0mR2lj/sCSTWwTlP5FM4aPIq08NvW6PeuK1bFJY9fIgTwVsUnbAKOhmsMt62w== cardno:12 078 454" "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDPsu3vNsvBb/G+wALpstD/DnoRZ3fipAs00jtl8rzDuv96RlS7AJr4aNvG6Pt2D9SYn2wVLaiw+76mz2gOycH9/N+VCvL4/0MN9uqj+7XIcxNRo0gHVOblmi2bOXcmGKh3eRwHj1xyDwRxo9WIuBEP2bPpDPz75OXRtEdlTgvky7siSguQxJu03cb0p9hNAYhUoohNXyWW2CjDCLUQVE1+QRVUzsKq3KkPy0cHYgmZC1gRSMQyKpMt72L5tayLz3Tp/zrshucc+QO5IJeZdqMxsNAcvALsysT1J5EqxZoYH9VpWLRhSgVD6Nvn853pycJAlXQxgOCpSD3/v/JbgUe5NE+ci0o7NMy5IiHUv2gQMRIEhwBHlRGwokUPL9upx0lsjaEiPya5xQqqDKRom87xytM778ANS5CuMdQMWg9qVbpHZUHMjA0QmNkjPgq71pUDXHk5L4mZuS8wVjyjnvlw68yIJuHEc8P7QiLcjvRHFS2L9Ck8NRmPDTQXlQi9kk6LmMyu6fdevR/kZL21b+xO1e2DMyxBbNDTot8luppiiL8adgUDMwptpIne7JCWB1o9NFCbXUVgwuCCYBif6pOGSc6bGo1JTAKMflRlcy6Mi3t5H0mR2lj/sCSTWwTlP5FM4aPIq08NvW6PeuK1bFJY9fIgTwVsUnbAKOhmsMt62w== cardno:12 078 454"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII74JrgGsDQ6r7tD7+k3ykxXV7DpeeFRscPMxrBsDPhz kat@goliath" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII74JrgGsDQ6r7tD7+k3ykxXV7DpeeFRscPMxrBsDPhz kat@goliath"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDkeBFF4xxZgeURLzNHcvUFxImmkQ3pxXtpj3mtSyHXB kat@koishi" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDkeBFF4xxZgeURLzNHcvUFxImmkQ3pxXtpj3mtSyHXB kat@koishi"
]; ];
}; };
users.groups.kat = { name, ... }: { users.groups.kat = {name, ...}: {
gid = config.users.users.${name}.uid; gid = config.users.users.${name}.uid;
}; };
} }

View file

@ -1,8 +1,10 @@
{inputs, system}: { {
inputs,
system,
}: {
pkgs = import inputs.nixpkgs { pkgs = import inputs.nixpkgs {
inherit system; inherit system;
overlays = overlays = [
[
inputs.deploy-rs.overlay inputs.deploy-rs.overlay
inputs.arcexprs.overlays.default inputs.arcexprs.overlays.default
(final: prev: { (final: prev: {

View file

@ -12,7 +12,7 @@
export NF_CONFIG_ROOT=''${NF_CONFIG_ROOT-${toString ../.}} export NF_CONFIG_ROOT=''${NF_CONFIG_ROOT-${toString ../.}}
''; '';
exportsSsh = '' exportsSsh = ''
export PATH="${makeBinPath [ packages.nf-hostname packages.nf-sshopts ]}:$PATH" export PATH="${makeBinPath [packages.nf-hostname packages.nf-sshopts]}:$PATH"
''; '';
exportsFmtNix = '' exportsFmtNix = ''
NF_NIX_BLACKLIST_DIRS=(${string.concatMapSep " " string.escapeShellArg fmt.nix.blacklistDirs}) NF_NIX_BLACKLIST_DIRS=(${string.concatMapSep " " string.escapeShellArg fmt.nix.blacklistDirs})
@ -20,10 +20,15 @@
NF_NIX_WHITELIST_FILES=(${string.concatMapSep " " string.escapeShellArg fmt.nix.whitelist}) NF_NIX_WHITELIST_FILES=(${string.concatMapSep " " string.escapeShellArg fmt.nix.whitelist})
''; '';
output = { output = {
inherit (pkgs.buildPackages) inherit
terraform tflint (pkgs.buildPackages)
alejandra deadnix statix terraform
ssh-to-age jq tflint
alejandra
deadnix
statix
ssh-to-age
jq
; ;
inherit (inputs.deploy-rs.packages.${system}) deploy-rs; inherit (inputs.deploy-rs.packages.${system}) deploy-rs;
nf-deploy = pkgs.writeShellScriptBin "nf-deploy" '' nf-deploy = pkgs.writeShellScriptBin "nf-deploy" ''
@ -52,7 +57,8 @@
INPUT_INFRA_CT_CONFIG = reisen + "/bin/ct-config.sh"; INPUT_INFRA_CT_CONFIG = reisen + "/bin/ct-config.sh";
}; };
inputVars = set.mapToValues (key: path: ''${key}="$(base64 -w0 < ${path})"'') inputAttrs; inputVars = set.mapToValues (key: path: ''${key}="$(base64 -w0 < ${path})"'') inputAttrs;
in pkgs.writeShellScriptBin "nf-setup-node" '' in
pkgs.writeShellScriptBin "nf-setup-node" ''
${exports} ${exports}
NF_SETUP_INPUTS=( NF_SETUP_INPUTS=(
${string.intercalate "\n" inputVars} ${string.intercalate "\n" inputVars}
@ -65,13 +71,13 @@
''; '';
nf-sshopts = pkgs.writeShellScriptBin "nf-sshopts" '' nf-sshopts = pkgs.writeShellScriptBin "nf-sshopts" ''
${exports} ${exports}
export PATH="$PATH:${makeBinPath [ pkgs.jq ]}" export PATH="$PATH:${makeBinPath [pkgs.jq]}"
source ${../ci/sshopts.sh} source ${../ci/sshopts.sh}
''; '';
nf-sops-keyscan = pkgs.writeShellScriptBin "nf-sops-keyscan" '' nf-sops-keyscan = pkgs.writeShellScriptBin "nf-sops-keyscan" ''
${exports} ${exports}
${exportsSsh} ${exportsSsh}
export PATH="$PATH:${makeBinPath [ pkgs.ssh-to-age ]}" export PATH="$PATH:${makeBinPath [pkgs.ssh-to-age]}"
source ${../ci/sops-keyscan.sh} source ${../ci/sops-keyscan.sh}
''; '';
nf-ssh = pkgs.writeShellScriptBin "nf-ssh" '' nf-ssh = pkgs.writeShellScriptBin "nf-ssh" ''
@ -94,39 +100,39 @@
''; '';
nf-generate = pkgs.writeShellScriptBin "nf-generate" '' nf-generate = pkgs.writeShellScriptBin "nf-generate" ''
${exports} ${exports}
export PATH="$PATH:${makeBinPath [ pkgs.jq ]}" export PATH="$PATH:${makeBinPath [pkgs.jq]}"
source ${../ci/generate.sh} source ${../ci/generate.sh}
''; '';
nf-statix = pkgs.writeShellScriptBin "nf-statix" '' nf-statix = pkgs.writeShellScriptBin "nf-statix" ''
${exports} ${exports}
export PATH="${makeBinPath [ packages.statix ]}:$PATH" export PATH="${makeBinPath [packages.statix]}:$PATH"
source ${../ci/statix.sh} source ${../ci/statix.sh}
''; '';
nf-deadnix = pkgs.writeShellScriptBin "nf-deadnix" '' nf-deadnix = pkgs.writeShellScriptBin "nf-deadnix" ''
${exports} ${exports}
${exportsFmtNix} ${exportsFmtNix}
export PATH="${makeBinPath [ packages.deadnix pkgs.findutils ]}:$PATH" export PATH="${makeBinPath [packages.deadnix pkgs.findutils]}:$PATH"
source ${../ci/deadnix.sh} source ${../ci/deadnix.sh}
''; '';
nf-alejandra = pkgs.writeShellScriptBin "nf-alejandra" '' nf-alejandra = pkgs.writeShellScriptBin "nf-alejandra" ''
${exports} ${exports}
${exportsFmtNix} ${exportsFmtNix}
export PATH="${makeBinPath [ packages.alejandra ]}:$PATH" export PATH="${makeBinPath [packages.alejandra]}:$PATH"
source ${../ci/alejandra.sh} source ${../ci/alejandra.sh}
''; '';
nf-lint-tf = pkgs.writeShellScriptBin "nf-lint-tf" '' nf-lint-tf = pkgs.writeShellScriptBin "nf-lint-tf" ''
${exports} ${exports}
export PATH="$PATH:${makeBinPath [ packages.tflint ]}" export PATH="$PATH:${makeBinPath [packages.tflint]}"
source ${../ci/lint-tf.sh} source ${../ci/lint-tf.sh}
''; '';
nf-lint-nix = pkgs.writeShellScriptBin "nf-lint-nix" '' nf-lint-nix = pkgs.writeShellScriptBin "nf-lint-nix" ''
${exports} ${exports}
export PATH="${makeBinPath [ packages.nf-statix packages.nf-deadnix ]}:$PATH" export PATH="${makeBinPath [packages.nf-statix packages.nf-deadnix]}:$PATH"
source ${../ci/lint-nix.sh} source ${../ci/lint-nix.sh}
''; '';
nf-fmt-tf = pkgs.writeShellScriptBin "nf-fmt-tf" '' nf-fmt-tf = pkgs.writeShellScriptBin "nf-fmt-tf" ''
${exports} ${exports}
export PATH="${makeBinPath [ packages.terraform ]}:$PATH" export PATH="${makeBinPath [packages.terraform]}:$PATH"
source ${../ci/fmt-tf.sh} source ${../ci/fmt-tf.sh}
''; '';
nf-fmt-nix = pkgs.writeShellScriptBin "nf-fmt-nix" '' nf-fmt-nix = pkgs.writeShellScriptBin "nf-fmt-nix" ''
@ -144,4 +150,5 @@
inherit (inputs) self; inherit (inputs) self;
}; };
}; };
in output in
output

View file

@ -5,12 +5,17 @@
}: let }: let
inherit (lib.strings) concatStringsSep; inherit (lib.strings) concatStringsSep;
inherit (lib.lists) toList head; inherit (lib.lists) toList head;
in { domain, name }: runCommand name { in
{
domain,
name,
}:
runCommand name {
domains = concatStringsSep "," (toList domain); domains = concatStringsSep "," (toList domain);
domain = head (toList domain); domain = head (toList domain);
nativeBuildInputs = [ buildPackages.minica ]; nativeBuildInputs = [buildPackages.minica];
outputs = [ "out" "key" "cakey" "ca" "cert" "fullchain" ]; outputs = ["out" "key" "cakey" "ca" "cert" "fullchain"];
} '' } ''
install -d $out install -d $out
minica \ minica \
--ca-key ca.key.pem \ --ca-key ca.key.pem \
@ -27,4 +32,4 @@ in { domain, name }: runCommand name {
ln -s $cakey $out/ca.key.pem ln -s $cakey $out/ca.key.pem
ln -s $cert $out/cert.pem ln -s $cert $out/cert.pem
ln -s $ca $out/ca.pem ln -s $ca $out/ca.pem
'' ''