Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9a89479f66 | |||
| b82393272c | |||
| 1cb9e9b645 | |||
| b8735803c4 | |||
| 14bf297897 | |||
| 1fad610dff | |||
| 2c00901b04 | |||
| 2c0ac0db09 | |||
| 6be107374e | |||
| 9e4d8274b5 | |||
| f54dea8a13 | |||
| a6788f13a8 | |||
| 5b4af162b9 | |||
| 4e5c956f78 | |||
| 083549e3c6 | |||
| fada3c79b3 | |||
| ce72e4421b | |||
| ddc5c76a35 | |||
| d0b6718254 | |||
| c1c76ab3de | |||
| 558874731a | |||
| b14135274b | |||
| 5df88ac25a | |||
| 2d8e0da386 | |||
| 8f87c11cb5 | |||
| 7b8eeb917f | |||
| a2043cafe1 |
@@ -38,24 +38,27 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
outputs = inputs:
|
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 {
|
in {
|
||||||
devShells = import ./shells { inherit inputs; };
|
devShells = import ./shells { inherit inputs; };
|
||||||
|
|
||||||
nixosConfigurations = {
|
nixosConfigurations = generateHosts "nixos";
|
||||||
valinor = gen.generate { host = "valinor"; };
|
darwinConfigurations = generateHosts "macos";
|
||||||
iriy = gen.generate { host = "iriy"; };
|
homeConfigurations = generateHosts "home";
|
||||||
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"; };
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# ===== Unsupported/NotImplemented ======
|
# ===== Unsupported/NotImplemented ======
|
||||||
|
|||||||
@@ -17,10 +17,14 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
sops = false;
|
requires = {
|
||||||
db = false;
|
secrets = [ ];
|
||||||
|
databases = [ ];
|
||||||
|
};
|
||||||
|
|
||||||
|
runtime = {
|
||||||
paths = [{
|
paths = [{
|
||||||
path="${serverCfg.configPath}/example/";
|
path="${serverCfg.path.config}/example/";
|
||||||
mode = "0444";
|
mode = "0444";
|
||||||
}];
|
}];
|
||||||
|
|
||||||
@@ -46,4 +50,5 @@ in {
|
|||||||
...
|
...
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,15 +16,16 @@ let
|
|||||||
// (if serverCfg.containers?nextcloud then { NEXTCLOUD_DOMAIN = "${serverCfg.containers.nextcloud.subdomain}.${serverCfg.domain}";} else {});
|
// (if serverCfg.containers?nextcloud then { NEXTCLOUD_DOMAIN = "${serverCfg.containers.nextcloud.subdomain}.${serverCfg.domain}";} else {});
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
sops = true;
|
requires = {
|
||||||
db = true;
|
secrets = [ name ];
|
||||||
|
databases = [ name ];
|
||||||
|
};
|
||||||
|
|
||||||
|
runtime = {
|
||||||
paths = [{
|
paths = [{
|
||||||
path="${serverCfg.configPath}/authentik/media";
|
path="${serverCfg.path.config}/authentik";
|
||||||
owner = "1000:1000";
|
|
||||||
mode = "0755";
|
|
||||||
}{
|
|
||||||
path="${serverCfg.configPath}/authentik/templates";
|
|
||||||
owner = "1000:1000";
|
owner = "1000:1000";
|
||||||
|
dirs = ["media" "templates"];
|
||||||
mode = "0755";
|
mode = "0755";
|
||||||
}];
|
}];
|
||||||
|
|
||||||
@@ -55,8 +56,8 @@ in {
|
|||||||
|
|
||||||
cmd = [ "server" ];
|
cmd = [ "server" ];
|
||||||
volumes = [
|
volumes = [
|
||||||
"${serverCfg.configPath}/authentik/media:/media"
|
"${serverCfg.path.config}/authentik/media:/media"
|
||||||
"${serverCfg.configPath}/authentik/templates:/templates"
|
"${serverCfg.path.config}/authentik/templates:/templates"
|
||||||
"${authentikData}:/blueprints/custom:ro"
|
"${authentikData}:/blueprints/custom:ro"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
@@ -77,8 +78,8 @@ in {
|
|||||||
overrides = {
|
overrides = {
|
||||||
cmd = [ "worker" ];
|
cmd = [ "worker" ];
|
||||||
volumes = [
|
volumes = [
|
||||||
"${serverCfg.configPath}/authentik/media:/media"
|
"${serverCfg.path.config}/authentik/media:/media"
|
||||||
"${serverCfg.configPath}/authentik/templates:/templates"
|
"${serverCfg.path.config}/authentik/templates:/templates"
|
||||||
"${authentikData}:/blueprints/custom:ro"
|
"${authentikData}:/blueprints/custom:ro"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
@@ -114,4 +115,5 @@ in {
|
|||||||
echo "Completed Authentik Setup"
|
echo "Completed Authentik Setup"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,16 +3,7 @@ let
|
|||||||
version = "latest";
|
version = "latest";
|
||||||
serverCfg = config.syscfg.server;
|
serverCfg = config.syscfg.server;
|
||||||
in {
|
in {
|
||||||
sops = false;
|
runtime = {
|
||||||
db = false;
|
|
||||||
paths = [
|
|
||||||
{
|
|
||||||
path = "${serverCfg.configPath}/calibre-web/";
|
|
||||||
mode = "0755";
|
|
||||||
dirs = ["library" "ingest"];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
containers = {
|
containers = {
|
||||||
server = builder.mkContainer {
|
server = builder.mkContainer {
|
||||||
subdomain = containerCfg.subdomain;
|
subdomain = containerCfg.subdomain;
|
||||||
@@ -35,14 +26,14 @@ in {
|
|||||||
"traefik.http.routers.${containerCfg.subdomain}-login.tls" = "true";
|
"traefik.http.routers.${containerCfg.subdomain}-login.tls" = "true";
|
||||||
};
|
};
|
||||||
overrides = {
|
overrides = {
|
||||||
cmd = [ ];
|
|
||||||
volumes = [
|
volumes = [
|
||||||
"${serverCfg.configPath}/calibre-web/library/:/calibre-library"
|
"${serverCfg.path.book}:/calibre-library"
|
||||||
"${serverCfg.configPath}/calibre-web/ingest/:/cwa-book-ingest"
|
"${serverCfg.path.dlBook}:/cwa-book-ingest"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
# curl 'https://books.test.helcel.net/admin/ajaxconfig' \
|
# curl 'https://books.test.helcel.net/admin/ajaxconfig' \
|
||||||
# -X POST
|
# -X POST
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ let
|
|||||||
version = "latest";
|
version = "latest";
|
||||||
serverCfg = config.syscfg.server;
|
serverCfg = config.syscfg.server;
|
||||||
in {
|
in {
|
||||||
sops = true;
|
requires.secrets = [ name ];
|
||||||
|
|
||||||
|
runtime = {
|
||||||
containers = {
|
containers = {
|
||||||
server = builder.mkContainer {
|
server = builder.mkContainer {
|
||||||
subdomain = containerCfg.subdomain;
|
subdomain = containerCfg.subdomain;
|
||||||
@@ -31,4 +33,5 @@ in {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,9 +13,11 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
sops = true;
|
requires.secrets = [ name ];
|
||||||
|
|
||||||
|
runtime = {
|
||||||
paths = [{
|
paths = [{
|
||||||
path="${serverCfg.dataPath}/ethercalc/";
|
path="${serverCfg.path.data}/ethercalc/";
|
||||||
mode = "0666";
|
mode = "0666";
|
||||||
}];
|
}];
|
||||||
|
|
||||||
@@ -31,9 +33,10 @@ in {
|
|||||||
};
|
};
|
||||||
overrides = {
|
overrides = {
|
||||||
volumes = [
|
volumes = [
|
||||||
"${serverCfg.dataPath}/ethercalc:/data"
|
"${serverCfg.path.data}/ethercalc:/data"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,10 +76,14 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
sops = true;
|
requires = {
|
||||||
db = true;
|
secrets = [ name ];
|
||||||
|
databases = [ name ];
|
||||||
|
};
|
||||||
|
|
||||||
|
runtime = {
|
||||||
paths = [{
|
paths = [{
|
||||||
path="${serverCfg.configPath}/etherpad/";
|
path="${serverCfg.path.config}/etherpad/";
|
||||||
mode = "0444";
|
mode = "0444";
|
||||||
}];
|
}];
|
||||||
|
|
||||||
@@ -107,7 +111,7 @@ in {
|
|||||||
cmd = [ "--settings" "/etc/etherpad/settings.json" "--apikey" "/etc/etherpad/APIKEY.txt" ];
|
cmd = [ "--settings" "/etc/etherpad/settings.json" "--apikey" "/etc/etherpad/APIKEY.txt" ];
|
||||||
volumes = [
|
volumes = [
|
||||||
"${settings}:/etc/etherpad/settings.json"
|
"${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";
|
trigger = "server";
|
||||||
envFile = config.sops.secrets."ETHERPAD".path;
|
envFile = config.sops.secrets."ETHERPAD".path;
|
||||||
script = pkgs.writeShellScript "setup" ''
|
script = pkgs.writeShellScript "setup" ''
|
||||||
echo "$APIKEY" > ${serverCfg.configPath}/etherpad/APIKEY.txt
|
echo "$APIKEY" > ${serverCfg.path.config}/etherpad/APIKEY.txt
|
||||||
chmod 444 ${serverCfg.configPath}/etherpad/APIKEY.txt
|
chmod 444 ${serverCfg.path.config}/etherpad/APIKEY.txt
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,15 @@ let
|
|||||||
version = "latest";
|
version = "latest";
|
||||||
serverCfg = config.syscfg.server;
|
serverCfg = config.syscfg.server;
|
||||||
in {
|
in {
|
||||||
sops = true;
|
requires = {
|
||||||
db = true;
|
secrets = [ name ];
|
||||||
|
databases = [ name ];
|
||||||
|
};
|
||||||
|
|
||||||
|
runtime = {
|
||||||
paths = [
|
paths = [
|
||||||
{
|
{
|
||||||
path = "${serverCfg.configPath}/freshrss";
|
path = "${serverCfg.path.config}/freshrss";
|
||||||
owner = "1000:1000";
|
owner = "1000:1000";
|
||||||
mode = "0755";
|
mode = "0755";
|
||||||
}
|
}
|
||||||
@@ -33,7 +37,7 @@ in {
|
|||||||
|
|
||||||
overrides = {
|
overrides = {
|
||||||
environmentFiles = [ config.sops.secrets."FRESHRSS".path config.sops.secrets."CUSTOM".path ];
|
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 {
|
|||||||
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -27,12 +27,12 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
sops = true; # Enabled to safeguard sensitive camera RTSP stream credentials
|
requires.secrets = [ name ];
|
||||||
db = false; # Internal SQLite is used by default in Frigate
|
|
||||||
|
|
||||||
|
runtime = {
|
||||||
paths = [
|
paths = [
|
||||||
{
|
{
|
||||||
path = "${serverCfg.configPath}/frigate/";
|
path = "${serverCfg.path.config}/frigate/";
|
||||||
mode = "0755";
|
mode = "0755";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@@ -53,7 +53,7 @@ in {
|
|||||||
overrides = {
|
overrides = {
|
||||||
cmd = [ ];
|
cmd = [ ];
|
||||||
volumes = [
|
volumes = [
|
||||||
"${serverCfg.configPath}/frigate:/config"
|
"${serverCfg.path.config}/frigate:/config"
|
||||||
"/var/lib/frigate/storage:/media/frigate"
|
"/var/lib/frigate/storage:/media/frigate"
|
||||||
"/dev/bus/usb:/dev/bus/usb" # Passes Google Coral USB TPU to the container
|
"/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
|
"/dev/dri:/dev/dri" # Passes Intel/AMD GPU for hardware video decoding
|
||||||
@@ -66,12 +66,12 @@ in {
|
|||||||
trigger = "server";
|
trigger = "server";
|
||||||
envFile = config.sops.secrets."FRIGATE_ENV".path;
|
envFile = config.sops.secrets."FRIGATE_ENV".path;
|
||||||
script = pkgs.writeShellScript "setup-frigate" ''
|
script = pkgs.writeShellScript "setup-frigate" ''
|
||||||
mkdir -p "${serverCfg.configPath}/frigate"
|
mkdir -p "${serverCfg.path.config}/frigate"
|
||||||
mkdir -p "/var/lib/frigate/storage"
|
mkdir -p "/var/lib/frigate/storage"
|
||||||
|
|
||||||
# Bootstrap a standard configuration layout if missing
|
# Bootstrap a standard configuration layout if missing
|
||||||
if [ ! -f "${serverCfg.configPath}/frigate/config.yml" ]; then
|
if [ ! -f "${serverCfg.path.config}/frigate/config.yml" ]; then
|
||||||
cat <<EOF > "${serverCfg.configPath}/frigate/config.yml"
|
cat <<EOF > "${serverCfg.path.config}/frigate/config.yml"
|
||||||
mqtt:
|
mqtt:
|
||||||
enabled: False # Set to True and define host if connecting to Home Assistant
|
enabled: False # Set to True and define host if connecting to Home Assistant
|
||||||
|
|
||||||
@@ -92,4 +92,5 @@ EOF
|
|||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,15 +5,16 @@ let
|
|||||||
|
|
||||||
LDAP_DC_DOMAIN = "dc=ldap," + (lib.concatMapStringsSep "," (x: "dc=${x}") (lib.splitString "." serverCfg.domain));
|
LDAP_DC_DOMAIN = "dc=ldap," + (lib.concatMapStringsSep "," (x: "dc=${x}") (lib.splitString "." serverCfg.domain));
|
||||||
in {
|
in {
|
||||||
sops = true;
|
requires = {
|
||||||
db = true;
|
secrets = [ name ];
|
||||||
|
databases = [ name ];
|
||||||
|
};
|
||||||
|
|
||||||
|
runtime = {
|
||||||
paths = [{
|
paths = [{
|
||||||
path="${serverCfg.dataPath}/gitea/data";
|
path="${serverCfg.path.data}/gitea";
|
||||||
owner = "1000:1000";
|
|
||||||
mode = "0755";
|
|
||||||
}{
|
|
||||||
path="${serverCfg.dataPath}/gitea/data-runner";
|
|
||||||
owner = "1000:1000";
|
owner = "1000:1000";
|
||||||
|
dirs = ["data" "runner"];
|
||||||
mode = "0755";
|
mode = "0755";
|
||||||
}];
|
}];
|
||||||
containers = {
|
containers = {
|
||||||
@@ -73,7 +74,7 @@ in {
|
|||||||
} else {});
|
} else {});
|
||||||
extraLabels = {
|
extraLabels = {
|
||||||
"traefik.http.routers.${containerCfg.subdomain}-login.rule" = "Host(`${containerCfg.subdomain}.${serverCfg.domain}`) && Path(`/user/login`) ";
|
"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.priority" = "100";
|
||||||
"traefik.http.routers.${containerCfg.subdomain}-login.entrypoints" = "web-secure";
|
"traefik.http.routers.${containerCfg.subdomain}-login.entrypoints" = "web-secure";
|
||||||
"traefik.http.routers.${containerCfg.subdomain}-login.tls" = "true";
|
"traefik.http.routers.${containerCfg.subdomain}-login.tls" = "true";
|
||||||
@@ -81,7 +82,7 @@ in {
|
|||||||
|
|
||||||
overrides = {
|
overrides = {
|
||||||
volumes = [
|
volumes = [
|
||||||
"${serverCfg.dataPath}/gitea/data:/data"
|
"${serverCfg.path.data}/gitea/data:/data"
|
||||||
];
|
];
|
||||||
ports = [ "2222:22" ];
|
ports = [ "2222:22" ];
|
||||||
};
|
};
|
||||||
@@ -98,7 +99,7 @@ in {
|
|||||||
|
|
||||||
overrides = {
|
overrides = {
|
||||||
volumes = [
|
volumes = [
|
||||||
"${serverCfg.dataPath}/gitea/data-runner:/data"
|
"${serverCfg.path.data}/gitea/runner:/data"
|
||||||
"/var/run/podman/podman.sock:/var/run/docker.sock"
|
"/var/run/podman/podman.sock:/var/run/docker.sock"
|
||||||
];
|
];
|
||||||
# ports = [ "8088:8088" ];
|
# 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
|
$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)
|
RUNNER_TOKEN=$($GT actions generate-runner-token)
|
||||||
$GTR register \
|
$GTR register \
|
||||||
@@ -141,4 +142,5 @@ in {
|
|||||||
echo "Completed Gitea Setup"
|
echo "Completed Gitea Setup"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -2,22 +2,17 @@
|
|||||||
let
|
let
|
||||||
serverCfg = config.syscfg.server;
|
serverCfg = config.syscfg.server;
|
||||||
version = "latest";
|
version = "latest";
|
||||||
|
|
||||||
routerName = if containerCfg.subpath != null
|
|
||||||
then "${containerCfg.subdomain}-${lib.strings.sanitizeDerivationName containerCfg.subpath}"
|
|
||||||
else containerCfg.subdomain;
|
|
||||||
in {
|
in {
|
||||||
|
runtime = {
|
||||||
paths = [{
|
paths = [{
|
||||||
path = "${serverCfg.configPath}/handbrake/config";
|
path = "${serverCfg.path.config}/handbrake";
|
||||||
mode = "0755";
|
|
||||||
} {
|
|
||||||
path = "${serverCfg.dataPath}/handbrake/";
|
|
||||||
mode = "0755";
|
mode = "0755";
|
||||||
}];
|
}];
|
||||||
|
|
||||||
containers = {
|
containers = {
|
||||||
server = builder.mkContainer {
|
server = builder.mkContainer {
|
||||||
|
authentik = true;
|
||||||
|
tmpfs = true;
|
||||||
subdomain = containerCfg.subdomain;
|
subdomain = containerCfg.subdomain;
|
||||||
subpath = containerCfg.subpath;
|
subpath = containerCfg.subpath;
|
||||||
image = "ghcr.io/jlesage/handbrake:${version}";
|
image = "ghcr.io/jlesage/handbrake:${version}";
|
||||||
@@ -30,18 +25,12 @@ in {
|
|||||||
AUTOMATED_CONVERSION_FORMAT = "mkv";
|
AUTOMATED_CONVERSION_FORMAT = "mkv";
|
||||||
AUTOMATED_CONVERSION_OUTPUT_SUBDIR = "SAME_AS_SRC";
|
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 = {
|
overrides = {
|
||||||
volumes = [
|
volumes = [
|
||||||
"${serverCfg.configPath}/handbrake/config:/config:rw"
|
"${serverCfg.path.config}/handbrake:/config:rw"
|
||||||
"${serverCfg.dataPath}/handbrake/watch:/watch:rw"
|
"${serverCfg.path.dlComplete}:/watch:rw"
|
||||||
"${serverCfg.dataPath}/handbrake/output:/output:rw"
|
"${serverCfg.path.dlConverted}:/output:rw"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -51,9 +40,9 @@ in {
|
|||||||
setup = {
|
setup = {
|
||||||
trigger = "server";
|
trigger = "server";
|
||||||
script = pkgs.writeShellScript "setup" ''
|
script = pkgs.writeShellScript "setup" ''
|
||||||
mkdir -p ${serverCfg.dataPath}/handbrake/{watch,output}
|
mkdir -p ${serverCfg.path.data}/handbrake/{watch,output}
|
||||||
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -4,9 +4,10 @@ let
|
|||||||
serverCfg = config.syscfg.server;
|
serverCfg = config.syscfg.server;
|
||||||
|
|
||||||
in {
|
in {
|
||||||
|
runtime = {
|
||||||
vm = {
|
vm = {
|
||||||
portForward = [ 8123 ];
|
portForward = [ 8123 ];
|
||||||
cfg = {cfg,...}:{
|
cfg = {cfg,...}: {
|
||||||
services.home-assistant = {
|
services.home-assistant = {
|
||||||
enable = true;
|
enable = true;
|
||||||
openFirewall = true;
|
openFirewall = true;
|
||||||
@@ -97,5 +98,5 @@ in {
|
|||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -258,9 +258,7 @@ let
|
|||||||
];}#)];}
|
];}#)];}
|
||||||
];
|
];
|
||||||
in {
|
in {
|
||||||
sops = false;
|
runtime = {
|
||||||
db = false;
|
|
||||||
|
|
||||||
containers = {
|
containers = {
|
||||||
server = builder.mkContainer {
|
server = builder.mkContainer {
|
||||||
subdomain = containerCfg.subdomain;
|
subdomain = containerCfg.subdomain;
|
||||||
@@ -284,5 +282,5 @@ in {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -4,14 +4,19 @@ let
|
|||||||
serverCfg = config.syscfg.server;
|
serverCfg = config.syscfg.server;
|
||||||
|
|
||||||
in {
|
in {
|
||||||
sops = true;
|
requires = {
|
||||||
db = true;
|
secrets = [ name ];
|
||||||
|
databases = [ name ];
|
||||||
|
};
|
||||||
|
|
||||||
|
runtime = {
|
||||||
paths = [{
|
paths = [{
|
||||||
path = "${serverCfg.configPath}/immich/cache";
|
path = "${serverCfg.path.config}/immich";
|
||||||
|
dirs = ["cache"];
|
||||||
mode = "0750";
|
mode = "0750";
|
||||||
}{
|
}{
|
||||||
path = "${serverCfg.dataPath}/immich/";
|
path = "${serverCfg.path.data}/immich/";
|
||||||
|
dirs = ["upload" "thumbs" "encoded-video" "backups"];
|
||||||
mode = "0755";
|
mode = "0755";
|
||||||
}];
|
}];
|
||||||
|
|
||||||
@@ -33,7 +38,10 @@ in {
|
|||||||
};
|
};
|
||||||
overrides = {
|
overrides = {
|
||||||
volumes = [
|
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;
|
port = 3003;
|
||||||
overrides = {
|
overrides = {
|
||||||
volumes = [
|
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 vchord CASCADE;"
|
||||||
$PSQL -d "immich_db" -tAc "CREATE EXTENSION IF NOT EXISTS earthdistance 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}"
|
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
|
until [[ "$(${pkgs.curl}/bin/curl -s -o /dev/null -w "%{http_code}" "$IMMICH_URL")" =~ (200|301|302) ]]; do
|
||||||
sleep 5
|
sleep 5
|
||||||
@@ -94,4 +100,5 @@ in {
|
|||||||
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -5,14 +5,19 @@ let
|
|||||||
|
|
||||||
|
|
||||||
in {
|
in {
|
||||||
sops = true;
|
requires = {
|
||||||
db = true;
|
secrets = [ name ];
|
||||||
|
databases = [ name ];
|
||||||
|
};
|
||||||
|
|
||||||
|
runtime = {
|
||||||
paths = [{
|
paths = [{
|
||||||
path = "${serverCfg.configPath}/influxdb/";
|
path = "${serverCfg.path.config}/influxdb/";
|
||||||
|
owner = "1500:1500";
|
||||||
mode = "0700";
|
mode = "0700";
|
||||||
}{
|
}{
|
||||||
path = "${serverCfg.dataPath}/influxdb/";
|
path = "${serverCfg.path.data}/influxdb/";
|
||||||
|
owner = "1500:1500";
|
||||||
mode = "0700";
|
mode = "0700";
|
||||||
}];
|
}];
|
||||||
|
|
||||||
@@ -28,13 +33,14 @@ in {
|
|||||||
# };
|
# };
|
||||||
# overrides = {
|
# overrides = {
|
||||||
# volumes = [
|
# volumes = [
|
||||||
# "${serverCfg.dataPath}/influxdb:/db:rw"
|
# "${serverCfg.path.data}/influxdb:/db:rw"
|
||||||
# "${serverCfg.configPath}/influxdb:/config:ro"
|
# "${serverCfg.path.config}/influxdb:/config:ro"
|
||||||
# ];
|
# ];
|
||||||
# };
|
# };
|
||||||
# };
|
# };
|
||||||
|
|
||||||
server = builder.mkContainer {
|
server = builder.mkContainer {
|
||||||
|
tmpfs = true;
|
||||||
subdomain = containerCfg.subdomain;
|
subdomain = containerCfg.subdomain;
|
||||||
image = "influxdata/influxdb3-ui:${version}";
|
image = "influxdata/influxdb3-ui:${version}";
|
||||||
port = 8080;
|
port = 8080;
|
||||||
@@ -43,15 +49,12 @@ in {
|
|||||||
SESSION_SECRET_KEY = "7b0024c13ae770000f797c201e2f210b9932a689c04d34de04379faa44e88e97";
|
SESSION_SECRET_KEY = "7b0024c13ae770000f797c201e2f210b9932a689c04d34de04379faa44e88e97";
|
||||||
DATABASE_URL = "/db/sqlite.db";
|
DATABASE_URL = "/db/sqlite.db";
|
||||||
};
|
};
|
||||||
extraOptions = [
|
|
||||||
"--tmpfs=/tmp:rw,noexec,nosuid,size=512m"
|
|
||||||
];
|
|
||||||
overrides = {
|
overrides = {
|
||||||
ports = [ "8080:8080" ];
|
ports = [ "8080:8080" ];
|
||||||
cmd = [ "--mode=admin" ];
|
cmd = [ "--mode=admin" ];
|
||||||
volumes = [
|
volumes = [
|
||||||
"${serverCfg.dataPath}/influxdb:/db:rw"
|
"${serverCfg.path.data}/influxdb:/db:rw"
|
||||||
"${serverCfg.configPath}/influxdb/:/app-root/config:ro"
|
"${serverCfg.path.config}/influxdb/:/app-root/config:ro"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -60,7 +63,7 @@ in {
|
|||||||
setup = {
|
setup = {
|
||||||
trigger = "server";
|
trigger = "server";
|
||||||
script = pkgs.writeShellScript "setup" ''
|
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_SERVER": "http://${builder.host}:8181",
|
||||||
"DEFAULT_INFLUX_DATABASE": "main",
|
"DEFAULT_INFLUX_DATABASE": "main",
|
||||||
@@ -68,8 +71,8 @@ in {
|
|||||||
"DEFAULT_SERVER_NAME": "${serverCfg.domain}"
|
"DEFAULT_SERVER_NAME": "${serverCfg.domain}"
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
chmod -R 755 ${serverCfg.configPath}/influxdb
|
chmod -R 755 ${serverCfg.path.config}/influxdb
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -24,10 +24,14 @@ let
|
|||||||
};
|
};
|
||||||
|
|
||||||
in {
|
in {
|
||||||
sops = true;
|
requires = {
|
||||||
db = true;
|
secrets = [ name ];
|
||||||
|
databases = [ name ];
|
||||||
|
};
|
||||||
|
|
||||||
|
runtime = {
|
||||||
paths = [{
|
paths = [{
|
||||||
path="${serverCfg.configPath}/invidious";
|
path="${serverCfg.path.config}/invidious";
|
||||||
mode = "0755";
|
mode = "0755";
|
||||||
}];
|
}];
|
||||||
|
|
||||||
@@ -49,7 +53,7 @@ in {
|
|||||||
};
|
};
|
||||||
overrides = {
|
overrides = {
|
||||||
volumes = [
|
volumes = [
|
||||||
"${serverCfg.configPath}/invidious:/data:ro"
|
"${serverCfg.path.config}/invidious:/data:ro"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -72,7 +76,8 @@ in {
|
|||||||
export DB_HOST=${builder.host}
|
export DB_HOST=${builder.host}
|
||||||
export INVIDIOUS_DOMAIN=${containerCfg.subdomain}.${serverCfg.domain}
|
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"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -25,14 +25,10 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
|
runtime = {
|
||||||
paths = [
|
paths = [
|
||||||
{
|
{
|
||||||
path = "${serverCfg.dataPath}/media/";
|
path = "${serverCfg.path.config}/jellyfin/";
|
||||||
owner = "1000:1000";
|
|
||||||
mode = "0755";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
path = "${serverCfg.configPath}/jellyfin/";
|
|
||||||
owner = "1000:1000";
|
owner = "1000:1000";
|
||||||
mode = "0755";
|
mode = "0755";
|
||||||
}
|
}
|
||||||
@@ -40,6 +36,7 @@ in {
|
|||||||
|
|
||||||
containers = {
|
containers = {
|
||||||
server = builder.mkContainer {
|
server = builder.mkContainer {
|
||||||
|
tmpfs = true;
|
||||||
subdomain = containerCfg.subdomain;
|
subdomain = containerCfg.subdomain;
|
||||||
imageStream = image;
|
imageStream = image;
|
||||||
port = 8096;
|
port = 8096;
|
||||||
@@ -49,9 +46,6 @@ in {
|
|||||||
JELLYFIN_HttpListenerHost__BindAddress= "0.0.0.0"; #we can use settings.xml override
|
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";
|
JELLYFIN_ServerName = if containerCfg.extra?name then containerCfg.extra.name else "Flix";
|
||||||
};
|
};
|
||||||
extraOptions = [
|
|
||||||
"--tmpfs=/tmp:rw,noexec,nosuid,size=512m"
|
|
||||||
];
|
|
||||||
overrides = {
|
overrides = {
|
||||||
cmd = [
|
cmd = [
|
||||||
"--datadir" "/config/data"
|
"--datadir" "/config/data"
|
||||||
@@ -60,8 +54,8 @@ in {
|
|||||||
"--logdir" "/config/log"
|
"--logdir" "/config/log"
|
||||||
];
|
];
|
||||||
volumes = [
|
volumes = [
|
||||||
"${serverCfg.dataPath}/media:/media:ro"
|
"${serverCfg.path.film}:/media:ro"
|
||||||
"${serverCfg.configPath}/jellyfin:/config"
|
"${serverCfg.path.config}/jellyfin:/config"
|
||||||
];
|
];
|
||||||
# If you have an Intel/AMD GPU for transcoding, add the device:
|
# If you have an Intel/AMD GPU for transcoding, add the device:
|
||||||
devices = lib.optionals (builtins.pathExists "/dev/dri") [ "/dev/dri:/dev/dri" ];
|
devices = lib.optionals (builtins.pathExists "/dev/dri") [ "/dev/dri:/dev/dri" ];
|
||||||
@@ -169,7 +163,7 @@ in {
|
|||||||
fi
|
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)
|
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'));
|
VALUES ( 1, "$HOMEPAGE_VAR_JELLYFIN_API", 'Home', strftime('%Y-%m-%d %H:%M:%S', 'now'), strftime('%Y-%m-%d %H:%M:%S', 'now'));
|
||||||
EOF
|
EOF
|
||||||
@@ -177,5 +171,5 @@ EOF
|
|||||||
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -3,21 +3,21 @@ let
|
|||||||
version = "31";
|
version = "31";
|
||||||
serverCfg = config.syscfg.server;
|
serverCfg = config.syscfg.server;
|
||||||
in {
|
in {
|
||||||
sops = true;
|
requires = {
|
||||||
db = true;
|
secrets = [ name ];
|
||||||
|
databases = [ name ];
|
||||||
|
};
|
||||||
|
|
||||||
|
runtime = {
|
||||||
paths = [{
|
paths = [{
|
||||||
path="${serverCfg.dataPath}/nextcloud/www";
|
path="${serverCfg.path.config}/nextcloud";
|
||||||
owner = "33:33";
|
owner = "33:33";
|
||||||
mode = "0755";
|
mode = "0755";
|
||||||
}{
|
|
||||||
path="${serverCfg.dataPath}/nextcloud/data";
|
|
||||||
owner = "33:33";
|
|
||||||
mode = "0755";
|
|
||||||
backup = true;
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
containers = {
|
containers = {
|
||||||
server = builder.mkContainer {
|
server = builder.mkContainer {
|
||||||
|
tmpfs = true;
|
||||||
subdomain = containerCfg.subdomain;
|
subdomain = containerCfg.subdomain;
|
||||||
image = "nextcloud:${version}";
|
image = "nextcloud:${version}";
|
||||||
port = 80;
|
port = 80;
|
||||||
@@ -28,13 +28,14 @@ in {
|
|||||||
POSTGRES_USER = "nextcloud_user";
|
POSTGRES_USER = "nextcloud_user";
|
||||||
POSTGRES_DB = "nextcloud_db";
|
POSTGRES_DB = "nextcloud_db";
|
||||||
AUTHENTIK_POSTGRESQL__SSLMODE = "disable";
|
AUTHENTIK_POSTGRESQL__SSLMODE = "disable";
|
||||||
"NEXTCLOUD_TRUSTED_DOMAINS " = "${containerCfg.subdomain}.${serverCfg.domain} nextcloud-server";
|
NEXTCLOUD_TRUSTED_DOMAINS = "${containerCfg.subdomain}.${serverCfg.domain} nextcloud-server";
|
||||||
"SMTP_HOST" = serverCfg.mailServer;
|
SMTP_HOST = serverCfg.mail.server;
|
||||||
"SMTP_NAME" = "mail_user";
|
SMTP_NAME = "mail_user";
|
||||||
"SMTP_PASSWORD" = "mail_password";
|
SMTP_PASSWORD = "mail_password";
|
||||||
"MAIL_FROM_ADDRESS" = "${containerCfg.subdomain}@${serverCfg.domain}";
|
MAIL_FROM_ADDRESS = "${containerCfg.subdomain}@${serverCfg.domain}";
|
||||||
"MAIL_DOMAIN" = serverCfg.mailDomain;
|
MAIL_DOMAIN = serverCfg.mail.domain;
|
||||||
"TRUSTED_PROXIES" = "10.10.0.0/16 192.168.0.0/16";
|
TRUSTED_PROXIES = "10.10.0.0/16 192.168.0.0/16";
|
||||||
|
NEXTCLOUD_DATA_DIR = "/var/www/html/data";
|
||||||
};
|
};
|
||||||
extraLabels = {
|
extraLabels = {
|
||||||
"traefik.http.routers.${containerCfg.subdomain}.middlewares" = "sts_headers,${containerCfg.subdomain}-caldav";
|
"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.stsSeconds" = "15552000";
|
||||||
"traefik.http.middlewares.sts_headers.headers.stsIncludeSubdomains" = "true";
|
"traefik.http.middlewares.sts_headers.headers.stsIncludeSubdomains" = "true";
|
||||||
};
|
};
|
||||||
extraOptions = [
|
|
||||||
"--tmpfs=/tmp:rw,noexec,nosuid,size=512m"
|
|
||||||
];
|
|
||||||
overrides = {
|
overrides = {
|
||||||
ports = if containerCfg.port!=null then [ "${toString containerCfg.port}:80" ] else [];
|
ports = if containerCfg.port!=null then [ "${toString containerCfg.port}:80" ] else [];
|
||||||
volumes = [
|
volumes = [
|
||||||
"${serverCfg.dataPath}/nextcloud/www:/var/www/html"
|
"${serverCfg.path.config}/nextcloud:/var/www/html"
|
||||||
"${serverCfg.dataPath}/nextcloud/data:/var/www/html/data"
|
"${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" ];
|
cron = [ "*/5 * * * * root ${pkgs.podman}/bin/podman --events-backend=none exec -u www-data nextcloud-server php -f /var/www/html/cron.php" ];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,11 @@ let
|
|||||||
version = "5.1.4";
|
version = "5.1.4";
|
||||||
|
|
||||||
in {
|
in {
|
||||||
sops = false;
|
runtime = {
|
||||||
db = false;
|
|
||||||
paths = [
|
paths = [
|
||||||
{ path="${serverCfg.configPath}/openhab/conf"; owner="1000:1000"; mode = "0755"; }
|
{ path="${serverCfg.path.config}/openhab/conf"; owner="1000:1000"; mode = "0755"; }
|
||||||
{ path="${serverCfg.configPath}/openhab/userdata"; owner="1000:1000"; mode = "0755"; }
|
{ path="${serverCfg.path.config}/openhab/userdata"; owner="1000:1000"; mode = "0755"; }
|
||||||
{ path="${serverCfg.configPath}/openhab/addons"; owner="1000:1000"; mode = "0755"; }
|
{ path="${serverCfg.path.config}/openhab/addons"; owner="1000:1000"; mode = "0755"; }
|
||||||
];
|
];
|
||||||
|
|
||||||
containers = {
|
containers = {
|
||||||
@@ -31,9 +30,9 @@ in {
|
|||||||
];
|
];
|
||||||
overrides = {
|
overrides = {
|
||||||
volumes = [
|
volumes = [
|
||||||
"${serverCfg.configPath}/openhab/conf:/openhab/conf"
|
"${serverCfg.path.config}/openhab/conf:/openhab/conf"
|
||||||
"${serverCfg.configPath}/openhab/userdata:/openhab/userdata"
|
"${serverCfg.path.config}/openhab/userdata:/openhab/userdata"
|
||||||
"${serverCfg.configPath}/openhab/addons:/opt/openhab/addons"
|
"${serverCfg.path.config}/openhab/addons:/opt/openhab/addons"
|
||||||
"/var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket:ro"
|
"/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)
|
#Extra: AndroidTV/Jellyfin (Bind with lights + more)
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -59,12 +59,9 @@ let
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
in {
|
in {
|
||||||
sops = true;
|
requires.secrets = [ name ];
|
||||||
# paths = [{
|
|
||||||
# path="${serverCfg.dataPath}/searxng/";
|
|
||||||
# mode = "0444";
|
|
||||||
# }];
|
|
||||||
|
|
||||||
|
runtime = {
|
||||||
containers = {
|
containers = {
|
||||||
server = builder.mkContainer {
|
server = builder.mkContainer {
|
||||||
subdomain = containerCfg.subdomain;
|
subdomain = containerCfg.subdomain;
|
||||||
@@ -80,13 +77,11 @@ in {
|
|||||||
#SEARXNG_VALKEY_URL = "valkey://user:password@${builder.host}:6379/0}";
|
#SEARXNG_VALKEY_URL = "valkey://user:password@${builder.host}:6379/0}";
|
||||||
};
|
};
|
||||||
overrides = {
|
overrides = {
|
||||||
cmd = [ ];
|
|
||||||
volumes = [
|
volumes = [
|
||||||
"${settings}:/etc/searxng/settings.yml"
|
"${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/"
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -2,20 +2,16 @@
|
|||||||
let
|
let
|
||||||
version = "latest";
|
version = "latest";
|
||||||
serverCfg = config.syscfg.server;
|
serverCfg = config.syscfg.server;
|
||||||
|
|
||||||
routerName = if containerCfg.subpath != null
|
|
||||||
then "${containerCfg.subdomain}-${lib.strings.sanitizeDerivationName containerCfg.subpath}"
|
|
||||||
else containerCfg.subdomain;
|
|
||||||
in {
|
in {
|
||||||
sops = false;
|
runtime = {
|
||||||
db = false;
|
|
||||||
paths = [{
|
paths = [{
|
||||||
path = "${serverCfg.configPath}/selfmark/";
|
path = "${serverCfg.path.config}/selfmark/";
|
||||||
mode = "0444";
|
mode = "0444";
|
||||||
}];
|
}];
|
||||||
|
|
||||||
containers = {
|
containers = {
|
||||||
server = builder.mkContainer {
|
server = builder.mkContainer {
|
||||||
|
authentik = true;
|
||||||
subdomain = containerCfg.subdomain;
|
subdomain = containerCfg.subdomain;
|
||||||
subpath = containerCfg.subpath;
|
subpath = containerCfg.subpath;
|
||||||
image = "ghcr.io/calibrain/shelfmark:${version}";
|
image = "ghcr.io/calibrain/shelfmark:${version}";
|
||||||
@@ -81,15 +77,14 @@ in {
|
|||||||
EXT_BYPASSER_PATH = "/v1";
|
EXT_BYPASSER_PATH = "/v1";
|
||||||
EXT_BYPASSER_TIMEOUT = "60000";
|
EXT_BYPASSER_TIMEOUT = "60000";
|
||||||
};
|
};
|
||||||
|
|
||||||
extraLabels = {
|
|
||||||
} // (if serverCfg.containers ? authentik then {
|
|
||||||
"traefik.http.routers.${routerName}.middlewares" = "authentik";
|
|
||||||
} else {});
|
|
||||||
overrides = {
|
overrides = {
|
||||||
volumes = [ ];
|
volumes = [
|
||||||
|
"${serverCfg.path.dlComplete}:/books:rw"
|
||||||
|
"${serverCfg.path.books}:/output:rw"
|
||||||
|
"${serverCfg.path.config}/selfmark:/config:rw"
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,9 +30,10 @@ let
|
|||||||
in
|
in
|
||||||
assert containerCfg.subpath == null || throw "Error: Servarr does not support subpath.";
|
assert containerCfg.subpath == null || throw "Error: Servarr does not support subpath.";
|
||||||
{
|
{
|
||||||
sops = true;
|
requires.secrets = [ name ];
|
||||||
# db = [ "prowlarr" "sonarr" "radarr" ]; -> one db for each
|
# db = [ "prowlarr" "sonarr" "radarr" ]; -> one db for each
|
||||||
|
|
||||||
|
runtime = {
|
||||||
paths = [
|
paths = [
|
||||||
{ path = "${serverCfg.dataPath}/media/"; mode = "0755"; }
|
{ path = "${serverCfg.dataPath}/media/"; mode = "0755"; }
|
||||||
{ path = "${serverCfg.configPath}/servarr/prowlarr"; mode = "0755"; }
|
{ path = "${serverCfg.configPath}/servarr/prowlarr"; mode = "0755"; }
|
||||||
@@ -44,6 +45,8 @@ in
|
|||||||
containers = {
|
containers = {
|
||||||
}// lib.optionalAttrs (builtins.elem "prowlarr" (containerCfg.extra.modules or defaultModules)) {
|
}// lib.optionalAttrs (builtins.elem "prowlarr" (containerCfg.extra.modules or defaultModules)) {
|
||||||
prowlarr = builder.mkContainer {
|
prowlarr = builder.mkContainer {
|
||||||
|
authentik = true;
|
||||||
|
tmpfs = true;
|
||||||
subdomain = containerCfg.subdomain;
|
subdomain = containerCfg.subdomain;
|
||||||
subpath = "prowlarr";
|
subpath = "prowlarr";
|
||||||
imageStream = images.prowlarr;
|
imageStream = images.prowlarr;
|
||||||
@@ -58,17 +61,15 @@ in
|
|||||||
};
|
};
|
||||||
extraOptions = [
|
extraOptions = [
|
||||||
"--user=0:0"
|
"--user=0:0"
|
||||||
"--tmpfs=/tmp:rw,noexec,nosuid,size=512m"
|
|
||||||
"--passwd-entry=root:x:0:0:root:/root:/bin/sh"
|
"--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" ];
|
overrides.volumes = sharedVolumes ++ [ "${serverCfg.configPath}/servarr/prowlarr:/config" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
}// lib.optionalAttrs (builtins.elem "radarr" (containerCfg.extra.modules or defaultModules)) {
|
}// lib.optionalAttrs (builtins.elem "radarr" (containerCfg.extra.modules or defaultModules)) {
|
||||||
radarr = builder.mkContainer {
|
radarr = builder.mkContainer {
|
||||||
|
authentik = true;
|
||||||
|
tmpfs = true;
|
||||||
subdomain = containerCfg.subdomain;
|
subdomain = containerCfg.subdomain;
|
||||||
subpath = "radarr";
|
subpath = "radarr";
|
||||||
imageStream = images.radarr;
|
imageStream = images.radarr;
|
||||||
@@ -83,17 +84,15 @@ in
|
|||||||
};
|
};
|
||||||
extraOptions = [
|
extraOptions = [
|
||||||
"--user=0:0"
|
"--user=0:0"
|
||||||
"--tmpfs=/tmp:rw,noexec,nosuid,size=512m"
|
|
||||||
"--passwd-entry=root:x:0:0:root:/root:/bin/sh"
|
"--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" ];
|
overrides.volumes = sharedVolumes ++ [ "${serverCfg.configPath}/servarr/radarr:/config" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
}// lib.optionalAttrs (builtins.elem "sonarr" (containerCfg.extra.modules or defaultModules)) {
|
}// lib.optionalAttrs (builtins.elem "sonarr" (containerCfg.extra.modules or defaultModules)) {
|
||||||
sonarr = builder.mkContainer {
|
sonarr = builder.mkContainer {
|
||||||
|
authentik = true;
|
||||||
|
tmpfs = true;
|
||||||
subdomain = containerCfg.subdomain;
|
subdomain = containerCfg.subdomain;
|
||||||
subpath = "sonarr";
|
subpath = "sonarr";
|
||||||
imageStream = images.sonarr;
|
imageStream = images.sonarr;
|
||||||
@@ -108,17 +107,15 @@ in
|
|||||||
};
|
};
|
||||||
extraOptions = [
|
extraOptions = [
|
||||||
"--user=0:0"
|
"--user=0:0"
|
||||||
"--tmpfs=/tmp:rw,noexec,nosuid,size=512m"
|
|
||||||
"--passwd-entry=root:x:0:0:root:/root:/bin/sh"
|
"--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" ];
|
overrides.volumes = sharedVolumes ++ [ "${serverCfg.configPath}/servarr/sonarr:/config" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
}// lib.optionalAttrs (builtins.elem "lidarr" (containerCfg.extra.modules or defaultModules)) {
|
}// lib.optionalAttrs (builtins.elem "lidarr" (containerCfg.extra.modules or defaultModules)) {
|
||||||
lidarr = builder.mkContainer {
|
lidarr = builder.mkContainer {
|
||||||
|
authentik = true;
|
||||||
|
tmpfs = true;
|
||||||
subdomain = containerCfg.subdomain;
|
subdomain = containerCfg.subdomain;
|
||||||
subpath = "lidarr";
|
subpath = "lidarr";
|
||||||
imageStream = images.lidarr;
|
imageStream = images.lidarr;
|
||||||
@@ -133,12 +130,8 @@ in
|
|||||||
};
|
};
|
||||||
extraOptions = [
|
extraOptions = [
|
||||||
"--user=0:0"
|
"--user=0:0"
|
||||||
"--tmpfs=/tmp:rw,noexec,nosuid,size=512m"
|
|
||||||
"--passwd-entry=root:x:0:0:root:/root:/bin/sh"
|
"--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" ];
|
overrides.volumes = sharedVolumes ++ [ "${serverCfg.configPath}/servarr/lidarr:/config" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -526,4 +519,5 @@ in
|
|||||||
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,13 @@ let
|
|||||||
version = "stable";
|
version = "stable";
|
||||||
serverCfg = config.syscfg.server;
|
serverCfg = config.syscfg.server;
|
||||||
in {
|
in {
|
||||||
sops = true;
|
requires = {
|
||||||
db =true;
|
secrets = [ name ];
|
||||||
containers = {
|
databases = [ name ];
|
||||||
|
};
|
||||||
|
|
||||||
|
runtime = {
|
||||||
|
containers = {
|
||||||
server = builder.mkContainer {
|
server = builder.mkContainer {
|
||||||
subdomain = containerCfg.subdomain;
|
subdomain = containerCfg.subdomain;
|
||||||
image = "ghcr.io/suwayomi/suwayomi-server:${version}";
|
image = "ghcr.io/suwayomi/suwayomi-server:${version}";
|
||||||
@@ -40,9 +43,11 @@ in {
|
|||||||
|
|
||||||
overrides = {
|
overrides = {
|
||||||
volumes = [
|
volumes = [
|
||||||
|
"${serverCfg.path.manga}:/home/suwayomi/.local/share/Tachidesk/downloads"
|
||||||
|
# "${serverCfg.path.config}/suwayomi:/home/suwayomi/.local/share/Tachidesk"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -11,9 +11,11 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
sops = true;
|
requires.secrets = [ name ];
|
||||||
|
|
||||||
|
runtime = {
|
||||||
paths = [{
|
paths = [{
|
||||||
path="${serverCfg.configPath}/traefik";
|
path="${serverCfg.path.config}/traefik";
|
||||||
owner = "1000:1000";
|
owner = "1000:1000";
|
||||||
mode = "0755";
|
mode = "0755";
|
||||||
}];
|
}];
|
||||||
@@ -77,11 +79,11 @@ in {
|
|||||||
ports = [ "443:443" "80:80" ] ++ (if containerCfg.port!=null then [ "${toString containerCfg.port}:8080" ] else []);
|
ports = [ "443:443" "80:80" ] ++ (if containerCfg.port!=null then [ "${toString containerCfg.port}:8080" ] else []);
|
||||||
volumes = [
|
volumes = [
|
||||||
"/var/run/podman/podman.sock:/var/run/docker.sock"
|
"/var/run/podman/podman.sock:/var/run/docker.sock"
|
||||||
# "${serverCfg.configPath}/traefik/access.log:/etc/traefik/access.log"
|
# "${serverCfg.path.config}/traefik/access.log:/etc/traefik/access.log"
|
||||||
"${serverCfg.configPath}/traefik:/custom"
|
"${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 {
|
in {
|
||||||
|
runtime = {
|
||||||
paths = [{
|
paths = [{
|
||||||
path = "${serverCfg.dataPath}/transmission/complete";
|
path = "${serverCfg.path.config}/transmission";
|
||||||
owner = "1000:1000";
|
|
||||||
mode = "0755";
|
|
||||||
}{
|
|
||||||
path = "${serverCfg.dataPath}/transmission/incomplete";
|
|
||||||
owner = "1000:1000";
|
|
||||||
mode = "0755";
|
|
||||||
}{
|
|
||||||
path = "${serverCfg.configPath}/transmission/config";
|
|
||||||
owner = "1000:1000";
|
owner = "1000:1000";
|
||||||
mode = "0755";
|
mode = "0755";
|
||||||
}];
|
}];
|
||||||
|
|
||||||
containers = {
|
containers = {
|
||||||
server = builder.mkContainer {
|
server = builder.mkContainer {
|
||||||
|
authentik = true;
|
||||||
subdomain = containerCfg.subdomain;
|
subdomain = containerCfg.subdomain;
|
||||||
subpath = containerCfg.subpath;
|
subpath = containerCfg.subpath;
|
||||||
imageStream = image;
|
imageStream = image;
|
||||||
@@ -44,17 +35,12 @@ in {
|
|||||||
WHITELIST = "";# 127.0.0.1,::1,10.*";
|
WHITELIST = "";# 127.0.0.1,::1,10.*";
|
||||||
# HOST_WHITELIST = "traefik-server,authentik-server,authentik-worker";
|
# HOST_WHITELIST = "traefik-server,authentik-server,authentik-worker";
|
||||||
};
|
};
|
||||||
extraLabels = {
|
|
||||||
} // (if serverCfg.containers ? authentik then {
|
|
||||||
"traefik.http.routers.${routerName}.middlewares" = "authentik";
|
|
||||||
} else {});
|
|
||||||
|
|
||||||
overrides = {
|
overrides = {
|
||||||
cmd = [ ];
|
|
||||||
volumes = [
|
volumes = [
|
||||||
"${serverCfg.dataPath}/transmission/complete:/downloads/complete"
|
"${serverCfg.path.dlComplete}:/downloads/complete"
|
||||||
"${serverCfg.dataPath}/transmission/incomplete:/downloads/incomplete"
|
"${serverCfg.path.dlIncomplete}:/downloads/incomplete"
|
||||||
"${serverCfg.configPath}/transmission/config:/config"
|
"${serverCfg.path.config}/transmission:/config"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -66,8 +52,8 @@ in {
|
|||||||
envFile = [ config.sops.secrets."CUSTOM".path ];
|
envFile = [ config.sops.secrets."CUSTOM".path ];
|
||||||
script = pkgs.writeShellScript "setup" ''
|
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"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -15,15 +15,21 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
sops = true;
|
requires = {
|
||||||
db = true;
|
secrets = [ name ];
|
||||||
|
databases = [ name ];
|
||||||
|
};
|
||||||
|
|
||||||
|
runtime = {
|
||||||
paths = [{
|
paths = [{
|
||||||
path = "${serverCfg.configPath}/umami/";
|
path = "${serverCfg.path.config}/umami/";
|
||||||
mode = "0444";
|
mode = "0444";
|
||||||
}];
|
}];
|
||||||
|
|
||||||
containers = {
|
containers = {
|
||||||
server = builder.mkContainer {
|
server = builder.mkContainer {
|
||||||
|
authentik = true;
|
||||||
|
tmpfs = true;
|
||||||
subdomain = containerCfg.subdomain;
|
subdomain = containerCfg.subdomain;
|
||||||
image = "${pkgs.umami.name}:${pkgs.umami.version}";
|
image = "${pkgs.umami.name}:${pkgs.umami.version}";
|
||||||
imageStream = image;
|
imageStream = image;
|
||||||
@@ -39,16 +45,10 @@ in {
|
|||||||
# DISABLE_LOGIN = "1";#(if serverCfg.containers?authentik then "1" else "0");
|
# 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 = {
|
overrides = {
|
||||||
cmd = [ "start" ]; # Specific command for the umami binary
|
cmd = [ "start" ]; # Specific command for the umami binary
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,32 @@
|
|||||||
{ config, lib, pkgs, serverCfg }:
|
{ config, lib, pkgs, serverCfg }:
|
||||||
let
|
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 =
|
contBuilder =
|
||||||
{ image ? null, imageStream ? null, imageFile ? null
|
{ image ? null, imageStream ? null, imageFile ? null
|
||||||
, secret ? null
|
, secret ? null
|
||||||
, subdomain ? null, subpath?null, port ? null
|
, subdomain ? null, subpath?null, port ? null
|
||||||
|
, authentik ? false
|
||||||
|
, tmpfs ? false
|
||||||
|
, tmpfsSize ? "512m"
|
||||||
, extraEnv ? { }, extraLabels ? { }, extraOptions ? [ ]
|
, extraEnv ? { }, extraLabels ? { }, extraOptions ? [ ]
|
||||||
, overrides ? { }
|
, overrides ? { }
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
routerName = if subpath != null
|
routerName = mkRouterName { inherit subdomain subpath; };
|
||||||
then "${subdomain}-${lib.strings.sanitizeDerivationName subpath}"
|
|
||||||
else subdomain;
|
|
||||||
base = {
|
base = {
|
||||||
image = if imageStream != null then "${imageStream.imageName}:${imageStream.imageTag}"
|
image = if imageStream != null then "${imageStream.imageName}:${imageStream.imageTag}"
|
||||||
else if imageFile != null then "${imageFile.imageName}:${imageFile.imageTag}" else image;
|
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;
|
"traefik.http.services.${routerName}.loadbalancer.server.port" = toString port;
|
||||||
}) else {
|
}) else {
|
||||||
"traefik.enable" = "false";
|
"traefik.enable" = "false";
|
||||||
}) // extraLabels;
|
})
|
||||||
|
// lib.optionalAttrs authentik (mkAuthentikLabels { inherit subdomain subpath routerName; })
|
||||||
|
// extraLabels;
|
||||||
|
|
||||||
extraOptions = [
|
extraOptions = [
|
||||||
"--add-host=host.containers.internal:host-gateway"
|
"--add-host=host.containers.internal:host-gateway"
|
||||||
] ++ extraOptions;
|
]
|
||||||
|
++ lib.optional tmpfs (mkTmpfsOption tmpfsSize)
|
||||||
|
++ extraOptions;
|
||||||
};
|
};
|
||||||
in lib.recursiveUpdate base overrides;
|
in lib.recursiveUpdate base overrides;
|
||||||
vmBuilder = { name, vm }: ((import "${pkgs.path}/nixos/lib/eval-config.nix" {
|
vmBuilder = { name, vm }: ((import "${pkgs.path}/nixos/lib/eval-config.nix" {
|
||||||
@@ -69,6 +89,30 @@ let
|
|||||||
in {
|
in {
|
||||||
mkContainer = contBuilder;
|
mkContainer = contBuilder;
|
||||||
mkVm = vmBuilder;
|
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 ''
|
mkData = { name, dir, vars?{} }: pkgs.runCommand name vars ''
|
||||||
mkdir -p $out
|
mkdir -p $out
|
||||||
cp -r ${./data + "/${dir}"}/. $out/
|
cp -r ${./data + "/${dir}"}/. $out/
|
||||||
|
|||||||
@@ -2,30 +2,25 @@
|
|||||||
let
|
let
|
||||||
serverCfg = config.syscfg.server;
|
serverCfg = config.syscfg.server;
|
||||||
builder = import ./builder.nix { inherit config lib pkgs serverCfg; };
|
builder = import ./builder.nix { inherit config lib pkgs serverCfg; };
|
||||||
|
loadApp = name: containerCfg:
|
||||||
in{
|
builder.mkApp name ((import (./apps + "/${name}.nix")) {
|
||||||
config = lib.mkMerge [{
|
inherit config pkgs lib containerCfg builder name;
|
||||||
syscfg.server.loadedContainers = lib.mapAttrs (name: containerCfg:
|
});
|
||||||
(import (./apps + "/${name}.nix")) { inherit config pkgs lib containerCfg builder name; }
|
loadedContainers = lib.mapAttrs loadApp serverCfg.containers;
|
||||||
) config.syscfg.server.containers;
|
appsList = builtins.attrValues loadedContainers;
|
||||||
} (lib.mkIf ( serverCfg.containers != {} ) (
|
concatRuntimeLists = field: lib.concatMap (app: app.runtime.${field}) appsList;
|
||||||
let
|
mkNamedUnits = mkUnit: items: lib.listToAttrs (map mkUnit items);
|
||||||
appsList = builtins.attrValues config.syscfg.server.loadedContainers;
|
|
||||||
mergedContainers = lib.concatMapAttrs (appName: app:
|
mergedContainers = lib.concatMapAttrs (appName: app:
|
||||||
lib.mapAttrs' (cName: cCfg: lib.nameValuePair "${appName}-${cName}" cCfg) app.containers
|
lib.mapAttrs' (cName: cCfg: lib.nameValuePair "${appName}-${cName}" cCfg) app.runtime.containers
|
||||||
) config.syscfg.server.loadedContainers;
|
) loadedContainers;
|
||||||
allPathConfigs = lib.concatMap (app: app.paths) appsList;
|
allPathConfigs = map (path: {
|
||||||
allSetupConfigs = lib.concatMap (app: if app.setup?script then [({name = app.name; envFile="";} // app.setup)] else []) appsList;
|
inherit path;
|
||||||
allCronsConfigs = lib.concatMap (app: app.cron) appsList;
|
mode = "0755";
|
||||||
allVMConfigs = builtins.filter (app: app.vm != null) appsList;
|
}) (lib.unique (builtins.attrValues serverCfg.path)) ++ concatRuntimeLists "paths";
|
||||||
in{
|
allSetupConfigs = map (app: ({ name = app.name; envFile = ""; } // app.runtime.setup)) appsList;
|
||||||
virtualisation.oci-containers = {
|
allCronsConfigs = concatRuntimeLists "cron";
|
||||||
backend = "podman";
|
allVMConfigs = builtins.filter (app: app.runtime.vm != null) appsList;
|
||||||
containers = mergedContainers;
|
mkPathSetup = cfg:
|
||||||
};
|
|
||||||
system.activationScripts.container-setup-dirs = {
|
|
||||||
deps = [ "users" "groups" ];
|
|
||||||
text = lib.concatStringsSep "\n" (map (cfg:
|
|
||||||
let
|
let
|
||||||
effectiveCfg = {
|
effectiveCfg = {
|
||||||
owner = "root:root";
|
owner = "root:root";
|
||||||
@@ -37,8 +32,18 @@ in{
|
|||||||
${lib.concatMapStringsSep "\n" (dir: "${pkgs.coreutils}/bin/mkdir -p ${effectiveCfg.path}/${lib.escapeShellArg dir}") effectiveCfg.dirs}
|
${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/chown ${effectiveCfg.owner} "${effectiveCfg.path}"
|
||||||
${pkgs.coreutils}/bin/chmod ${effectiveCfg.mode} "${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 = {
|
systemd.services = {
|
||||||
@@ -52,7 +57,7 @@ in{
|
|||||||
startAt = "weekly";
|
startAt = "weekly";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// lib.listToAttrs (lib.concatMap (e: [{
|
// mkNamedUnits (e: {
|
||||||
name = "${e.name}-vm";
|
name = "${e.name}-vm";
|
||||||
value = {
|
value = {
|
||||||
description = "Isolated NixOS Guest VM for ${e.name}";
|
description = "Isolated NixOS Guest VM for ${e.name}";
|
||||||
@@ -69,12 +74,12 @@ in{
|
|||||||
RestartSec = "10s";
|
RestartSec = "10s";
|
||||||
ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p /media/data/kvm";
|
ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p /media/data/kvm";
|
||||||
ExecStart = ''
|
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)
|
}) allVMConfigs
|
||||||
// lib.listToAttrs (lib.concatMap (e: [{
|
// mkNamedUnits (e: {
|
||||||
name = "${e.name}-setup";
|
name = "${e.name}-setup";
|
||||||
value = {
|
value = {
|
||||||
description = "Run ${e.name} setup";
|
description = "Run ${e.name} setup";
|
||||||
@@ -90,13 +95,11 @@ in{
|
|||||||
User = "root";
|
User = "root";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}]) allSetupConfigs );
|
}) allSetupConfigs;
|
||||||
|
|
||||||
services.cron = {
|
services.cron = {
|
||||||
enable = true;
|
enable = true;
|
||||||
systemCronJobs = allCronsConfigs;
|
systemCronJobs = allCronsConfigs;
|
||||||
};
|
};
|
||||||
|
})];
|
||||||
}))];
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
let
|
let
|
||||||
|
|
||||||
listNames = config.syscfg.server.db;
|
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);
|
allApps = lib.unique (listNames ++ containerNames);
|
||||||
in {
|
in {
|
||||||
config = lib.mkIf ( builtins.length allApps > 0) {
|
config = lib.mkIf ( builtins.length allApps > 0) {
|
||||||
@@ -47,9 +47,10 @@ in {
|
|||||||
environment = {
|
environment = {
|
||||||
INFLUXDB3_NODE_IDENTIFIER_PREFIX = "node0";
|
INFLUXDB3_NODE_IDENTIFIER_PREFIX = "node0";
|
||||||
INFLUXDB3_OBJECT_STORE = "file";
|
INFLUXDB3_OBJECT_STORE = "file";
|
||||||
INFLUXDB3_DATA_DIR = "${config.syscfg.server.dataPath}/influxdb";
|
INFLUXDB3_DATA_DIR = "${config.syscfg.server.path.data}/influxdb";
|
||||||
INFLUXDB3_DB_DIR = "${config.syscfg.server.dataPath}/influxdb";
|
INFLUXDB3_DB_DIR = "${config.syscfg.server.path.data}/influxdb";
|
||||||
INFLUXDB3_ENABLE_INTERNAL_DB = "true";
|
INFLUXDB3_ENABLE_INTERNAL_DB = "true";
|
||||||
|
INFLUXDB3_AUTH_TOKEN = "b27686e85a883437666f61586e084f7deb763958497739479ca48bc913ee90afd1a920332156133c89fb8674cb197ced17706074e6a42fc7ce6b2d54ac6119c9";
|
||||||
INFLUXDB3_INITIAL_ADMIN_TOKEN = "b27686e85a883437666f61586e084f7deb763958497739479ca48bc913ee90afd1a920332156133c89fb8674cb197ced17706074e6a42fc7ce6b2d54ac6119c9";
|
INFLUXDB3_INITIAL_ADMIN_TOKEN = "b27686e85a883437666f61586e084f7deb763958497739479ca48bc913ee90afd1a920332156133c89fb8674cb197ced17706074e6a42fc7ce6b2d54ac6119c9";
|
||||||
};
|
};
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
let
|
let
|
||||||
listNames = config.syscfg.server.db;
|
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);
|
allApps = lib.unique (listNames ++ containerNames);
|
||||||
in{
|
in{
|
||||||
sops.secrets = {
|
sops.secrets = {
|
||||||
|
|||||||
@@ -3,16 +3,32 @@ let
|
|||||||
|
|
||||||
in with lib; {
|
in with lib; {
|
||||||
domain = mkOption { type = types.str; };
|
domain = mkOption { type = types.str; };
|
||||||
mailDomain = mkOption { type = types.str; };
|
mail = {
|
||||||
mailServer = mkOption { type = types.str; };
|
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;
|
path = mkOption {
|
||||||
default = "/media/data";
|
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 {
|
colorScheme = mkOption {
|
||||||
@@ -24,18 +40,44 @@ in with lib; {
|
|||||||
type = lib.types.attrsOf (lib.types.submodule ({ name, ... }: {
|
type = lib.types.attrsOf (lib.types.submodule ({ name, ... }: {
|
||||||
options = {
|
options = {
|
||||||
name = lib.mkOption {type = lib.types.str; default = name;};
|
name = lib.mkOption {type = lib.types.str; default = name;};
|
||||||
sops = lib.mkOption {type = lib.types.bool; default = false;};
|
requires = {
|
||||||
db = lib.mkOption {type = lib.types.bool; default = false;};
|
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 = [ ];};
|
paths = lib.mkOption {type = lib.types.listOf lib.types.attrs; default = [ ];};
|
||||||
containers = lib.mkOption {type = lib.types.attrsOf 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;};
|
vm = lib.mkOption {type = lib.types.nullOr lib.types.attrs; default = null;};
|
||||||
cron = lib.mkOption {type = lib.types.listOf lib.types.str; default = [ ];};
|
cron = lib.mkOption {type = lib.types.listOf lib.types.str; default = [ ];};
|
||||||
|
setup = lib.mkOption {
|
||||||
setup = {
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
trigger = lib.mkOption {type = lib.types.str; default = "";};
|
trigger = lib.mkOption {type = lib.types.str; default = "";};
|
||||||
script = lib.mkOption {type = lib.types.nullOr lib.types.package; default = null;};
|
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 = { };
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -27,8 +27,6 @@
|
|||||||
# user = ...
|
# user = ...
|
||||||
# ...
|
# ...
|
||||||
# };
|
# };
|
||||||
mailDomain = "test@helcel";
|
|
||||||
mailServer = "infomaniak.ch";
|
|
||||||
|
|
||||||
containers = {
|
containers = {
|
||||||
# ===== BASE =====
|
# ===== BASE =====
|
||||||
|
|||||||
Reference in New Issue
Block a user