This commit is contained in:
soraefir
2026-05-14 23:05:27 +02:00
parent dd47977cbd
commit 83dec697d1
13 changed files with 94 additions and 191 deletions

View File

@@ -4,13 +4,13 @@ let
serverCfg = config.syscfg.server; serverCfg = config.syscfg.server;
authentikData = builder.mkData { authentikData = builder.mkData {
name = "authentik"; dir = "authentik"; vars = { name = "authentik"; dir = "authentik"; vars = {
AUTHENTIK_DOMAIN = "${containerCfg.subdomain}.${serverCfg.hostDomain}"; AUTHENTIK_DOMAIN = "${containerCfg.subdomain}.${serverCfg.domain}";
COOKIE_DOMAIN = "${serverCfg.hostDomain}"; COOKIE_DOMAIN = "${serverCfg.domain}";
AUTHENTIK_LDAP_DC_DOMAIN = "dc=ldap," + (lib.concatMapStringsSep "," (x: "dc=${x}") (lib.splitString "." serverCfg.hostDomain)); AUTHENTIK_LDAP_DC_DOMAIN = "dc=ldap," + (lib.concatMapStringsSep "," (x: "dc=${x}") (lib.splitString "." serverCfg.domain));
} }
// (if serverCfg.containers?jellyfin then { JELLYFIN_DOMAIN = "${serverCfg.containers.jellyfin.subdomain}.${serverCfg.hostDomain}";} else {}) // (if serverCfg.containers?jellyfin then { JELLYFIN_DOMAIN = "${serverCfg.containers.jellyfin.subdomain}.${serverCfg.domain}";} else {})
// (if serverCfg.containers?gitea then { GITEA_DOMAIN = "${serverCfg.containers.gitea.subdomain}.${serverCfg.hostDomain}";} else {}) // (if serverCfg.containers?gitea then { GITEA_DOMAIN = "${serverCfg.containers.gitea.subdomain}.${serverCfg.domain}";} else {})
// (if serverCfg.containers?nextcloud then { NEXTCLOUD_DOMAIN = "${serverCfg.containers.nextcloud.subdomain}.${serverCfg.hostDomain}";} else {}); // (if serverCfg.containers?nextcloud then { NEXTCLOUD_DOMAIN = "${serverCfg.containers.nextcloud.subdomain}.${serverCfg.domain}";} else {});
}; };
in { in {
sops = true; sops = true;
@@ -39,11 +39,11 @@ in {
AUTHENTIK_POSAUTHENTIK_POSTGRESQL__SSLMODE = "false"; AUTHENTIK_POSAUTHENTIK_POSTGRESQL__SSLMODE = "false";
AUTHENTIK_EMAIL__HOST = serverCfg.mailDomain; AUTHENTIK_EMAIL__HOST = serverCfg.mailDomain;
AUTHENTIK_EMAIL__PORT = "587"; AUTHENTIK_EMAIL__PORT = "587";
AUTHENTIK_EMAIL__USERNAME = "noreply@${serverCfg.hostDomain}"; AUTHENTIK_EMAIL__USERNAME = "noreply@${serverCfg.domain}";
AUTHENTIK_EMAIL__USE_TLS = "true"; AUTHENTIK_EMAIL__USE_TLS = "true";
AUTHENTIK_EMAIL__USE_SSL = "false"; AUTHENTIK_EMAIL__USE_SSL = "false";
AUTHENTIK_EMAIL__TIMEOUT = "10"; AUTHENTIK_EMAIL__TIMEOUT = "10";
AUTHENTIK_EMAIL__FROM = "sso@noreply.${serverCfg.hostDomain}"; AUTHENTIK_EMAIL__FROM = "sso@noreply.${serverCfg.domain}";
AUTHENTIK_DISABLE_UPDATE_CHECK = "true"; AUTHENTIK_DISABLE_UPDATE_CHECK = "true";
AUTHENTIK_POSTGRESQL__SSLMODE = "disable"; AUTHENTIK_POSTGRESQL__SSLMODE = "disable";
}; };
@@ -83,7 +83,7 @@ in {
image = "ghcr.io/goauthentik/ldap:${version}"; image = "ghcr.io/goauthentik/ldap:${version}";
secret = name; secret = name;
extraEnv = { extraEnv = {
AUTHENTIK_HOST = "https://${containerCfg.subdomain}.${serverCfg.hostDomain}"; AUTHENTIK_HOST = "https://${containerCfg.subdomain}.${serverCfg.domain}";
AUTHENTIK_INSECURE = "false"; AUTHENTIK_INSECURE = "false";
}; };
}; };
@@ -93,7 +93,7 @@ in {
trigger = "worker"; trigger = "worker";
script = pkgs.writeShellScript "setup" '' script = pkgs.writeShellScript "setup" ''
# Define the command wrapper # Define the command wrapper
AK="${pkgs.podman}/bin/podman --events-backend=none exec --env-file ${config.sops.secrets."CUSTOM".path} -e DOMAIN=${serverCfg.hostDomain} -u root authentik-worker ak" AK="${pkgs.podman}/bin/podman --events-backend=none exec --env-file ${config.sops.secrets."CUSTOM".path} -e DOMAIN=${serverCfg.domain} -u root authentik-worker ak"
$AK apply_blueprint /blueprints/custom/authentik.yaml $AK apply_blueprint /blueprints/custom/authentik.yaml
$AK apply_blueprint /blueprints/custom/traefik.yaml $AK apply_blueprint /blueprints/custom/traefik.yaml

View File

@@ -11,10 +11,10 @@ in {
port = 9980; port = 9980;
secret = name; secret = name;
extraEnv = { extraEnv = {
"aliasgroup1" = "https://${serverCfg.containers.nextcloud.subdomain}.${serverCfg.hostDomain}"; "aliasgroup1" = "https://${serverCfg.containers.nextcloud.subdomain}.${serverCfg.domain}";
"server_name" = "${containerCfg.subdomain}.${serverCfg.hostDomain}"; "server_name" = "${containerCfg.subdomain}.${serverCfg.domain}";
"username" = "collabora_user"; "username" = "collabora_user";
"VIRTUAL_HOST" = "${containerCfg.subdomain}.${serverCfg.hostDomain}"; "VIRTUAL_HOST" = "${containerCfg.subdomain}.${serverCfg.domain}";
"VIRTUAL_PORT" = "9980"; "VIRTUAL_PORT" = "9980";
"VIRTUAL_PROTO" = "http"; "VIRTUAL_PROTO" = "http";
"DONT_GEN_SSL_CERT" = "true"; "DONT_GEN_SSL_CERT" = "true";

View File

@@ -3,7 +3,7 @@ let
version = "latest"; version = "latest";
serverCfg = config.syscfg.server; serverCfg = config.syscfg.server;
LDAP_DC_DOMAIN = "dc=ldap," + (lib.concatMapStringsSep "," (x: "dc=${x}") (lib.splitString "." serverCfg.hostDomain)); LDAP_DC_DOMAIN = "dc=ldap," + (lib.concatMapStringsSep "," (x: "dc=${x}") (lib.splitString "." serverCfg.domain));
in { in {
sops = true; sops = true;
db = true; db = true;
@@ -49,8 +49,8 @@ in {
GITEA__mailer__SMTP_PORT = ""; GITEA__mailer__SMTP_PORT = "";
GITEA__mailer__USER= ""; GITEA__mailer__USER= "";
GITEA__server__DOMAIN = "${containerCfg.subdomain}.${serverCfg.hostDomain}"; GITEA__server__DOMAIN = "${containerCfg.subdomain}.${serverCfg.domain}";
GITEA__server__ROOT_URL = "https://${containerCfg.subdomain}.${serverCfg.hostDomain}/"; GITEA__server__ROOT_URL = "https://${containerCfg.subdomain}.${serverCfg.domain}/";
GITEA__server__PROTOCOL = "http"; GITEA__server__PROTOCOL = "http";
GITEA__server__HTTP_PORT = "8080"; GITEA__server__HTTP_PORT = "8080";
GITEA__server__LFS_START_SERVER = "true"; GITEA__server__LFS_START_SERVER = "true";
@@ -64,7 +64,7 @@ in {
GITEA__service__ENABLE_REVERSE_PROXY_EMAIL = "true"; GITEA__service__ENABLE_REVERSE_PROXY_EMAIL = "true";
GITEA__service__ENABLE_REVERSE_PROXY_FULL_NAME = "true"; GITEA__service__ENABLE_REVERSE_PROXY_FULL_NAME = "true";
GITEA__service__ALLOW_ONLY_EXTERNAL_REGISTRATION = "true"; GITEA__service__ALLOW_ONLY_EXTERNAL_REGISTRATION = "true";
GITEA__security__REVERSE_PROXY_LOGOUT_REDIRECT = "https://${serverCfg.containers.authentik.subdomain}.${serverCfg.hostDomain}/outpost.goauthentik.io/sign_out"; GITEA__security__REVERSE_PROXY_LOGOUT_REDIRECT = "https://${serverCfg.containers.authentik.subdomain}.${serverCfg.domain}/outpost.goauthentik.io/sign_out";
GITEA__security__REVERSE_PROXY_AUTHENTICATION_USER = "X-authentik-username"; GITEA__security__REVERSE_PROXY_AUTHENTICATION_USER = "X-authentik-username";
GITEA__security__REVERSE_PROXY_AUTHENTICATION_EMAIL = "X-authentik-email"; GITEA__security__REVERSE_PROXY_AUTHENTICATION_EMAIL = "X-authentik-email";
GITEA__security__REVERSE_PROXY_AUTHENTICATION_FULL_NAME = "X-authentik-name"; GITEA__security__REVERSE_PROXY_AUTHENTICATION_FULL_NAME = "X-authentik-name";
@@ -72,7 +72,7 @@ in {
GITEA__security__REVERSE_PROXY_TRUSTED_PROXIES = "127.0.0.0/8,::1/128,10.0.0.0/8"; GITEA__security__REVERSE_PROXY_TRUSTED_PROXIES = "127.0.0.0/8,::1/128,10.0.0.0/8";
} else {}); } else {});
extraLabels = { extraLabels = {
"traefik.http.routers.${containerCfg.subdomain}-login.rule" = "Host(`${containerCfg.subdomain}.${serverCfg.hostDomain}`) && 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 then "authentik" else ""; "traefik.http.routers.${containerCfg.subdomain}-login.middlewares" = if serverCfg.containers?authentik 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";
@@ -92,8 +92,8 @@ in {
secret = name; secret = name;
extraEnv = { extraEnv = {
CONFIG_FILE="/data/config.yml"; CONFIG_FILE="/data/config.yml";
GITEA_INSTANCE_URL="https://${containerCfg.subdomain}.${serverCfg.hostDomain}"; GITEA_INSTANCE_URL="https://${containerCfg.subdomain}.${serverCfg.domain}";
GITHUB_INSTANCE_URL="https://${containerCfg.subdomain}.${serverCfg.hostDomain}"; GITHUB_INSTANCE_URL="https://${containerCfg.subdomain}.${serverCfg.domain}";
}; };
overrides = { overrides = {
@@ -121,7 +121,7 @@ in {
RUNNER_TOKEN=$($GT actions generate-runner-token) RUNNER_TOKEN=$($GT actions generate-runner-token)
$GTR register \ $GTR register \
--instance "https://${containerCfg.subdomain}.${serverCfg.hostDomain}" \ --instance "https://${containerCfg.subdomain}.${serverCfg.domain}" \
--token "$RUNNER_TOKEN" \ --token "$RUNNER_TOKEN" \
--name "Runner" \ --name "Runner" \
--labels "ubuntu-latest:docker://catthehacker/ubuntu:act-latest" \ --labels "ubuntu-latest:docker://catthehacker/ubuntu:act-latest" \

View File

@@ -31,7 +31,7 @@ in {
INVIDIOUS_VISITOR_DATA = "\${VISITOR_DATA}"; INVIDIOUS_VISITOR_DATA = "\${VISITOR_DATA}";
INVIDIOUS_PORT = "3000"; INVIDIOUS_PORT = "3000";
INVIDIOUS_COMPANION_KEY = "\${INVIDIOUS_KEY}"; INVIDIOUS_COMPANION_KEY = "\${INVIDIOUS_KEY}";
INVIDIOUS_DOMAIN = "${containerCfg.subdomain}.${serverCfg.hostDomain}"; INVIDIOUS_DOMAIN = "${containerCfg.subdomain}.${serverCfg.domain}";
#registration_enabled: false #registration_enabled: false
}; };
}; };

View File

@@ -1,7 +1,7 @@
{ config, containerCfg, pkgs, lib, builder, name, ... }: { config, containerCfg, pkgs, lib, builder, name, ... }:
let let
serverCfg = config.syscfg.server; serverCfg = config.syscfg.server;
LDAP_DC_DOMAIN = "dc=ldap," + (lib.concatMapStringsSep "," (x: "dc=${x}") (lib.splitString "." serverCfg.hostDomain)); LDAP_DC_DOMAIN = "dc=ldap," + (lib.concatMapStringsSep "," (x: "dc=${x}") (lib.splitString "." serverCfg.domain));
nss = pkgs.dockerTools.fakeNss.override { nss = pkgs.dockerTools.fakeNss.override {
extraPasswdLines = [ extraPasswdLines = [
"jellyfin:x:1000:1000:Jellyfin Daemon:/config/data:/bin/false" "jellyfin:x:1000:1000:Jellyfin Daemon:/config/data:/bin/false"
@@ -73,7 +73,7 @@ in {
trigger = "server"; trigger = "server";
envFile = config.sops.secrets."CUSTOM".path; envFile = config.sops.secrets."CUSTOM".path;
script = pkgs.writeShellScript "setup" '' script = pkgs.writeShellScript "setup" ''
JELLYFIN_URL="https://${containerCfg.subdomain}.${serverCfg.hostDomain}" JELLYFIN_URL="https://${containerCfg.subdomain}.${serverCfg.domain}"
until [ "$(${pkgs.curl}/bin/curl -sf "$JELLYFIN_URL/health")" = "Healthy" ]; do until [ "$(${pkgs.curl}/bin/curl -sf "$JELLYFIN_URL/health")" = "Healthy" ]; do
sleep 5 sleep 5
done done

View File

@@ -28,11 +28,11 @@ 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.hostDomain}"; "NEXTCLOUD_TRUSTED_DOMAINS " = "${containerCfg.subdomain}.${serverCfg.domain}";
"SMTP_HOST" = serverCfg.mailServer; "SMTP_HOST" = serverCfg.mailServer;
"SMTP_NAME" = "mail_user"; "SMTP_NAME" = "mail_user";
"SMTP_PASSWORD" = "mail_password"; "SMTP_PASSWORD" = "mail_password";
"MAIL_FROM_ADDRESS" = "${containerCfg.subdomain}@${serverCfg.hostDomain}"; "MAIL_FROM_ADDRESS" = "${containerCfg.subdomain}@${serverCfg.domain}";
"MAIL_DOMAIN" = serverCfg.mailDomain; "MAIL_DOMAIN" = serverCfg.mailDomain;
"TRUSTED_PROXIES" = "10.10.0.0/16 192.168.0.0/16"; "TRUSTED_PROXIES" = "10.10.0.0/16 192.168.0.0/16";
}; };
@@ -61,7 +61,7 @@ in {
trigger = "server"; trigger = "server";
script = pkgs.writeShellScript "setup" '' script = pkgs.writeShellScript "setup" ''
# Define the command wrapper # Define the command wrapper
OCC="${pkgs.podman}/bin/podman --events-backend=none exec --env-file ${config.sops.secrets."CUSTOM".path} -e DOMAIN=${serverCfg.hostDomain} -u www-data nextcloud-server php occ" OCC="${pkgs.podman}/bin/podman --events-backend=none exec --env-file ${config.sops.secrets."CUSTOM".path} -e DOMAIN=${serverCfg.domain} -u www-data nextcloud-server php occ"
echo "Waiting for Nextcloud container to start..." echo "Waiting for Nextcloud container to start..."
until $OCC status > /dev/null 2>&1; do until $OCC status > /dev/null 2>&1; do
@@ -126,23 +126,23 @@ in {
${lib.optionalString (serverCfg.containers ? ethercalc) '' ${lib.optionalString (serverCfg.containers ? ethercalc) ''
$OCC config:app:set ownpad ownpad_ethercalc_enable --value="yes" $OCC config:app:set ownpad ownpad_ethercalc_enable --value="yes"
$OCC config:app:set ownpad ownpad_ethercalc_host --value="https://${serverCfg.containers.ethercalc.subdomain}.${serverCfg.hostDomain}" $OCC config:app:set ownpad ownpad_ethercalc_host --value="https://${serverCfg.containers.ethercalc.subdomain}.${serverCfg.domain}"
''} ''}
${lib.optionalString (serverCfg.containers ? etherpad) '' ${lib.optionalString (serverCfg.containers ? etherpad) ''
$OCC config:app:set ownpad ownpad_etherpad_enable --value="yes" $OCC config:app:set ownpad ownpad_etherpad_enable --value="yes"
$OCC config:app:set ownpad ownpad_etherpad_host --value="https://${serverCfg.containers.etherpad.subdomain}.${serverCfg.hostDomain}" $OCC config:app:set ownpad ownpad_etherpad_host --value="https://${serverCfg.containers.etherpad.subdomain}.${serverCfg.domain}"
''} ''}
${lib.optionalString (serverCfg.containers ? collabora) '' ${lib.optionalString (serverCfg.containers ? collabora) ''
$OCC config:app:set richdocuments wopi_url --value="https://${serverCfg.containers.collabora.subdomain}.${serverCfg.hostDomain}/" $OCC config:app:set richdocuments wopi_url --value="https://${serverCfg.containers.collabora.subdomain}.${serverCfg.domain}/"
$OCC config:app:set richdocuments public_wopi_url --value="https://${serverCfg.containers.collabora.subdomain}.${serverCfg.hostDomain}" $OCC config:app:set richdocuments public_wopi_url --value="https://${serverCfg.containers.collabora.subdomain}.${serverCfg.domain}"
$OCC config:app:set richdocuments wopi_allowlist --value="10.0.0.0/8" $OCC config:app:set richdocuments wopi_allowlist --value="10.0.0.0/8"
''} ''}
${lib.optionalString (serverCfg.containers ? authentik) '' ${lib.optionalString (serverCfg.containers ? authentik) ''
$OCC saml:config:set 1 --general-idp0_display_name="authentik" $OCC saml:config:set 1 --general-idp0_display_name="authentik"
$OCC saml:config:set 1 --general-uid_mapping="http://schemas.goauthentik.io/2021/02/saml/username" $OCC saml:config:set 1 --general-uid_mapping="http://schemas.goauthentik.io/2021/02/saml/username"
$OCC saml:config:set 1 --idp-entityId="https://${serverCfg.containers.authentik.subdomain}.${serverCfg.hostDomain}" $OCC saml:config:set 1 --idp-entityId="https://${serverCfg.containers.authentik.subdomain}.${serverCfg.domain}"
$OCC saml:config:set 1 --idp-singleSignOnService.url="https://${serverCfg.containers.authentik.subdomain}.${serverCfg.hostDomain}/application/saml/nextcloud/sso/binding/redirect/" $OCC saml:config:set 1 --idp-singleSignOnService.url="https://${serverCfg.containers.authentik.subdomain}.${serverCfg.domain}/application/saml/nextcloud/sso/binding/redirect/"
$OCC saml:config:set 1 --idp-singleLogoutService.url="https://${serverCfg.containers.authentik.subdomain}.${serverCfg.hostDomain}/application/saml/nextcloud/slo/binding/redirect/" $OCC saml:config:set 1 --idp-singleLogoutService.url="https://${serverCfg.containers.authentik.subdomain}.${serverCfg.domain}/application/saml/nextcloud/slo/binding/redirect/"
AUTHENTIK_CERT=$(${pkgs.postgresql}/bin/psql -h localhost -U authentik_user -d authentik_db -At -c "SELECT certificate_data FROM authentik_crypto_certificatekeypair WHERE name = 'authentik Self-signed Certificate';") AUTHENTIK_CERT=$(${pkgs.postgresql}/bin/psql -h localhost -U authentik_user -d authentik_db -At -c "SELECT certificate_data FROM authentik_crypto_certificatekeypair WHERE name = 'authentik Self-signed Certificate';")
$OCC saml:config:set 1 --idp-x509cert="$AUTHENTIK_CERT" $OCC saml:config:set 1 --idp-x509cert="$AUTHENTIK_CERT"
@@ -172,7 +172,7 @@ in {
$OCC config:app:set systemtags allow_user_creating --value="no" $OCC config:app:set systemtags allow_user_creating --value="no"
echo "Applying Theme..." echo "Applying Theme..."
$OCC config:app:set theming url --value="https://${containerCfg.subdomain}.${serverCfg.hostDomain}" $OCC config:app:set theming url --value="https://${containerCfg.subdomain}.${serverCfg.domain}"
${lib.optionalString (containerCfg.extra ? name) ''$OCC config:app:set theming name --value="${containerCfg.extra.name}"''} ${lib.optionalString (containerCfg.extra ? name) ''$OCC config:app:set theming name --value="${containerCfg.extra.name}"''}
${lib.optionalString (containerCfg.extra ? slogan) ''$OCC config:app:set theming slogan --value="${containerCfg.extra.slogan}"''} ${lib.optionalString (containerCfg.extra ? slogan) ''$OCC config:app:set theming slogan --value="${containerCfg.extra.slogan}"''}
$OCC config:app:set theming background_color --value="${serverCfg.colorScheme.palette.base02}" $OCC config:app:set theming background_color --value="${serverCfg.colorScheme.palette.base02}"

View File

@@ -11,8 +11,8 @@ let
wiki_url = ""; wiki_url = "";
custom = { custom = {
links = { links = {
"Home" = "https://${serverCfg.hostDomain}"; "Home" = "https://${serverCfg.domain}";
# "Status" = "https://status.${serverCfg.hostDomain}"; # "Status" = "https://status.${serverCfg.domain}";
}; };
}; };
pwa_colors = { pwa_colors = {
@@ -72,7 +72,7 @@ in {
port = 8080; port = 8080;
secret = name; secret = name;
extraEnv = { extraEnv = {
SEARXNG_BASE_URL = "https://${containerCfg.subdomain}.${serverCfg.hostDomain}"; SEARXNG_BASE_URL = "https://${containerCfg.subdomain}.${serverCfg.domain}";
SEARXNG_PORT = "8080"; SEARXNG_PORT = "8080";
SEARXNG_BIND_ADDRESS = "[::]"; SEARXNG_BIND_ADDRESS = "[::]";
SEARXNG_PUBLIC_INSTANCE = "false"; SEARXNG_PUBLIC_INSTANCE = "false";

View File

@@ -39,10 +39,10 @@ in {
"traefik.http.middlewares.umami-global.plugin.umami-feeder.umamiUsername" = "admin"; "traefik.http.middlewares.umami-global.plugin.umami-feeder.umamiUsername" = "admin";
"traefik.http.middlewares.umami-global.plugin.umami-feeder.umamiPassword" = "umami"; "traefik.http.middlewares.umami-global.plugin.umami-feeder.umamiPassword" = "umami";
"traefik.http.middlewares.umami-global.plugin.umami-feeder.createNewWebsites" = "true"; "traefik.http.middlewares.umami-global.plugin.umami-feeder.createNewWebsites" = "true";
} else {}) // (if containerCfg.extra ? provider || serverCfg.hostDomain != "localhost" then { } else {}) // (if containerCfg.extra ? provider || serverCfg.domain != "localhost" then {
"traefik.http.routers.${containerCfg.subdomain}.tls.certresolver" = "default"; "traefik.http.routers.${containerCfg.subdomain}.tls.certresolver" = "default";
"traefik.http.routers.${containerCfg.subdomain}.tls.domains[0].main" = "${serverCfg.hostDomain}"; "traefik.http.routers.${containerCfg.subdomain}.tls.domains[0].main" = "${serverCfg.domain}";
"traefik.http.routers.${containerCfg.subdomain}.tls.domains[0].sans" = "*.${serverCfg.hostDomain}"; "traefik.http.routers.${containerCfg.subdomain}.tls.domains[0].sans" = "*.${serverCfg.domain}";
} else {}); } else {});
extraEnv = { }; extraEnv = { };
overrides = { overrides = {
@@ -66,11 +66,11 @@ in {
"--experimental.plugins.umami-feeder.version=v1.4.1" "--experimental.plugins.umami-feeder.version=v1.4.1"
"--entrypoints.web-secure.http.middlewares=umami-global@docker" "--entrypoints.web-secure.http.middlewares=umami-global@docker"
] else []) ++ (if containerCfg.extra ? provider then [ ] else []) ++ (if containerCfg.extra ? provider then [
"--certificatesresolvers.default.acme.email=acme@${serverCfg.hostDomain}" "--certificatesresolvers.default.acme.email=acme@${serverCfg.domain}"
"--certificatesresolvers.default.acme.dnschallenge=true" "--certificatesresolvers.default.acme.dnschallenge=true"
"--certificatesresolvers.default.acme.dnschallenge.provider=${containerCfg.extra.provider}" "--certificatesresolvers.default.acme.dnschallenge.provider=${containerCfg.extra.provider}"
"--certificatesresolvers.default.acme.storage=/custom/acme.json" "--certificatesresolvers.default.acme.storage=/custom/acme.json"
] else []) ++ (if serverCfg.hostDomain != "localhost" then [ ] else []) ++ (if serverCfg.domain != "localhost" then [
"--certificatesresolvers.default.acme.httpchallenge=false" "--certificatesresolvers.default.acme.httpchallenge=false"
"--certificatesresolvers.default.acme.tlschallenge=true" "--certificatesresolvers.default.acme.tlschallenge=true"
] else []); ] else []);

View File

@@ -31,7 +31,7 @@ in {
secret = name; secret = name;
extraEnv = { extraEnv = {
PORT = "3000"; PORT = "3000";
# HOSTNAME = "${containerCfg.subdomain}.${serverCfg.hostDomain}"; # HOSTNAME = "${containerCfg.subdomain}.${serverCfg.domain}";
DATABASE_TYPE = "postgresql"; DATABASE_TYPE = "postgresql";
REDIS_URL = "redis://${builder.host}"; REDIS_URL = "redis://${builder.host}";
CLIENT_IP_HEADER = "X-Forwarded-For"; CLIENT_IP_HEADER = "X-Forwarded-For";

View File

@@ -24,8 +24,8 @@ let
"traefik.enable" = "true"; "traefik.enable" = "true";
"traefik.http.routers.${routerName}.entrypoints" = "web-secure"; "traefik.http.routers.${routerName}.entrypoints" = "web-secure";
"traefik.http.routers.${routerName}.rule" = if subpath != null "traefik.http.routers.${routerName}.rule" = if subpath != null
then "Host(`${subdomain}.${serverCfg.hostDomain}`) && PathPrefix(`/${subpath}`)" then "Host(`${subdomain}.${serverCfg.domain}`) && PathPrefix(`/${subpath}`)"
else "Host(`${subdomain}.${serverCfg.hostDomain}`)"; else "Host(`${subdomain}.${serverCfg.domain}`)";
"traefik.http.routers.${routerName}.tls" = "true"; "traefik.http.routers.${routerName}.tls" = "true";
} // lib.optionalAttrs (port!=null) { } // lib.optionalAttrs (port!=null) {
"traefik.http.services.${routerName}.loadbalancer.server.port" = toString port; "traefik.http.services.${routerName}.loadbalancer.server.port" = toString port;

View File

@@ -1,130 +0,0 @@
{ config, lib, pkgs, ... }:
let
cfg = config.syscfg.server;
containers = cfg.containers;
faviconOverride = {
" ~* /favicon\.(ico|png|svg|jpg)$" = {
extraConfig = ''
add_header Content-Type image/svg+xml;
return 200 '<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 50 50"><defs><style>.cls-1{fill:#fd4b2d;}</style></defs><path class="cls-1" d="M30.83,5A23.23,23.23,0,0,0,10.41,67.13h10.8C26,63,32.94,61.8,38,67.13H49.39C44.93,61.09,38.24,55,30.83,55Z"/><path class="cls-1" d="M46.25,28.11c-14.89,31.15-41,4.6-25-11H10.41c-8.47,14.76,3.24,34.68,20.42,34.23,13.28,0,24.24-19.72,24.24-23.21,0-1.54-2.14-6.25-5.68-11H38A40.52,40.52,0,0,1,46.25,78.11Zm.4-.91Z"/></svg>';
'';
# proxyPass = "http://127.0.0.1:9000";
};
};
# Function to convert your container config into an NGINX vhost
mkVhost = container: {
forceSSL = true;
# quic = true;
# http3 = true;
useACMEHost = "${cfg.hostDomain}";
locations = faviconOverride // {
"/" = {
proxyPass = "http://${container.ip}:${toString container.port}";
proxyWebsockets = true; # Recommended for modern apps
};
};
};
in {
config = lib.mkIf ( config.syscfg.server.web) {
security.acme = {
acceptTerms = true;
defaults.email = "admin@domain.org";
certs."${cfg.hostDomain}" = {
domain = "*.${cfg.hostDomain}";
extraDomainNames = [ "${cfg.hostDomain}" ]; # Adds the root too
dnsProvider = "infomaniak";
credentialsFile = config.sops.secrets."INFOMANIAK_API_KEY".path; # File containing your API token (e.g. CLOUDFLARE_DNS_API_TOKEN=...)
group = "nginx";
};
};
services.nginx = {
enable = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
recommendedGzipSettings = true;
# appendHttpConfig = ''
# add_header Alt-Svc 'h3=":443"; ma=86400';
# '';
commonHttpConfig = ''
proxy_buffer_size 32k;
proxy_buffers 8 16k;
proxy_busy_buffers_size 48k;
'';
virtualHosts = {
"_" = {
default = true;
forceSSL = true;
# quic = true;
# http3 = true;
useACMEHost = "${cfg.hostDomain}";
locations = {
"/" = {
extraConfig = ''
return 404;
'';
};
};
};
"sec.${cfg.hostDomain}" = {
forceSSL = true;
useACMEHost = "${cfg.hostDomain}";
locations = {
"/" = {
proxyWebsockets = true;
proxyPass= "http://${cfg.containers.authentik.subdomain}.${cfg.hostDomain}";
extraConfig = ''
auth_request /outpost.goauthentik.io/auth/nginx;
error_page 401 = @goauthentik_proxy_signin;
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
auth_request_set $authentik_username $upstream_http_x_authentik_username;
auth_request_set $authentik_groups $upstream_http_x_authentik_groups;
auth_request_set $authentik_entitlements $upstream_http_x_authentik_entitlements;
auth_request_set $authentik_email $upstream_http_x_authentik_email;
auth_request_set $authentik_name $upstream_http_x_authentik_name;
auth_request_set $authentik_uid $upstream_http_x_authentik_uid;
proxy_set_header X-authentik-username $authentik_username;
proxy_set_header X-authentik-groups $authentik_groups;
proxy_set_header X-authentik-entitlements $authentik_entitlements;
proxy_set_header X-authentik-email $authentik_email;
proxy_set_header X-authentik-name $authentik_name;
proxy_set_header X-authentik-uid $authentik_uid;
'';
};
"/outpost.goauthentik.io" = {
proxyWebsockets = true;
proxyPass = "http://${config.syscfg.server.containers.authentik.ip}:${toString config.syscfg.server.containers.authentik.port}/outpost.goauthentik.io";
extraConfig = ''
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
add_header Set-Cookie $auth_cookie;
auth_request_set $auth_cookie $upstream_http_set_cookie;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
'';
};
};
extraConfig = ''
location @goauthentik_proxy_signin {
internal;
add_header Set-Cookie $auth_cookie;
return 302 https://${cfg.containers.authentik.subdomain}.${cfg.hostDomain}/outpost.goauthentik.io/start?rd=$scheme://$http_host$request_uri;
}
'';
};
} //lib.mapAttrs' (name: v:
lib.nameValuePair "${v.subdomain}.${cfg.hostDomain}" (mkVhost v)
) containers;
};
};
}

View File

@@ -2,7 +2,7 @@
let let
in with lib; { in with lib; {
hostDomain = mkOption { type = types.str; }; domain = mkOption { type = types.str; };
mailDomain = mkOption { type = types.str; }; mailDomain = mkOption { type = types.str; };
mailServer = mkOption { type = types.str; }; mailServer = mkOption { type = types.str; };

View File

@@ -19,23 +19,35 @@
virt = true; virt = true;
}; };
server = { server = {
domain = "test.helcel.net";
openssh = true; openssh = true;
web = true; web = true;
hostDomain = "test.helcel.net"; # mail = {
# server = ...
# user = ...
# ...
# };
mailDomain = "test@helcel"; mailDomain = "test@helcel";
mailServer = "infomaniak.ch"; mailServer = "infomaniak.ch";
containers = { containers = {
# ===== BASE =====
traefik = { traefik = {
subdomain = "traefik"; subdomain = "traefik";
extra={provider="infomaniak";}; extra={provider="infomaniak";};
}; };
umami = {
subdomain = "umami";
};
authentik = { authentik = {
subdomain = "sso"; subdomain = "sso";
port = 9000; port = 9000;
}; };
searxng = {
subdomain = "searx";
};
# ===== CLOUD =====
nextcloud = { nextcloud = {
subdomain = "cloud"; subdomain = "cloud";
}; };
@@ -46,27 +58,48 @@
subdomain = "pad"; subdomain = "pad";
}; };
ethercalc = { ethercalc = {
subdomain = "pad"; subdomain = "calc";
}; };
gitea = { immich = {
subdomain = "git"; subdomain = "pic";
};
searxng = {
subdomain = "searx";
}; };
# ===== FLIX =====
# invidious = {
# subdomain = "yt";
# };
jellyfin = { jellyfin = {
subdomain = "flix"; subdomain = "flix";
}; };
transmission = {
subdomain = "rflix";
subpath = "p2p";
};
# servarr = { # servarr = {
# subdomain = "arr"; # subdomain = "arr";
# }; # };
umami = { transmission = {
subdomain = "umami"; subdomain = "arr";
subpath = "p2p";
}; };
# handbrake = {
# subdomain = "arr";
# subpath = "hb";
# };
# ===== DEV =====
gitea = {
subdomain = "git";
};
# ===== HOME =====
# homeassistant = {
# subdomain = "hass";
# };
# frigate = {
# subdomain = "hass";
# subpath = "cam";
# };
# trmnl = {
# subdomain = "hass";
# subpath = "trmnl";
# };
# influx = {
# subdomain = "metrum";
# };
}; };
}; };
}; };