This commit is contained in:
soraefir
2026-06-04 00:30:29 +02:00
parent b82393272c
commit 9a89479f66
26 changed files with 1385 additions and 1380 deletions

View File

@@ -16,8 +16,12 @@ let
// (if serverCfg.containers?nextcloud then { NEXTCLOUD_DOMAIN = "${serverCfg.containers.nextcloud.subdomain}.${serverCfg.domain}";} else {});
};
in {
sops = true;
db = true;
requires = {
secrets = [ name ];
databases = [ name ];
};
runtime = {
paths = [{
path="${serverCfg.path.config}/authentik";
owner = "1000:1000";
@@ -111,4 +115,5 @@ in {
echo "Completed Authentik Setup"
'';
};
};
}

View File

@@ -3,10 +3,7 @@ let
version = "latest";
serverCfg = config.syscfg.server;
in {
sops = false;
db = false;
runtime = {
containers = {
server = builder.mkContainer {
subdomain = containerCfg.subdomain;
@@ -36,6 +33,7 @@ in {
};
};
};
};
# curl 'https://books.test.helcel.net/admin/ajaxconfig' \
# -X POST

View File

@@ -3,7 +3,9 @@ let
version = "latest";
serverCfg = config.syscfg.server;
in {
sops = true;
requires.secrets = [ name ];
runtime = {
containers = {
server = builder.mkContainer {
subdomain = containerCfg.subdomain;
@@ -31,4 +33,5 @@ in {
};
};
};
};
}

View File

@@ -13,7 +13,9 @@ let
};
};
in {
sops = true;
requires.secrets = [ name ];
runtime = {
paths = [{
path="${serverCfg.path.data}/ethercalc/";
mode = "0666";
@@ -36,4 +38,5 @@ in {
};
};
};
};
}

View File

@@ -76,8 +76,12 @@ let
};
};
in {
sops = true;
db = true;
requires = {
secrets = [ name ];
databases = [ name ];
};
runtime = {
paths = [{
path="${serverCfg.path.config}/etherpad/";
mode = "0444";
@@ -121,4 +125,5 @@ in {
chmod 444 ${serverCfg.path.config}/etherpad/APIKEY.txt
'';
};
};
}

View File

@@ -3,8 +3,12 @@ let
version = "latest";
serverCfg = config.syscfg.server;
in {
sops = true;
db = true;
requires = {
secrets = [ name ];
databases = [ name ];
};
runtime = {
paths = [
{
path = "${serverCfg.path.config}/freshrss";
@@ -53,4 +57,5 @@ in {
'';
};
};
}

View File

@@ -27,9 +27,9 @@ let
};
};
in {
sops = true; # Enabled to safeguard sensitive camera RTSP stream credentials
db = false; # Internal SQLite is used by default in Frigate
requires.secrets = [ name ];
runtime = {
paths = [
{
path = "${serverCfg.path.config}/frigate/";
@@ -92,4 +92,5 @@ EOF
fi
'';
};
};
}

View File

@@ -5,8 +5,12 @@ let
LDAP_DC_DOMAIN = "dc=ldap," + (lib.concatMapStringsSep "," (x: "dc=${x}") (lib.splitString "." serverCfg.domain));
in {
sops = true;
db = true;
requires = {
secrets = [ name ];
databases = [ name ];
};
runtime = {
paths = [{
path="${serverCfg.path.data}/gitea";
owner = "1000:1000";
@@ -138,4 +142,5 @@ in {
echo "Completed Gitea Setup"
'';
};
};
}

View File

@@ -2,12 +2,8 @@
let
serverCfg = config.syscfg.server;
version = "latest";
routerName = if containerCfg.subpath != null
then "${containerCfg.subdomain}-${lib.strings.sanitizeDerivationName containerCfg.subpath}"
else containerCfg.subdomain;
in {
runtime = {
paths = [{
path = "${serverCfg.path.config}/handbrake";
mode = "0755";
@@ -15,6 +11,8 @@ in {
containers = {
server = builder.mkContainer {
authentik = true;
tmpfs = true;
subdomain = containerCfg.subdomain;
subpath = containerCfg.subpath;
image = "ghcr.io/jlesage/handbrake:${version}";
@@ -27,12 +25,6 @@ in {
AUTOMATED_CONVERSION_FORMAT = "mkv";
AUTOMATED_CONVERSION_OUTPUT_SUBDIR = "SAME_AS_SRC";
};
extraLabels = { } // (if serverCfg.containers ? authentik then {
"traefik.http.routers.${routerName}.middlewares" = "authentik";
} else {});
extraOptions = [
"--tmpfs=/tmp:rw,noexec,nosuid,size=512m"
];
overrides = {
volumes = [
@@ -52,5 +44,5 @@ in {
'';
};
};
}

View File

@@ -4,9 +4,10 @@ let
serverCfg = config.syscfg.server;
in {
runtime = {
vm = {
portForward = [ 8123 ];
cfg = {cfg,...}:{
cfg = {cfg,...}: {
services.home-assistant = {
enable = true;
openFirewall = true;
@@ -97,5 +98,5 @@ in {
fi
'';
};
};
}

View File

@@ -258,9 +258,7 @@ let
];}#)];}
];
in {
sops = false;
db = false;
runtime = {
containers = {
server = builder.mkContainer {
subdomain = containerCfg.subdomain;
@@ -284,5 +282,5 @@ in {
};
};
};
};
}

View File

@@ -4,9 +4,12 @@ let
serverCfg = config.syscfg.server;
in {
sops = true;
db = true;
requires = {
secrets = [ name ];
databases = [ name ];
};
runtime = {
paths = [{
path = "${serverCfg.path.config}/immich";
dirs = ["cache"];
@@ -97,4 +100,5 @@ in {
'';
};
};
}

View File

@@ -5,9 +5,12 @@ let
in {
sops = true;
db = true;
requires = {
secrets = [ name ];
databases = [ name ];
};
runtime = {
paths = [{
path = "${serverCfg.path.config}/influxdb/";
owner = "1500:1500";
@@ -37,6 +40,7 @@ in {
# };
server = builder.mkContainer {
tmpfs = true;
subdomain = containerCfg.subdomain;
image = "influxdata/influxdb3-ui:${version}";
port = 8080;
@@ -45,9 +49,6 @@ in {
SESSION_SECRET_KEY = "7b0024c13ae770000f797c201e2f210b9932a689c04d34de04379faa44e88e97";
DATABASE_URL = "/db/sqlite.db";
};
extraOptions = [
"--tmpfs=/tmp:rw,noexec,nosuid,size=512m"
];
overrides = {
ports = [ "8080:8080" ];
cmd = [ "--mode=admin" ];
@@ -73,5 +74,5 @@ EOF
chmod -R 755 ${serverCfg.path.config}/influxdb
'';
};
};
}

View File

@@ -24,8 +24,12 @@ let
};
in {
sops = true;
db = true;
requires = {
secrets = [ name ];
databases = [ name ];
};
runtime = {
paths = [{
path="${serverCfg.path.config}/invidious";
mode = "0755";
@@ -75,4 +79,5 @@ in {
${pkgs.gettext}/bin/envsubst < "${../data/invidious/config.yml}" > "${serverCfg.path.config}/invidious/config.yml"
'';
};
};
}

View File

@@ -25,6 +25,7 @@ let
};
};
in {
runtime = {
paths = [
{
path = "${serverCfg.path.config}/jellyfin/";
@@ -35,6 +36,7 @@ in {
containers = {
server = builder.mkContainer {
tmpfs = true;
subdomain = containerCfg.subdomain;
imageStream = image;
port = 8096;
@@ -44,9 +46,6 @@ in {
JELLYFIN_HttpListenerHost__BindAddress= "0.0.0.0"; #we can use settings.xml override
JELLYFIN_ServerName = if containerCfg.extra?name then containerCfg.extra.name else "Flix";
};
extraOptions = [
"--tmpfs=/tmp:rw,noexec,nosuid,size=512m"
];
overrides = {
cmd = [
"--datadir" "/config/data"
@@ -172,5 +171,5 @@ EOF
'';
};
};
}

View File

@@ -3,8 +3,12 @@ let
version = "31";
serverCfg = config.syscfg.server;
in {
sops = true;
db = true;
requires = {
secrets = [ name ];
databases = [ name ];
};
runtime = {
paths = [{
path="${serverCfg.path.config}/nextcloud";
owner = "33:33";
@@ -13,6 +17,7 @@ in {
containers = {
server = builder.mkContainer {
tmpfs = true;
subdomain = containerCfg.subdomain;
image = "nextcloud:${version}";
port = 80;
@@ -40,9 +45,6 @@ in {
"traefik.http.middlewares.sts_headers.headers.stsSeconds" = "15552000";
"traefik.http.middlewares.sts_headers.headers.stsIncludeSubdomains" = "true";
};
extraOptions = [
"--tmpfs=/tmp:rw,noexec,nosuid,size=512m"
];
overrides = {
ports = if containerCfg.port!=null then [ "${toString containerCfg.port}:80" ] else [];
volumes = [
@@ -193,4 +195,5 @@ in {
};
cron = [ "*/5 * * * * root ${pkgs.podman}/bin/podman --events-backend=none exec -u www-data nextcloud-server php -f /var/www/html/cron.php" ];
};
}

View File

@@ -4,8 +4,7 @@ let
version = "5.1.4";
in {
sops = false;
db = false;
runtime = {
paths = [
{ path="${serverCfg.path.config}/openhab/conf"; owner="1000:1000"; mode = "0755"; }
{ path="${serverCfg.path.config}/openhab/userdata"; owner="1000:1000"; mode = "0755"; }
@@ -74,4 +73,5 @@ in {
#Extra: AndroidTV/Jellyfin (Bind with lights + more)
'';
};
};
}

View File

@@ -59,8 +59,9 @@ let
};
});
in {
sops = true;
requires.secrets = [ name ];
runtime = {
containers = {
server = builder.mkContainer {
subdomain = containerCfg.subdomain;
@@ -82,4 +83,5 @@ in {
};
};
};
};
}

View File

@@ -2,11 +2,8 @@
let
version = "latest";
serverCfg = config.syscfg.server;
routerName = if containerCfg.subpath != null
then "${containerCfg.subdomain}-${lib.strings.sanitizeDerivationName containerCfg.subpath}"
else containerCfg.subdomain;
in {
runtime = {
paths = [{
path = "${serverCfg.path.config}/selfmark/";
mode = "0444";
@@ -14,6 +11,7 @@ in {
containers = {
server = builder.mkContainer {
authentik = true;
subdomain = containerCfg.subdomain;
subpath = containerCfg.subpath;
image = "ghcr.io/calibrain/shelfmark:${version}";
@@ -79,11 +77,6 @@ in {
EXT_BYPASSER_PATH = "/v1";
EXT_BYPASSER_TIMEOUT = "60000";
};
extraLabels = {
} // (if serverCfg.containers ? authentik then {
"traefik.http.routers.${routerName}.middlewares" = "authentik";
} else {});
overrides = {
volumes = [
"${serverCfg.path.dlComplete}:/books:rw"
@@ -93,5 +86,5 @@ in {
};
};
};
};
}

View File

@@ -30,9 +30,10 @@ let
in
assert containerCfg.subpath == null || throw "Error: Servarr does not support subpath.";
{
sops = true;
requires.secrets = [ name ];
# db = [ "prowlarr" "sonarr" "radarr" ]; -> one db for each
runtime = {
paths = [
{ path = "${serverCfg.dataPath}/media/"; mode = "0755"; }
{ path = "${serverCfg.configPath}/servarr/prowlarr"; mode = "0755"; }
@@ -44,6 +45,8 @@ in
containers = {
}// lib.optionalAttrs (builtins.elem "prowlarr" (containerCfg.extra.modules or defaultModules)) {
prowlarr = builder.mkContainer {
authentik = true;
tmpfs = true;
subdomain = containerCfg.subdomain;
subpath = "prowlarr";
imageStream = images.prowlarr;
@@ -58,17 +61,15 @@ in
};
extraOptions = [
"--user=0:0"
"--tmpfs=/tmp:rw,noexec,nosuid,size=512m"
"--passwd-entry=root:x:0:0:root:/root:/bin/sh"
];
extraLabels = { } // (if serverCfg.containers ? authentik then {
"traefik.http.routers.${containerCfg.subdomain}-prowlarr.middlewares" = "authentik";
} else {});
overrides.volumes = sharedVolumes ++ [ "${serverCfg.configPath}/servarr/prowlarr:/config" ];
};
}// lib.optionalAttrs (builtins.elem "radarr" (containerCfg.extra.modules or defaultModules)) {
radarr = builder.mkContainer {
authentik = true;
tmpfs = true;
subdomain = containerCfg.subdomain;
subpath = "radarr";
imageStream = images.radarr;
@@ -83,17 +84,15 @@ in
};
extraOptions = [
"--user=0:0"
"--tmpfs=/tmp:rw,noexec,nosuid,size=512m"
"--passwd-entry=root:x:0:0:root:/root:/bin/sh"
];
extraLabels = { } // (if serverCfg.containers ? authentik then {
"traefik.http.routers.${containerCfg.subdomain}-radarr.middlewares" = "authentik";
} else {});
overrides.volumes = sharedVolumes ++ [ "${serverCfg.configPath}/servarr/radarr:/config" ];
};
}// lib.optionalAttrs (builtins.elem "sonarr" (containerCfg.extra.modules or defaultModules)) {
sonarr = builder.mkContainer {
authentik = true;
tmpfs = true;
subdomain = containerCfg.subdomain;
subpath = "sonarr";
imageStream = images.sonarr;
@@ -108,17 +107,15 @@ in
};
extraOptions = [
"--user=0:0"
"--tmpfs=/tmp:rw,noexec,nosuid,size=512m"
"--passwd-entry=root:x:0:0:root:/root:/bin/sh"
];
extraLabels = { } // (if serverCfg.containers ? authentik then {
"traefik.http.routers.${containerCfg.subdomain}-sonarr.middlewares" = "authentik";
} else {});
overrides.volumes = sharedVolumes ++ [ "${serverCfg.configPath}/servarr/sonarr:/config" ];
};
}// lib.optionalAttrs (builtins.elem "lidarr" (containerCfg.extra.modules or defaultModules)) {
lidarr = builder.mkContainer {
authentik = true;
tmpfs = true;
subdomain = containerCfg.subdomain;
subpath = "lidarr";
imageStream = images.lidarr;
@@ -133,12 +130,8 @@ in
};
extraOptions = [
"--user=0:0"
"--tmpfs=/tmp:rw,noexec,nosuid,size=512m"
"--passwd-entry=root:x:0:0:root:/root:/bin/sh"
];
extraLabels = { } // (if serverCfg.containers ? authentik then {
"traefik.http.routers.${containerCfg.subdomain}-lidarr.middlewares" = "authentik";
} else {});
overrides.volumes = sharedVolumes ++ [ "${serverCfg.configPath}/servarr/lidarr:/config" ];
};
@@ -526,4 +519,5 @@ in
'';
};
};
}

View File

@@ -3,10 +3,13 @@ let
version = "stable";
serverCfg = config.syscfg.server;
in {
sops = true;
db =true;
containers = {
requires = {
secrets = [ name ];
databases = [ name ];
};
runtime = {
containers = {
server = builder.mkContainer {
subdomain = containerCfg.subdomain;
image = "ghcr.io/suwayomi/suwayomi-server:${version}";
@@ -46,5 +49,5 @@ in {
};
};
};
};
}

View File

@@ -11,7 +11,9 @@ let
};
};
in {
sops = true;
requires.secrets = [ name ];
runtime = {
paths = [{
path="${serverCfg.path.config}/traefik";
owner = "1000:1000";
@@ -83,5 +85,5 @@ in {
};
};
};
};
}

View File

@@ -13,10 +13,8 @@ let
};
};
};
routerName = if containerCfg.subpath != null
then "${containerCfg.subdomain}-${lib.strings.sanitizeDerivationName containerCfg.subpath}"
else containerCfg.subdomain;
in {
runtime = {
paths = [{
path = "${serverCfg.path.config}/transmission";
owner = "1000:1000";
@@ -25,6 +23,7 @@ in {
containers = {
server = builder.mkContainer {
authentik = true;
subdomain = containerCfg.subdomain;
subpath = containerCfg.subpath;
imageStream = image;
@@ -36,10 +35,6 @@ in {
WHITELIST = "";# 127.0.0.1,::1,10.*";
# HOST_WHITELIST = "traefik-server,authentik-server,authentik-worker";
};
extraLabels = {
} // (if serverCfg.containers ? authentik then {
"traefik.http.routers.${routerName}.middlewares" = "authentik";
} else {});
overrides = {
volumes = [
@@ -60,5 +55,5 @@ in {
${pkgs.gettext}/bin/envsubst < "${../data/transmission/settings.json}" > "${serverCfg.path.config}/transmission/config/settings.json"
'';
};
};
}

View File

@@ -15,8 +15,12 @@ let
};
};
in {
sops = true;
db = true;
requires = {
secrets = [ name ];
databases = [ name ];
};
runtime = {
paths = [{
path = "${serverCfg.path.config}/umami/";
mode = "0444";
@@ -24,6 +28,8 @@ in {
containers = {
server = builder.mkContainer {
authentik = true;
tmpfs = true;
subdomain = containerCfg.subdomain;
image = "${pkgs.umami.name}:${pkgs.umami.version}";
imageStream = image;
@@ -39,16 +45,10 @@ in {
# DISABLE_LOGIN = "1";#(if serverCfg.containers?authentik then "1" else "0");
};
extraLabels = { } // ( if serverCfg.containers?authentik then {
"traefik.http.routers.${containerCfg.subdomain}.middlewares" = if serverCfg.containers?authentik then "authentik" else "";
} else {});
extraOptions = [
"--tmpfs=/tmp:rw,noexec,nosuid,size=512m"
];
overrides = {
cmd = [ "start" ]; # Specific command for the umami binary
};
};
};
};
}

View File

@@ -1,16 +1,32 @@
{ config, lib, pkgs, serverCfg }:
let
mkRouterName = { subdomain, subpath ? null }:
if subpath != null
then "${subdomain}-${lib.strings.sanitizeDerivationName subpath}"
else subdomain;
getOr = attrs: path: default: lib.attrByPath path default attrs;
mkTmpfsOption = size: "--tmpfs=/tmp:rw,noexec,nosuid,size=${size}";
mkAuthentikLabels =
{ subdomain
, subpath ? null
, routerName ? mkRouterName { inherit subdomain subpath; }
, middleware ? "authentik"
}:
lib.optionalAttrs (serverCfg.containers ? authentik) {
"traefik.http.routers.${routerName}.middlewares" = middleware;
};
contBuilder =
{ image ? null, imageStream ? null, imageFile ? null
, secret ? null
, subdomain ? null, subpath?null, port ? null
, authentik ? false
, tmpfs ? false
, tmpfsSize ? "512m"
, extraEnv ? { }, extraLabels ? { }, extraOptions ? [ ]
, overrides ? { }
}:
let
routerName = if subpath != null
then "${subdomain}-${lib.strings.sanitizeDerivationName subpath}"
else subdomain;
routerName = mkRouterName { inherit subdomain subpath; };
base = {
image = if imageStream != null then "${imageStream.imageName}:${imageStream.imageTag}"
else if imageFile != null then "${imageFile.imageName}:${imageFile.imageTag}" else image;
@@ -33,11 +49,15 @@ let
"traefik.http.services.${routerName}.loadbalancer.server.port" = toString port;
}) else {
"traefik.enable" = "false";
}) // extraLabels;
})
// lib.optionalAttrs authentik (mkAuthentikLabels { inherit subdomain subpath routerName; })
// extraLabels;
extraOptions = [
"--add-host=host.containers.internal:host-gateway"
] ++ extraOptions;
]
++ lib.optional tmpfs (mkTmpfsOption tmpfsSize)
++ extraOptions;
};
in lib.recursiveUpdate base overrides;
vmBuilder = { name, vm }: ((import "${pkgs.path}/nixos/lib/eval-config.nix" {
@@ -70,54 +90,27 @@ in {
mkContainer = contBuilder;
mkVm = vmBuilder;
mkApp = name: app:
let
# Keep legacy app modules working while storing a stricter internal contract.
legacySetup =
if app ? setup then app.setup else null;
in {
{
inherit name;
requires = {
secrets =
if app ? requires && app.requires ? secrets then app.requires.secrets
else if app ? sops && app.sops then [ name ]
else [ ];
databases =
if app ? requires && app.requires ? databases then app.requires.databases
else if app ? db && app.db then [ name ]
else [ ];
secrets = getOr app [ "requires" "secrets" ] [ ];
databases = getOr app [ "requires" "databases" ] [ ];
};
exports = {
authentik = {
blueprints =
if app ? exports && app.exports ? authentik && app.exports.authentik ? blueprints
then app.exports.authentik.blueprints
else [ ];
blueprints = getOr app [ "exports" "authentik" "blueprints" ] [ ];
};
};
runtime = {
paths =
if app ? runtime && app.runtime ? paths then app.runtime.paths
else if app ? paths then app.paths
else [ ];
containers =
if app ? runtime && app.runtime ? containers then app.runtime.containers
else if app ? containers then app.containers
else { };
vm =
if app ? runtime && app.runtime ? vm then app.runtime.vm
else if app ? vm then app.vm
else null;
cron =
if app ? runtime && app.runtime ? cron then app.runtime.cron
else if app ? cron then app.cron
else [ ];
setup =
if app ? runtime && app.runtime ? setup then app.runtime.setup
else ({
paths = getOr app [ "runtime" "paths" ] [ ];
containers = getOr app [ "runtime" "containers" ] { };
vm = getOr app [ "runtime" "vm" ] null;
cron = getOr app [ "runtime" "cron" ] [ ];
setup = {
trigger = "";
script = null;
envFile = [ ];
} // (if legacySetup != null then legacySetup else { }));
} // getOr app [ "runtime" "setup" ] { };
};
};
mkData = { name, dir, vars?{} }: pkgs.runCommand name vars ''

View File

@@ -2,38 +2,25 @@
let
serverCfg = config.syscfg.server;
builder = import ./builder.nix { inherit config lib pkgs serverCfg; };
in{
config = lib.mkMerge [{
syscfg.server.loadedContainers = lib.mapAttrs (name: containerCfg:
builder.mkApp name ((import (./apps + "/${name}.nix")) { inherit config pkgs lib containerCfg builder name; })
) config.syscfg.server.containers;
} (lib.mkIf ( serverCfg.containers != {} ) (
let
appsList = builtins.attrValues config.syscfg.server.loadedContainers;
loadApp = name: containerCfg:
builder.mkApp name ((import (./apps + "/${name}.nix")) {
inherit config pkgs lib containerCfg builder name;
});
loadedContainers = lib.mapAttrs loadApp serverCfg.containers;
appsList = builtins.attrValues loadedContainers;
concatRuntimeLists = field: lib.concatMap (app: app.runtime.${field}) appsList;
mkNamedUnits = mkUnit: items: lib.listToAttrs (map mkUnit items);
mergedContainers = lib.concatMapAttrs (appName: app:
lib.mapAttrs' (cName: cCfg: lib.nameValuePair "${appName}-${cName}" cCfg) app.runtime.containers
) config.syscfg.server.loadedContainers;
serverPathConfigs = map (path: {
) loadedContainers;
allPathConfigs = map (path: {
inherit path;
mode = "0755";
}) (lib.unique (builtins.attrValues serverCfg.path));
allPathConfigs = serverPathConfigs ++ lib.concatMap (app: app.runtime.paths) appsList;
allSetupConfigs = lib.concatMap (app:
if app.runtime.setup ? script
then [ ({ name = app.name; envFile = ""; } // app.runtime.setup) ]
else [ ]
) appsList;
allCronsConfigs = lib.concatMap (app: app.runtime.cron) appsList;
}) (lib.unique (builtins.attrValues serverCfg.path)) ++ concatRuntimeLists "paths";
allSetupConfigs = map (app: ({ name = app.name; envFile = ""; } // app.runtime.setup)) appsList;
allCronsConfigs = concatRuntimeLists "cron";
allVMConfigs = builtins.filter (app: app.runtime.vm != null) appsList;
in{
virtualisation.oci-containers = {
backend = "podman";
containers = mergedContainers;
};
system.activationScripts.container-setup-dirs = {
deps = [ "users" "groups" ];
text = lib.concatStringsSep "\n" (map (cfg:
mkPathSetup = cfg:
let
effectiveCfg = {
owner = "root:root";
@@ -45,8 +32,18 @@ in{
${lib.concatMapStringsSep "\n" (dir: "${pkgs.coreutils}/bin/mkdir -p ${effectiveCfg.path}/${lib.escapeShellArg dir}") effectiveCfg.dirs}
${pkgs.coreutils}/bin/chown ${effectiveCfg.owner} "${effectiveCfg.path}"
${pkgs.coreutils}/bin/chmod ${effectiveCfg.mode} "${effectiveCfg.path}"
'') allPathConfigs);
'';
in {
config = lib.mkMerge [{
syscfg.server.loadedContainers = loadedContainers;
} (lib.mkIf (loadedContainers != {}) {
virtualisation.oci-containers = {
backend = "podman";
containers = mergedContainers;
};
system.activationScripts.container-setup-dirs = {
deps = [ "users" "groups" ];
text = lib.concatStringsSep "\n" (map mkPathSetup allPathConfigs);
};
systemd.services = {
@@ -60,7 +57,7 @@ in{
startAt = "weekly";
};
}
// lib.listToAttrs (lib.concatMap (e: [{
// mkNamedUnits (e: {
name = "${e.name}-vm";
value = {
description = "Isolated NixOS Guest VM for ${e.name}";
@@ -81,8 +78,8 @@ in{
'';
};
};
}]) allVMConfigs)
// lib.listToAttrs (lib.concatMap (e: [{
}) allVMConfigs
// mkNamedUnits (e: {
name = "${e.name}-setup";
value = {
description = "Run ${e.name} setup";
@@ -98,13 +95,11 @@ in{
User = "root";
};
};
}]) allSetupConfigs );
}) allSetupConfigs;
services.cron = {
enable = true;
systemCronJobs = allCronsConfigs;
};
}))];
})];
}