Compare commits

...

27 Commits

Author SHA1 Message Date
soraefir 9a89479f66 Refactor 2026-06-04 00:30:29 +02:00
soraefir b82393272c Refactor 2026-06-03 19:24:29 +02:00
sora-ext 1cb9e9b645 Update modules/server/containers/default.nix 2026-06-03 17:40:10 +02:00
sora-ext b8735803c4 Update flake.nix 2026-06-03 17:35:15 +02:00
sora-ext 14bf297897 Update modules/shared/syscfg/server.nix 2026-06-03 17:20:36 +02:00
sora-ext 1fad610dff Update modules/server/database/default.nix 2026-06-03 17:19:28 +02:00
sora-ext 2c00901b04 Update modules/server/containers/apps/umami.nix 2026-06-03 17:19:11 +02:00
sora-ext 2c0ac0db09 Update modules/server/containers/apps/transmission.nix 2026-06-03 17:19:02 +02:00
sora-ext 6be107374e Update modules/server/containers/apps/traefik.nix 2026-06-03 17:18:52 +02:00
sora-ext 9e4d8274b5 Update modules/server/containers/apps/suwayomi.nix 2026-06-03 17:18:42 +02:00
sora-ext f54dea8a13 Update modules/server/containers/apps/selfmark.nix 2026-06-03 17:17:45 +02:00
sora-ext a6788f13a8 Update modules/server/containers/apps/searxng.nix 2026-06-03 17:17:36 +02:00
sora-ext 5b4af162b9 Update modules/server/containers/apps/openhab.nix 2026-06-03 17:17:14 +02:00
sora-ext 4e5c956f78 Update modules/server/containers/apps/nextcloud.nix 2026-06-03 17:17:02 +02:00
sora-ext 083549e3c6 Update modules/server/containers/apps/jellyfin.nix 2026-06-03 17:16:53 +02:00
sora-ext fada3c79b3 Update modules/server/containers/apps/invidious.nix 2026-06-03 17:16:42 +02:00
sora-ext ce72e4421b Update modules/server/containers/apps/influx.nix 2026-06-03 17:16:30 +02:00
sora-ext ddc5c76a35 Update modules/server/containers/apps/immich.nix 2026-06-03 17:16:18 +02:00
sora-ext d0b6718254 Update modules/server/containers/apps/handbrake.nix 2026-06-03 17:16:06 +02:00
sora-ext c1c76ab3de Update modules/server/containers/apps/gitea.nix 2026-06-03 17:15:56 +02:00
sora-ext 558874731a Update modules/server/containers/apps/frigate.nix 2026-06-03 17:15:46 +02:00
sora-ext b14135274b Update modules/server/containers/apps/freshrss.nix 2026-06-03 17:15:37 +02:00
sora-ext 5df88ac25a Update modules/server/containers/apps/etherpad.nix 2026-06-03 17:15:29 +02:00
sora-ext 2d8e0da386 Update modules/server/containers/apps/ethercalc.nix 2026-06-03 17:15:20 +02:00
sora-ext 8f87c11cb5 Update modules/server/containers/apps/calibre.nix 2026-06-03 17:15:00 +02:00
sora-ext 7b8eeb917f Update modules/server/containers/apps/authentik.nix 2026-06-03 17:14:30 +02:00
sora-ext a2043cafe1 Update modules/server/containers/apps/.template.nix 2026-06-03 17:14:05 +02:00
32 changed files with 1515 additions and 1434 deletions
+18 -15
View File
@@ -38,24 +38,27 @@
};
outputs = inputs:
let gen = import ./generator.nix { inherit inputs; };
let
lib = inputs.nixpkgs.lib;
gen = import ./generator.nix { inherit inputs; };
systemsDir = ./systems;
systemNames = lib.attrNames (lib.filterAttrs
(name: type: type == "directory" && builtins.pathExists (systemsDir + "/${name}/cfg.nix"))
(builtins.readDir systemsDir));
hostsByType = systemType:
lib.filter
(host: (import (systemsDir + "/${host}/cfg.nix")).syscfg.type == systemType)
systemNames;
generateHosts = systemType:
builtins.listToAttrs (map
(host: lib.nameValuePair host (gen.generate { inherit host; }))
(hostsByType systemType));
in {
devShells = import ./shells { inherit inputs; };
nixosConfigurations = {
valinor = gen.generate { host = "valinor"; };
iriy = gen.generate { host = "iriy"; };
efir = gen.generate { host = "efir"; };
avalon = gen.generate { host = "avalon"; };
ci = gen.generate { host = "ci"; };
sandbox = gen.generate { host = "sandbox"; };
gateway = gen.generate { host = "gateway"; };
};
darwinConfigurations = { asgard = gen.generate { host = "asgard"; }; };
homeConfigurations = {
yomi = gen.generate { host = "example"; };
example = gen.generate { host = "example"; };
};
nixosConfigurations = generateHosts "nixos";
darwinConfigurations = generateHosts "macos";
homeConfigurations = generateHosts "home";
};
# ===== Unsupported/NotImplemented ======
+8 -3
View File
@@ -17,10 +17,14 @@ let
};
};
in {
sops = false;
db = false;
requires = {
secrets = [ ];
databases = [ ];
};
runtime = {
paths = [{
path="${serverCfg.configPath}/example/";
path="${serverCfg.path.config}/example/";
mode = "0444";
}];
@@ -46,4 +50,5 @@ in {
...
'';
};
};
}
+13 -11
View File
@@ -16,15 +16,16 @@ 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.configPath}/authentik/media";
owner = "1000:1000";
mode = "0755";
}{
path="${serverCfg.configPath}/authentik/templates";
path="${serverCfg.path.config}/authentik";
owner = "1000:1000";
dirs = ["media" "templates"];
mode = "0755";
}];
@@ -55,8 +56,8 @@ in {
cmd = [ "server" ];
volumes = [
"${serverCfg.configPath}/authentik/media:/media"
"${serverCfg.configPath}/authentik/templates:/templates"
"${serverCfg.path.config}/authentik/media:/media"
"${serverCfg.path.config}/authentik/templates:/templates"
"${authentikData}:/blueprints/custom:ro"
];
};
@@ -77,8 +78,8 @@ in {
overrides = {
cmd = [ "worker" ];
volumes = [
"${serverCfg.configPath}/authentik/media:/media"
"${serverCfg.configPath}/authentik/templates:/templates"
"${serverCfg.path.config}/authentik/media:/media"
"${serverCfg.path.config}/authentik/templates:/templates"
"${authentikData}:/blueprints/custom:ro"
];
};
@@ -114,4 +115,5 @@ in {
echo "Completed Authentik Setup"
'';
};
};
}
+4 -13
View File
@@ -3,16 +3,7 @@ let
version = "latest";
serverCfg = config.syscfg.server;
in {
sops = false;
db = false;
paths = [
{
path = "${serverCfg.configPath}/calibre-web/";
mode = "0755";
dirs = ["library" "ingest"];
}
];
runtime = {
containers = {
server = builder.mkContainer {
subdomain = containerCfg.subdomain;
@@ -35,14 +26,14 @@ in {
"traefik.http.routers.${containerCfg.subdomain}-login.tls" = "true";
};
overrides = {
cmd = [ ];
volumes = [
"${serverCfg.configPath}/calibre-web/library/:/calibre-library"
"${serverCfg.configPath}/calibre-web/ingest/:/cwa-book-ingest"
"${serverCfg.path.book}:/calibre-library"
"${serverCfg.path.dlBook}:/cwa-book-ingest"
];
};
};
};
};
# curl 'https://books.test.helcel.net/admin/ajaxconfig' \
# -X POST
+4 -1
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 {
};
};
};
};
}
+6 -3
View File
@@ -13,9 +13,11 @@ let
};
};
in {
sops = true;
requires.secrets = [ name ];
runtime = {
paths = [{
path="${serverCfg.dataPath}/ethercalc/";
path="${serverCfg.path.data}/ethercalc/";
mode = "0666";
}];
@@ -31,9 +33,10 @@ in {
};
overrides = {
volumes = [
"${serverCfg.dataPath}/ethercalc:/data"
"${serverCfg.path.data}/ethercalc:/data"
];
};
};
};
};
}
+11 -6
View File
@@ -76,10 +76,14 @@ let
};
};
in {
sops = true;
db = true;
requires = {
secrets = [ name ];
databases = [ name ];
};
runtime = {
paths = [{
path="${serverCfg.configPath}/etherpad/";
path="${serverCfg.path.config}/etherpad/";
mode = "0444";
}];
@@ -107,7 +111,7 @@ in {
cmd = [ "--settings" "/etc/etherpad/settings.json" "--apikey" "/etc/etherpad/APIKEY.txt" ];
volumes = [
"${settings}:/etc/etherpad/settings.json"
"${serverCfg.configPath}/etherpad/APIKEY.txt:/etc/etherpad/APIKEY.txt:ro"
"${serverCfg.path.config}/etherpad/APIKEY.txt:/etc/etherpad/APIKEY.txt:ro"
];
};
};
@@ -117,8 +121,9 @@ in {
trigger = "server";
envFile = config.sops.secrets."ETHERPAD".path;
script = pkgs.writeShellScript "setup" ''
echo "$APIKEY" > ${serverCfg.configPath}/etherpad/APIKEY.txt
chmod 444 ${serverCfg.configPath}/etherpad/APIKEY.txt
echo "$APIKEY" > ${serverCfg.path.config}/etherpad/APIKEY.txt
chmod 444 ${serverCfg.path.config}/etherpad/APIKEY.txt
'';
};
};
}
+9 -4
View File
@@ -3,11 +3,15 @@ let
version = "latest";
serverCfg = config.syscfg.server;
in {
sops = true;
db = true;
requires = {
secrets = [ name ];
databases = [ name ];
};
runtime = {
paths = [
{
path = "${serverCfg.configPath}/freshrss";
path = "${serverCfg.path.config}/freshrss";
owner = "1000:1000";
mode = "0755";
}
@@ -33,7 +37,7 @@ in {
overrides = {
environmentFiles = [ config.sops.secrets."FRESHRSS".path config.sops.secrets."CUSTOM".path ];
volumes = [];
volumes = ["${serverCfg.path.config}/freshrss:/var/www/FreshRSS/data"];
};
};
};
@@ -53,4 +57,5 @@ in {
'';
};
};
}
+8 -7
View File
@@ -27,12 +27,12 @@ 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.configPath}/frigate/";
path = "${serverCfg.path.config}/frigate/";
mode = "0755";
}
{
@@ -53,7 +53,7 @@ in {
overrides = {
cmd = [ ];
volumes = [
"${serverCfg.configPath}/frigate:/config"
"${serverCfg.path.config}/frigate:/config"
"/var/lib/frigate/storage:/media/frigate"
"/dev/bus/usb:/dev/bus/usb" # Passes Google Coral USB TPU to the container
"/dev/dri:/dev/dri" # Passes Intel/AMD GPU for hardware video decoding
@@ -66,12 +66,12 @@ in {
trigger = "server";
envFile = config.sops.secrets."FRIGATE_ENV".path;
script = pkgs.writeShellScript "setup-frigate" ''
mkdir -p "${serverCfg.configPath}/frigate"
mkdir -p "${serverCfg.path.config}/frigate"
mkdir -p "/var/lib/frigate/storage"
# Bootstrap a standard configuration layout if missing
if [ ! -f "${serverCfg.configPath}/frigate/config.yml" ]; then
cat <<EOF > "${serverCfg.configPath}/frigate/config.yml"
if [ ! -f "${serverCfg.path.config}/frigate/config.yml" ]; then
cat <<EOF > "${serverCfg.path.config}/frigate/config.yml"
mqtt:
enabled: False # Set to True and define host if connecting to Home Assistant
@@ -92,4 +92,5 @@ EOF
fi
'';
};
};
}
+13 -11
View File
@@ -5,15 +5,16 @@ 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.dataPath}/gitea/data";
owner = "1000:1000";
mode = "0755";
}{
path="${serverCfg.dataPath}/gitea/data-runner";
path="${serverCfg.path.data}/gitea";
owner = "1000:1000";
dirs = ["data" "runner"];
mode = "0755";
}];
containers = {
@@ -73,7 +74,7 @@ in {
} else {});
extraLabels = {
"traefik.http.routers.${containerCfg.subdomain}-login.rule" = "Host(`${containerCfg.subdomain}.${serverCfg.domain}`) && Path(`/user/login`) ";
"traefik.http.routers.${containerCfg.subdomain}-login.middlewares" = if (serverCfg.containers?authentik && false) then "authentik" else "";
"traefik.http.routers.${containerCfg.subdomain}-login.middlewares" = if (serverCfg.containers?authentik && containerCg.extra?proxyauth) then "authentik" else "";
"traefik.http.routers.${containerCfg.subdomain}-login.priority" = "100";
"traefik.http.routers.${containerCfg.subdomain}-login.entrypoints" = "web-secure";
"traefik.http.routers.${containerCfg.subdomain}-login.tls" = "true";
@@ -81,7 +82,7 @@ in {
overrides = {
volumes = [
"${serverCfg.dataPath}/gitea/data:/data"
"${serverCfg.path.data}/gitea/data:/data"
];
ports = [ "2222:22" ];
};
@@ -98,7 +99,7 @@ in {
overrides = {
volumes = [
"${serverCfg.dataPath}/gitea/data-runner:/data"
"${serverCfg.path.data}/gitea/runner:/data"
"/var/run/podman/podman.sock:/var/run/docker.sock"
];
# ports = [ "8088:8088" ];
@@ -117,7 +118,7 @@ in {
$GT admin user create --username "$DEFAULT_ADMIN_USERNAME" --password "$DEFAULT_ADMIN_PASSWORD" --email "$DEFAULT_ADMIN_EMAIL" --admin || true
touch ${serverCfg.dataPath}/gitea/data-runner/config.yml
touch ${serverCfg.path.data}/gitea/data-runner/config.yml
RUNNER_TOKEN=$($GT actions generate-runner-token)
$GTR register \
@@ -141,4 +142,5 @@ in {
echo "Completed Gitea Setup"
'';
};
};
}
+9 -20
View File
@@ -2,22 +2,17 @@
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.configPath}/handbrake/config";
mode = "0755";
} {
path = "${serverCfg.dataPath}/handbrake/";
path = "${serverCfg.path.config}/handbrake";
mode = "0755";
}];
containers = {
server = builder.mkContainer {
authentik = true;
tmpfs = true;
subdomain = containerCfg.subdomain;
subpath = containerCfg.subpath;
image = "ghcr.io/jlesage/handbrake:${version}";
@@ -30,18 +25,12 @@ 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 = [
"${serverCfg.configPath}/handbrake/config:/config:rw"
"${serverCfg.dataPath}/handbrake/watch:/watch:rw"
"${serverCfg.dataPath}/handbrake/output:/output:rw"
"${serverCfg.path.config}/handbrake:/config:rw"
"${serverCfg.path.dlComplete}:/watch:rw"
"${serverCfg.path.dlConverted}:/output:rw"
];
};
};
@@ -51,9 +40,9 @@ in {
setup = {
trigger = "server";
script = pkgs.writeShellScript "setup" ''
mkdir -p ${serverCfg.dataPath}/handbrake/{watch,output}
mkdir -p ${serverCfg.path.data}/handbrake/{watch,output}
'';
};
};
}
@@ -4,6 +4,7 @@ let
serverCfg = config.syscfg.server;
in {
runtime = {
vm = {
portForward = [ 8123 ];
cfg = {cfg,...}: {
@@ -97,5 +98,5 @@ in {
fi
'';
};
};
}
+2 -4
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 {
};
};
};
};
}
+15 -8
View File
@@ -4,14 +4,19 @@ let
serverCfg = config.syscfg.server;
in {
sops = true;
db = true;
requires = {
secrets = [ name ];
databases = [ name ];
};
runtime = {
paths = [{
path = "${serverCfg.configPath}/immich/cache";
path = "${serverCfg.path.config}/immich";
dirs = ["cache"];
mode = "0750";
}{
path = "${serverCfg.dataPath}/immich/";
path = "${serverCfg.path.data}/immich/";
dirs = ["upload" "thumbs" "encoded-video" "backups"];
mode = "0755";
}];
@@ -33,7 +38,10 @@ in {
};
overrides = {
volumes = [
"${serverCfg.dataPath}/immich:/data"
"${serverCfg.path.photo}:/data/upload"
"${serverCfg.path.data}/immich/backups:/data/backups"
"${serverCfg.path.config}/immich/thumbs:/data/thumbs"
"${serverCfg.path.config}/immich/encoded-video:/data/encoded-video"
];
};
};
@@ -43,7 +51,7 @@ in {
port = 3003;
overrides = {
volumes = [
"${serverCfg.configPath}/immich/cache:/cache"
"${serverCfg.path.config}/immich/cache:/cache"
];
};
};
@@ -57,8 +65,6 @@ in {
$PSQL -d "immich_db" -tAc "CREATE EXTENSION IF NOT EXISTS vchord CASCADE;"
$PSQL -d "immich_db" -tAc "CREATE EXTENSION IF NOT EXISTS earthdistance CASCADE;"
mkdir -p ${serverCfg.dataPath}/immich/{upload,library,thumbs,encoded-video,profile,backups}
IMMICH_URL="https://${containerCfg.subdomain}.${serverCfg.domain}"
until [[ "$(${pkgs.curl}/bin/curl -s -o /dev/null -w "%{http_code}" "$IMMICH_URL")" =~ (200|301|302) ]]; do
sleep 5
@@ -94,4 +100,5 @@ in {
'';
};
};
}
+17 -14
View File
@@ -5,14 +5,19 @@ let
in {
sops = true;
db = true;
requires = {
secrets = [ name ];
databases = [ name ];
};
runtime = {
paths = [{
path = "${serverCfg.configPath}/influxdb/";
path = "${serverCfg.path.config}/influxdb/";
owner = "1500:1500";
mode = "0700";
}{
path = "${serverCfg.dataPath}/influxdb/";
path = "${serverCfg.path.data}/influxdb/";
owner = "1500:1500";
mode = "0700";
}];
@@ -28,13 +33,14 @@ in {
# };
# overrides = {
# volumes = [
# "${serverCfg.dataPath}/influxdb:/db:rw"
# "${serverCfg.configPath}/influxdb:/config:ro"
# "${serverCfg.path.data}/influxdb:/db:rw"
# "${serverCfg.path.config}/influxdb:/config:ro"
# ];
# };
# };
server = builder.mkContainer {
tmpfs = true;
subdomain = containerCfg.subdomain;
image = "influxdata/influxdb3-ui:${version}";
port = 8080;
@@ -43,15 +49,12 @@ 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" ];
volumes = [
"${serverCfg.dataPath}/influxdb:/db:rw"
"${serverCfg.configPath}/influxdb/:/app-root/config:ro"
"${serverCfg.path.data}/influxdb:/db:rw"
"${serverCfg.path.config}/influxdb/:/app-root/config:ro"
];
};
};
@@ -60,7 +63,7 @@ in {
setup = {
trigger = "server";
script = pkgs.writeShellScript "setup" ''
cat > ${serverCfg.configPath}/influxdb/config.json << 'EOF'
cat > ${serverCfg.path.config}/influxdb/config.json << 'EOF'
{
"DEFAULT_INFLUX_SERVER": "http://${builder.host}:8181",
"DEFAULT_INFLUX_DATABASE": "main",
@@ -68,8 +71,8 @@ in {
"DEFAULT_SERVER_NAME": "${serverCfg.domain}"
}
EOF
chmod -R 755 ${serverCfg.configPath}/influxdb
chmod -R 755 ${serverCfg.path.config}/influxdb
'';
};
};
}
+10 -5
View File
@@ -24,10 +24,14 @@ let
};
in {
sops = true;
db = true;
requires = {
secrets = [ name ];
databases = [ name ];
};
runtime = {
paths = [{
path="${serverCfg.configPath}/invidious";
path="${serverCfg.path.config}/invidious";
mode = "0755";
}];
@@ -49,7 +53,7 @@ in {
};
overrides = {
volumes = [
"${serverCfg.configPath}/invidious:/data:ro"
"${serverCfg.path.config}/invidious:/data:ro"
];
};
};
@@ -72,7 +76,8 @@ in {
export DB_HOST=${builder.host}
export INVIDIOUS_DOMAIN=${containerCfg.subdomain}.${serverCfg.domain}
${pkgs.gettext}/bin/envsubst < "${../data/invidious/config.yml}" > "${serverCfg.configPath}/invidious/config.yml"
${pkgs.gettext}/bin/envsubst < "${../data/invidious/config.yml}" > "${serverCfg.path.config}/invidious/config.yml"
'';
};
};
}
+7 -13
View File
@@ -25,14 +25,10 @@ let
};
};
in {
runtime = {
paths = [
{
path = "${serverCfg.dataPath}/media/";
owner = "1000:1000";
mode = "0755";
}
{
path = "${serverCfg.configPath}/jellyfin/";
path = "${serverCfg.path.config}/jellyfin/";
owner = "1000:1000";
mode = "0755";
}
@@ -40,6 +36,7 @@ in {
containers = {
server = builder.mkContainer {
tmpfs = true;
subdomain = containerCfg.subdomain;
imageStream = image;
port = 8096;
@@ -49,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"
@@ -60,8 +54,8 @@ in {
"--logdir" "/config/log"
];
volumes = [
"${serverCfg.dataPath}/media:/media:ro"
"${serverCfg.configPath}/jellyfin:/config"
"${serverCfg.path.film}:/media:ro"
"${serverCfg.path.config}/jellyfin:/config"
];
# If you have an Intel/AMD GPU for transcoding, add the device:
devices = lib.optionals (builtins.pathExists "/dev/dri") [ "/dev/dri:/dev/dri" ];
@@ -169,7 +163,7 @@ in {
fi
''}
${pkgs.sqlite}/bin/sqlite3 ${serverCfg.configPath}/jellyfin/data/data/jellyfin.db <<EOF
${pkgs.sqlite}/bin/sqlite3 ${serverCfg.path.config}/jellyfin/data/data/jellyfin.db <<EOF
INSERT OR IGNORE INTO ApiKeys (Id, AccessToken, Name, DateCreated, DateLastActivity)
VALUES ( 1, "$HOMEPAGE_VAR_JELLYFIN_API", 'Home', strftime('%Y-%m-%d %H:%M:%S', 'now'), strftime('%Y-%m-%d %H:%M:%S', 'now'));
EOF
@@ -177,5 +171,5 @@ EOF
'';
};
};
}
+19 -20
View File
@@ -3,21 +3,21 @@ let
version = "31";
serverCfg = config.syscfg.server;
in {
sops = true;
db = true;
requires = {
secrets = [ name ];
databases = [ name ];
};
runtime = {
paths = [{
path="${serverCfg.dataPath}/nextcloud/www";
path="${serverCfg.path.config}/nextcloud";
owner = "33:33";
mode = "0755";
}{
path="${serverCfg.dataPath}/nextcloud/data";
owner = "33:33";
mode = "0755";
backup = true;
}];
containers = {
server = builder.mkContainer {
tmpfs = true;
subdomain = containerCfg.subdomain;
image = "nextcloud:${version}";
port = 80;
@@ -28,13 +28,14 @@ in {
POSTGRES_USER = "nextcloud_user";
POSTGRES_DB = "nextcloud_db";
AUTHENTIK_POSTGRESQL__SSLMODE = "disable";
"NEXTCLOUD_TRUSTED_DOMAINS " = "${containerCfg.subdomain}.${serverCfg.domain} nextcloud-server";
"SMTP_HOST" = serverCfg.mailServer;
"SMTP_NAME" = "mail_user";
"SMTP_PASSWORD" = "mail_password";
"MAIL_FROM_ADDRESS" = "${containerCfg.subdomain}@${serverCfg.domain}";
"MAIL_DOMAIN" = serverCfg.mailDomain;
"TRUSTED_PROXIES" = "10.10.0.0/16 192.168.0.0/16";
NEXTCLOUD_TRUSTED_DOMAINS = "${containerCfg.subdomain}.${serverCfg.domain} nextcloud-server";
SMTP_HOST = serverCfg.mail.server;
SMTP_NAME = "mail_user";
SMTP_PASSWORD = "mail_password";
MAIL_FROM_ADDRESS = "${containerCfg.subdomain}@${serverCfg.domain}";
MAIL_DOMAIN = serverCfg.mail.domain;
TRUSTED_PROXIES = "10.10.0.0/16 192.168.0.0/16";
NEXTCLOUD_DATA_DIR = "/var/www/html/data";
};
extraLabels = {
"traefik.http.routers.${containerCfg.subdomain}.middlewares" = "sts_headers,${containerCfg.subdomain}-caldav";
@@ -44,14 +45,11 @@ 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 = [
"${serverCfg.dataPath}/nextcloud/www:/var/www/html"
"${serverCfg.dataPath}/nextcloud/data:/var/www/html/data"
"${serverCfg.path.config}/nextcloud:/var/www/html"
"${serverCfg.path.cloud}:/var/www/html/data"
];
};
};
@@ -197,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" ];
};
}
+8 -8
View File
@@ -4,12 +4,11 @@ let
version = "5.1.4";
in {
sops = false;
db = false;
runtime = {
paths = [
{ path="${serverCfg.configPath}/openhab/conf"; owner="1000:1000"; mode = "0755"; }
{ path="${serverCfg.configPath}/openhab/userdata"; owner="1000:1000"; mode = "0755"; }
{ path="${serverCfg.configPath}/openhab/addons"; owner="1000:1000"; mode = "0755"; }
{ path="${serverCfg.path.config}/openhab/conf"; owner="1000:1000"; mode = "0755"; }
{ path="${serverCfg.path.config}/openhab/userdata"; owner="1000:1000"; mode = "0755"; }
{ path="${serverCfg.path.config}/openhab/addons"; owner="1000:1000"; mode = "0755"; }
];
containers = {
@@ -31,9 +30,9 @@ in {
];
overrides = {
volumes = [
"${serverCfg.configPath}/openhab/conf:/openhab/conf"
"${serverCfg.configPath}/openhab/userdata:/openhab/userdata"
"${serverCfg.configPath}/openhab/addons:/opt/openhab/addons"
"${serverCfg.path.config}/openhab/conf:/openhab/conf"
"${serverCfg.path.config}/openhab/userdata:/openhab/userdata"
"${serverCfg.path.config}/openhab/addons:/opt/openhab/addons"
"/var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket:ro"
];
};
@@ -74,4 +73,5 @@ in {
#Extra: AndroidTV/Jellyfin (Bind with lights + more)
'';
};
};
}
+3 -8
View File
@@ -59,12 +59,9 @@ let
};
});
in {
sops = true;
# paths = [{
# path="${serverCfg.dataPath}/searxng/";
# mode = "0444";
# }];
requires.secrets = [ name ];
runtime = {
containers = {
server = builder.mkContainer {
subdomain = containerCfg.subdomain;
@@ -80,13 +77,11 @@ in {
#SEARXNG_VALKEY_URL = "valkey://user:password@${builder.host}:6379/0}";
};
overrides = {
cmd = [ ];
volumes = [
"${settings}:/etc/searxng/settings.yml"
# "/path/to/your/logo.png:/usr/local/searxng/searx/static/themes/simple/img/searxng.png
# "${serverCfg.dataPath}/searxng:/var/cache/searxng/"
];
};
};
};
};
}
+9 -14
View File
@@ -2,20 +2,16 @@
let
version = "latest";
serverCfg = config.syscfg.server;
routerName = if containerCfg.subpath != null
then "${containerCfg.subdomain}-${lib.strings.sanitizeDerivationName containerCfg.subpath}"
else containerCfg.subdomain;
in {
sops = false;
db = false;
runtime = {
paths = [{
path = "${serverCfg.configPath}/selfmark/";
path = "${serverCfg.path.config}/selfmark/";
mode = "0444";
}];
containers = {
server = builder.mkContainer {
authentik = true;
subdomain = containerCfg.subdomain;
subpath = containerCfg.subpath;
image = "ghcr.io/calibrain/shelfmark:${version}";
@@ -81,15 +77,14 @@ in {
EXT_BYPASSER_PATH = "/v1";
EXT_BYPASSER_TIMEOUT = "60000";
};
extraLabels = {
} // (if serverCfg.containers ? authentik then {
"traefik.http.routers.${routerName}.middlewares" = "authentik";
} else {});
overrides = {
volumes = [ ];
volumes = [
"${serverCfg.path.dlComplete}:/books:rw"
"${serverCfg.path.books}:/output:rw"
"${serverCfg.path.config}/selfmark:/config:rw"
];
};
};
};
};
}
+11 -17
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
'';
};
};
}
+9 -4
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}";
@@ -40,9 +43,11 @@ in {
overrides = {
volumes = [
"${serverCfg.path.manga}:/home/suwayomi/.local/share/Tachidesk/downloads"
# "${serverCfg.path.config}/suwayomi:/home/suwayomi/.local/share/Tachidesk"
];
};
};
};
};
}
+7 -5
View File
@@ -11,9 +11,11 @@ let
};
};
in {
sops = true;
requires.secrets = [ name ];
runtime = {
paths = [{
path="${serverCfg.configPath}/traefik";
path="${serverCfg.path.config}/traefik";
owner = "1000:1000";
mode = "0755";
}];
@@ -77,11 +79,11 @@ in {
ports = [ "443:443" "80:80" ] ++ (if containerCfg.port!=null then [ "${toString containerCfg.port}:8080" ] else []);
volumes = [
"/var/run/podman/podman.sock:/var/run/docker.sock"
# "${serverCfg.configPath}/traefik/access.log:/etc/traefik/access.log"
"${serverCfg.configPath}/traefik:/custom"
# "${serverCfg.path.config}/traefik/access.log:/etc/traefik/access.log"
"${serverCfg.path.config}/traefik:/custom"
];
};
};
};
};
}
@@ -13,26 +13,17 @@ let
};
};
};
routerName = if containerCfg.subpath != null
then "${containerCfg.subdomain}-${lib.strings.sanitizeDerivationName containerCfg.subpath}"
else containerCfg.subdomain;
in {
runtime = {
paths = [{
path = "${serverCfg.dataPath}/transmission/complete";
owner = "1000:1000";
mode = "0755";
}{
path = "${serverCfg.dataPath}/transmission/incomplete";
owner = "1000:1000";
mode = "0755";
}{
path = "${serverCfg.configPath}/transmission/config";
path = "${serverCfg.path.config}/transmission";
owner = "1000:1000";
mode = "0755";
}];
containers = {
server = builder.mkContainer {
authentik = true;
subdomain = containerCfg.subdomain;
subpath = containerCfg.subpath;
imageStream = image;
@@ -44,17 +35,12 @@ 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 = {
cmd = [ ];
volumes = [
"${serverCfg.dataPath}/transmission/complete:/downloads/complete"
"${serverCfg.dataPath}/transmission/incomplete:/downloads/incomplete"
"${serverCfg.configPath}/transmission/config:/config"
"${serverCfg.path.dlComplete}:/downloads/complete"
"${serverCfg.path.dlIncomplete}:/downloads/incomplete"
"${serverCfg.path.config}/transmission:/config"
];
};
};
@@ -66,8 +52,8 @@ in {
envFile = [ config.sops.secrets."CUSTOM".path ];
script = pkgs.writeShellScript "setup" ''
${pkgs.gettext}/bin/envsubst < "${../data/transmission/settings.json}" > "${serverCfg.configPath}/transmission/config/settings.json"
${pkgs.gettext}/bin/envsubst < "${../data/transmission/settings.json}" > "${serverCfg.path.config}/transmission/config/settings.json"
'';
};
};
}
+10 -10
View File
@@ -15,15 +15,21 @@ let
};
};
in {
sops = true;
db = true;
requires = {
secrets = [ name ];
databases = [ name ];
};
runtime = {
paths = [{
path = "${serverCfg.configPath}/umami/";
path = "${serverCfg.path.config}/umami/";
mode = "0444";
}];
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
};
};
};
};
}
+49 -5
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" {
@@ -69,6 +89,30 @@ let
in {
mkContainer = contBuilder;
mkVm = vmBuilder;
mkApp = name: app:
{
inherit name;
requires = {
secrets = getOr app [ "requires" "secrets" ] [ ];
databases = getOr app [ "requires" "databases" ] [ ];
};
exports = {
authentik = {
blueprints = getOr app [ "exports" "authentik" "blueprints" ] [ ];
};
};
runtime = {
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 = [ ];
} // getOr app [ "runtime" "setup" ] { };
};
};
mkData = { name, dir, vars?{} }: pkgs.runCommand name vars ''
mkdir -p $out
cp -r ${./data + "/${dir}"}/. $out/
+36 -33
View File
@@ -2,30 +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:
(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.containers
) config.syscfg.server.loadedContainers;
allPathConfigs = lib.concatMap (app: app.paths) appsList;
allSetupConfigs = lib.concatMap (app: if app.setup?script then [({name = app.name; envFile="";} // app.setup)] else []) appsList;
allCronsConfigs = lib.concatMap (app: app.cron) appsList;
allVMConfigs = builtins.filter (app: app.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:
lib.mapAttrs' (cName: cCfg: lib.nameValuePair "${appName}-${cName}" cCfg) app.runtime.containers
) loadedContainers;
allPathConfigs = map (path: {
inherit path;
mode = "0755";
}) (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;
mkPathSetup = cfg:
let
effectiveCfg = {
owner = "root:root";
@@ -37,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 = {
@@ -52,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}";
@@ -69,12 +74,12 @@ in{
RestartSec = "10s";
ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p /media/data/kvm";
ExecStart = ''
${builder.mkVm { name = e.name; vm = e.vm; }}/bin/run-${e.name}-vm -nographic
${builder.mkVm { name = e.name; vm = e.runtime.vm; }}/bin/run-${e.name}-vm -nographic
'';
};
};
}]) allVMConfigs)
// lib.listToAttrs (lib.concatMap (e: [{
}) allVMConfigs
// mkNamedUnits (e: {
name = "${e.name}-setup";
value = {
description = "Run ${e.name} setup";
@@ -90,13 +95,11 @@ in{
User = "root";
};
};
}]) allSetupConfigs );
}) allSetupConfigs;
services.cron = {
enable = true;
systemCronJobs = allCronsConfigs;
};
}))];
})];
}
+4 -3
View File
@@ -3,7 +3,7 @@
let
listNames = config.syscfg.server.db;
containerNames = builtins.attrNames (lib.filterAttrs (appName: app: app.db) config.syscfg.server.loadedContainers);
containerNames = lib.concatMap (app: app.requires.databases) (builtins.attrValues config.syscfg.server.loadedContainers);
allApps = lib.unique (listNames ++ containerNames);
in {
config = lib.mkIf ( builtins.length allApps > 0) {
@@ -47,9 +47,10 @@ in {
environment = {
INFLUXDB3_NODE_IDENTIFIER_PREFIX = "node0";
INFLUXDB3_OBJECT_STORE = "file";
INFLUXDB3_DATA_DIR = "${config.syscfg.server.dataPath}/influxdb";
INFLUXDB3_DB_DIR = "${config.syscfg.server.dataPath}/influxdb";
INFLUXDB3_DATA_DIR = "${config.syscfg.server.path.data}/influxdb";
INFLUXDB3_DB_DIR = "${config.syscfg.server.path.data}/influxdb";
INFLUXDB3_ENABLE_INTERNAL_DB = "true";
INFLUXDB3_AUTH_TOKEN = "b27686e85a883437666f61586e084f7deb763958497739479ca48bc913ee90afd1a920332156133c89fb8674cb197ced17706074e6a42fc7ce6b2d54ac6119c9";
INFLUXDB3_INITIAL_ADMIN_TOKEN = "b27686e85a883437666f61586e084f7deb763958497739479ca48bc913ee90afd1a920332156133c89fb8674cb197ced17706074e6a42fc7ce6b2d54ac6119c9";
};
serviceConfig = {
+1 -1
View File
@@ -1,7 +1,7 @@
{ config, lib, pkgs, ... }:
let
listNames = config.syscfg.server.db;
containerNames = builtins.attrNames (lib.filterAttrs (appName: app: app.sops) config.syscfg.server.loadedContainers);
containerNames = lib.concatMap (app: app.requires.secrets) (builtins.attrValues config.syscfg.server.loadedContainers);
allApps = lib.unique (listNames ++ containerNames);
in{
sops.secrets = {
+55 -13
View File
@@ -3,16 +3,32 @@ let
in with lib; {
domain = mkOption { type = types.str; };
mailDomain = mkOption { type = types.str; };
mailServer = mkOption { type = types.str; };
mail = {
domain = mkOption { type = types.str; default = null;};
server = mkOption { type = types.str; default = null;};
configPath = mkOption {
type = types.str;
default = "/media/config";
};
dataPath = mkOption {
type = types.str;
default = "/media/data";
path = mkOption {
type = types.submodule {
freeformType = types.attrsOf types.str;
options = {
config = mkOption { type = types.str; default = "/media/config"; };
data = mkOption { type = types.str; default = "/media/data"; };
download = mkOption { type = types.str; default = "/media/data/download"; };
cloud = mkOption { type = types.str; default ="/media/media/cloud"; };
film = mkOption { type = types.str; default ="/media/media/film"; };
book = mkOption { type = types.str; default ="/media/media/book"; };
manga = mkOption { type = types.str; default ="/media/media/manga"; };
photo = mkOption { type = types.str; default ="/media/media/photo"; };
# music = mkOption { type = types.str; default ="/media/media/music"; };
dlComplete = mkOption { type = types.str; default ="/media/download/complete"; };
dlIncomplete = mkOption { type = types.str; default ="/media/download/incomplete"; };
dlConverted = mkOption { type = types.str; default ="/media/download/converted"; };
};
};
default = {};
};
colorScheme = mkOption {
@@ -24,18 +40,44 @@ in with lib; {
type = lib.types.attrsOf (lib.types.submodule ({ name, ... }: {
options = {
name = lib.mkOption {type = lib.types.str; default = name;};
sops = lib.mkOption {type = lib.types.bool; default = false;};
db = lib.mkOption {type = lib.types.bool; default = false;};
requires = {
secrets = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
};
databases = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
};
};
exports = {
authentik = {
blueprints = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
};
};
};
runtime = {
paths = lib.mkOption {type = lib.types.listOf lib.types.attrs; default = [ ];};
containers = lib.mkOption {type = lib.types.attrsOf lib.types.attrs; default = { };};
vm = lib.mkOption {type = lib.types.nullOr lib.types.attrs; default = null;};
cron = lib.mkOption {type = lib.types.listOf lib.types.str; default = [ ];};
setup = {
setup = lib.mkOption {
type = lib.types.submodule {
options = {
trigger = lib.mkOption {type = lib.types.str; default = "";};
script = lib.mkOption {type = lib.types.nullOr lib.types.package; default = null;};
envFile = lib.mkOption {type = with lib.types; coercedTo str (x: [x]) (listOf str); default = [];};
envFile = lib.mkOption {
type = with lib.types; coercedTo str (x: [x]) (listOf str);
default = [ ];
};
};
};
default = { };
};
};
};
}));
-2
View File
@@ -27,8 +27,6 @@
# user = ...
# ...
# };
mailDomain = "test@helcel";
mailServer = "infomaniak.ch";
containers = {
# ===== BASE =====