This commit is contained in:
soraefir
2026-05-08 20:22:04 +02:00
parent d3c301db36
commit 7194d91b1c
13 changed files with 214 additions and 293 deletions

View File

@@ -17,19 +17,11 @@
inputs.nixpkgs.follows = "nixpkgs";
};
# hyprland = {
# url = "github:hyprwm/Hyprland";
# inputs.nixpkgs.follows = "nixpkgs";
# };
sops-nix = {
url = "github:Mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
nix-colors.url = "github:misterio77/nix-colors";
arion.url = "github:hercules-ci/arion";
arion.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = inputs:

View File

@@ -13,7 +13,6 @@
./modules/nixos
syscfg
./systems/${host}
inputs.arion.nixosModules.arion
inputs.sops-nix.nixosModules.sops
inputs.home-manager.nixosModules.home-manager
{

View File

@@ -9,10 +9,12 @@ let
containers = lib.mapAttrs' (cName: cValue:
lib.nameValuePair "${name}-${cName}" cValue
) defs.containers;
paths = defs.paths or [];
}
) enabledConfigs;
mergedContainers = lib.attrsets.mergeAttrsList (lib.map(e: e.containers) containerSetsList);
allPathConfigs = lib.flatten (lib.map (e: e.paths or []) containerSetsList);
allPathConfigs = lib.flatten (lib.map (e: e.paths) containerSetsList);
allScriptConfigs = lib.flatten (lib.map (e: e.init or "") containerSetsList);
in
{
config = lib.mkIf ( enabledConfigs != {} ) {
@@ -35,9 +37,9 @@ in
system.activationScripts.container-setup-dirs = {
deps = [ "users" "groups" ];
text = lib.concatStringsSep "\n" (map (cfg: ''
mkdir -p "${cfg.path}"
chown ${cfg.owner} "${cfg.path}"
chmod ${cfg.mode} "${cfg.path}"
${pkgs.coreutils}/bin/mkdir -p "${cfg.path}"
${pkgs.coreutils}/bin/chown ${cfg.owner} "${cfg.path}"
${pkgs.coreutils}/bin/chmod ${cfg.mode} "${cfg.path}"
'') allPathConfigs);
};
};

View File

@@ -4,11 +4,11 @@ version = "2026.2.2";
serverCfg = config.syscfg.server;
in {
paths = [{
path="${serverCfg.dataPath}/authentik/media";
path="${serverCfg.configPath}/authentik/media";
owner = "1000:1000";
mode = "0755";
}{
path="${serverCfg.dataPath}/authentik/templates";
path="${serverCfg.configPath}/authentik/templates";
owner = "1000:1000";
mode = "0755";
}];
@@ -39,8 +39,8 @@ in {
cmd = [ "server" ];
ports = if containerCfg.pubPort != 0 && containerCfg.port != 0 then [ "${toString containerCfg.pubPort}:${toString containerCfg.port}" ] else [];
volumes = [
"${serverCfg.dataPath}/authentik/media:/media"
"${serverCfg.dataPath}/authentik/templates:/templates"
"${serverCfg.configPath}/authentik/media:/media"
"${serverCfg.configPath}/authentik/templates:/templates"
];
};
};
@@ -60,8 +60,8 @@ in {
overrides = {
cmd = [ "worker" ];
volumes = [
"${serverCfg.dataPath}/authentik/media:/media"
"${serverCfg.dataPath}/authentik/templates:/templates"
"${serverCfg.configPath}/authentik/media:/media"
"${serverCfg.configPath}/authentik/templates:/templates"
# "/var/run/podman/podman.sock:/var/run/docker.sock" #PODMAN GROUP FOR SOCKET ACCESS
];
};

View File

@@ -1,152 +0,0 @@
{ config, pkgs, lib, ... }:
let serverCfg = config.syscfg.server;
in {
project.name = "cloud";
networks = {
internal = {
name = lib.mkForce "internal";
internal = true;
};
external = {
name = lib.mkForce "external";
internal = false;
};
};
services = {
cloud_nextcloud.service = {
image = "nextcloud:27";
container_name = "cloud";
restart = "unless-stopped";
networks = [ "external" ];
volumes = [
"${serverCfg.configPath}/data/nextcloud:/var/www/html"
"${serverCfg.dataPath}/data/music:/media/music"
"${serverCfg.dataPath}/data/video:/media/video"
"${serverCfg.dataPath}/data/photo:/media/photo"
];
tmpfs = [ "/tmp" ];
labels = {
"traefik.enable" = "true";
"traefik.http.routers.nextcloud.entrypoints" = "web-secure";
"traefik.http.routers.nextcloud.rule" =
"Host(`cloud.${serverCfg.hostDomain}`)";
"traefik.http.routers.nextcloud.tls" = "true";
"traefik.http.routers.nextcloud.middlewares" =
"sts_headers,nextcloud-caldav";
"traefik.http.middlewares.nextcloud-caldav.redirectregex.permanent" =
"true";
"traefik.http.middlewares.nextcloud-caldav.redirectregex.regex" =
"^https://(.*)/.well-known/(card|cal)dav";
"traefik.http.middlewares.nextcloud-caldav.redirectregex.replacement" =
"https://$\${1}/remote.php/dav/";
"traefik.http.middlewares.sts_headers.headers.stsSeconds" = "15552000";
"traefik.http.middlewares.sts_headers.headers.stsIncludeSubdomains" =
"true";
};
};
cloud_office.service = {
image = "collabora/code:latest";
container_name = "cloud_office";
restart = "unless-stopped";
networks = [ "external" ];
volumes = [ ];
environment = {
username = "COLLABORA_USER";
password = "COLLABORA_PASSWORD";
aliasgroup1 = "https://cloud.${serverCfg.hostDomain}";
server_name = "office.${serverCfg.hostDomain}";
VIRTUAL_HOST = "office.${serverCfg.hostDomain}";
VIRTUAL_PORT = "9980";
VIRTUAL_PROTO = "http";
DONT_GEN_SSL_CERT = "true";
RESOLVE_TO_PROXY_IP = "true";
NETWORK_ACCESS = "internal";
extra_params = "--o:ssl.enable=false --o:ssl.termination=true";
dictionaries = "en fr de jp";
};
labels = {
"traefik.enable" = "true";
"traefik.http.routers.collabora.entrypoints" = "web-secure";
"traefik.http.routers.collabora.rule" =
"Host(`office.${serverCfg.hostDomain}`)";
"traefik.http.routers.collabora.tls" = "true";
};
};
cloud_etherpad.service = {
image = "etherpad/etherpad:latest";
container_name = "etherpad";
restart = "unless-stopped";
networks = [ "external" ];
volumes = [
"${serverCfg.dataPath}/ether/etherpad/data:/opt/etherpad-lite/var"
"${serverCfg.dataPath}/ether/etherpad/APIKEY.txt:/opt/etherpad-lite/APIKEY.txt"
];
environment = {
NODE_ENV = "production";
TITLE = "Helcel-Pad";
DB_TYPE = "mysql";
DB_HOST = serverCfg.dbHost;
DB_PORT = serverCfg.dbPort;
DB_NAME = "etherpad";
DB_USER = "ETHERPAD_DB_USER";
DB_PASS = "ETHERPAD_DB_PASSWORD";
DB_CHARSET = "utf8mb4";
DEFAULT_PAD_TEXT = "P A D";
PAD_OPTIONS_SHOW_LINE_NUMBERS = "true";
PAD_OPTIONS_USE_MONOSPACE_FONT = "true";
ADMIN_PASSWORD = "ETHERPAD_ADMIN_PASSWORD";
SKIN_VARIANTS = "super-dark-toolbar light-editor dark-background";
};
labels = {
"traefik.enable" = "true";
"traefik.http.routers.etherpad.entrypoints" = "web-secure";
"traefik.http.routers.etherpad.rule" =
"Host(`pad.${serverCfg.hostDomain}`)";
"traefik.http.routers.etherpad.tls" = "true";
};
};
cloud_ethercalc.service = {
image = "audreyt/ethercalc:latest";
container_name = "ethercalc";
restart = "unless-stopped";
networks = [ "external" "internal" ];
volumes = [
"${serverCfg.dataPath}/ether/etherpad/data:/opt/etherpad-lite/var"
"${serverCfg.dataPath}/ether/etherpad/APIKEY.txt:/opt/etherpad-lite/APIKEY.txt"
];
environment = {
NODE_ENV = "production";
TITLE = "Helcel-Calc";
REDIS_PORT_6379_TCP_ADDR = "ethercalc-redis";
REDIS_PORT_6379_TCP_PORT = "6379";
ADMIN_PASSWORD = "ETHERPAD_ADMIN_PASSWORD";
SKIN_VARIANTS = "super-dark-toolbar light-editor dark-background";
};
labels = {
"traefik.enable" = "true";
"traefik.http.routers.ethercalc.entrypoints" = "web-secure";
"traefik.http.routers.ethercalc.rule" =
"Host(`calc.${serverCfg.hostDomain}`)";
"traefik.http.routers.ethercalc.tls" = "true";
};
};
cloud_redis.service = {
image = "redis:latest";
container_name = "ethercalc-redis";
restart = "unless-stopped";
networks = [ "internal" ];
volumes = [ "${serverCfg.dataPath}/ether/ethercalc/redis:/data" ];
environment = { };
labels = { "traefik.enable" = "false"; };
};
};
}

View File

@@ -0,0 +1,35 @@
{ config, containerCfg, pkgs, lib, builder, ... }:
let
version = "latest";
serverCfg = config.syscfg.server;
in {
containers = {
server = builder.mkContainer {
subdomain = containerCfg.subdomain;
image = "collabora/code:${version}";
port = containerCfg.port;
ip = containerCfg.ip;
secret = "collabora";
extraEnv = {
"username" = "COLLABORA_USER";
"password" = "COLLABORA_PASSWORD";
"aliasgroup1" = "https://${serverCfg.containers.nextcloud.subdomain}.${serverCfg.hostDomain}";
"server_name" = "${containerCfg.subdomain}.${serverCfg.hostDomain}";
"VIRTUAL_HOST" = "${containerCfg.subdomain}.${serverCfg.hostDomain}";
"VIRTUAL_PORT" = "${containerCfg.port}";
"VIRTUAL_PROTO" = "http";
"DONT_GEN_SSL_CERT" = "true";
"RESOLVE_TO_PROXY_IP" = "true";
"extra_params" = "--o:ssl.enable=false --o:ssl.termination=true";
"dictionaries" = "en fr de jp no";
};
overrides = {
volumes = [
"${pkgs.noto-fonts}/share/fonts/noto:/opt/collaboraoffice/share/fonts/truetype/noto:ro"
"${pkgs.ibm-plex}/share/fonts/opentype:/opt/collaboraoffice/share/fonts/opentype/plex:ro"
];
};
};
};
}

View File

@@ -0,0 +1,49 @@
{ config, containerCfg, pkgs, lib, builder, ... }:
let
version = "latest";
serverCfg = config.syscfg.server;
in {
paths = [{
path="${serverCfg.dataPath}/etherpad/data";
owner = "1000:1000";
mode = "0755";
}{
path="${serverCfg.dataPath}/etherpad/APIKEY.txt";
owner = "1000:1000";
mode = "0755";
backup = true;
}];
containers = {
server = builder.mkContainer {
subdomain = containerCfg.subdomain;
image = "etherpad/etherpad:${version}";
port = containerCfg.port;
ip = containerCfg.ip;
secret = "etherpad";
extraEnv = {
NODE_ENV = "production";
TITLE = "Pad";
PORT = toString containerCfg.port;
DB_TYPE = "postgres";
DB_HOST = builder.host;
DB_NAME = "etherpad_db";
DB_USER = "etherpad_user";
DB_PASS = "ETHERPAD_DB_PASSWORD";
ADMIN_PASSWORD = "ETHERPAD_ADMIN_PASSWORD";
"TRUST_PROXY" = "true";
DB_CHARSET = "utf8mb4";
DEFAULT_PAD_TEXT = "";
PAD_OPTIONS_SHOW_LINE_NUMBERS = "true";
PAD_OPTIONS_USE_MONOSPACE_FONT = "true";
SKIN_VARIANTS = "super-dark-toolbar light-editor dark-background";
};
overrides = {
volumes = [
"${serverCfg.dataPath}/etherpad/data:/opt/etherpad-lite/var"
"${serverCfg.dataPath}/etherpad/APIKEY.txt:/opt/etherpad-lite/APIKEY.txt"
];
};
};
};
}

View File

@@ -0,0 +1,56 @@
{ config, containerCfg, pkgs, lib, builder, ... }:
let
version = "27";
serverCfg = config.syscfg.server;
in {
paths = [{
path="${serverCfg.dataPath}/nextcloud/www";
owner = "1000:1000";
mode = "0755";
}{
path="${serverCfg.dataPath}/nextcloud/data";
owner = "1000:1000";
mode = "0755";
backup = true;
}];
containers = {
server = builder.mkContainer {
subdomain = containerCfg.subdomain;
image = "nextcloud:${version}";
port = containerCfg.port;
ip = containerCfg.ip;
secret = "nextcloud";
extraEnv = {
"REDIS_HOST" = builder.host;
"POSTGRES_HOST" = builder.host;
"POSTGRES_USER" = "nextcloud_user";
"POSTGRES_DB" = "nextcloud_db";
"NEXTCLOUD_TRUSTED_DOMAINS " = "${containerCfg.subdomain}.${serverCfg.hostDomain}";
"SMTP_HOST" = ${serverCfg.mailServer};
"SMTP_NAME" = "mail_user";
"SMTP_PASSWORD" = "mail_password";
"MAIL_FROM_ADDRESS" = "${containerCfg.subdomain}@${serverCfg.hostDomain}";
"MAIL_DOMAIN" = ${serverCfg.mailDomain};
"TRUSTED_PROXIES" = "...";
};
extraLabels = {
"traefik.http.routers.${containerCfg.subdomain}.middlewares" = "sts_headers,${containerCfg.subdomain}-caldav";
"traefik.http.middlewares.${containerCfg.subdomain}-caldav.redirectregex.permanent" = "true";
"traefik.http.middlewares.${containerCfg.subdomain}-caldav.redirectregex.regex" = "^https://(.*)/.well-known/(card|cal)dav";
"traefik.http.middlewares.${containerCfg.subdomain}-caldav.redirectregex.replacement" = "https://$\${1}/remote.php/dav/";
"traefik.http.middlewares.sts_headers.headers.stsSeconds" = "15552000";
"traefik.http.middlewares.sts_headers.headers.stsIncludeSubdomains" = "true";
};
overrides = {
ports = if containerCfg.pubPort != 0 && containerCfg.port != 0 then [ "${toString containerCfg.pubPort}:${toString containerCfg.port}" ] else [];
volumes = [
"${serverCfg.dataPath}/nextcloud/www:/var/www/html"
"${serverCfg.dataPath}/nextcloud/data:/var/www/html/data"
];
tmpfs = [ "/tmp" ];
};
};
};
}

View File

@@ -1,30 +0,0 @@
{ config, pkgs, lib, ... }:
let serverCfg = config.syscfg.server;
in {
project.name = "name";
networks = {
internal = {
name = lib.mkForce "internal";
internal = true;
};
external = {
name = lib.mkForce "external";
internal = false;
};
};
services = {
NAME.service = {
image = "NAME:latest";
container_name = "NAME";
restart = "unless-stopped";
networks = [ "internal" ];
volumes = [ ];
environment = { };
labels = { "traefik.enable" = "false"; };
};
};
}

View File

@@ -1,78 +1,41 @@
{ config, pkgs, ... }: {
project.name = "traefik";
{ config, containerCfg, pkgs, lib, builder, ... }:
let
version = "2026.2.2";
serverCfg = config.syscfg.server;
in {
paths = [{
path="${serverCfg.dataPath}/authentik/media";
owner = "1000:1000";
mode = "0755";
}{
path="${serverCfg.dataPath}/authentik/templates";
owner = "1000:1000";
mode = "0755";
}];
networks = {
internal = {
name = lib.mkForce "internal";
internal = true;
containers = {
server = builder.mkContainer {
subdomain = containerCfg.subdomain;
image = "traefik:${version}";
port = containerCfg.port;
ip = containerCfg.ip;
extraEnv = {
"INFOMANIAK_ACCESS_TOKEN" = config.sops.secrets.INFOMANIAK_API_KEY.path;
};
external = {
name = lib.mkForce "external";
internal = false;
};
};
services = {
traefik.service = {
image = "traefik:latest";
container_name = "traefik";
restart = "unless-stopped";
networks = [ "internal" "external" ];
command = [
overrides = {
cmd = [
"--api"
"--providers.docker=true"
"--entrypoints.web.address=:80"
"--entrypoints.web-secure.address=:443"
];
port = [ "443" "80" ];
ports = [ "443" "80" ];
volumes = [
"/var/run/docker.sock:/var/run/docker.sock:ro"
"${serverCfg.configPath}/traefik/traefik.yaml:/etc/traefik/traefik.yaml"
"${serverCfg.configPath}/traefik/access.log:/etc/traefik/access.log"
"${serverCfg.configPath}/traefik/acme.json:/acme.json"
];
environment = {
"INFOMANIAK_ACCESS_TOKEN" = config.sops.secrets.INFOMANIAK_API_KEY.path;
};
labels = { "traefik.enable" = "false"; };
};
matomo.service = {
image = "matomo:latest";
container_name = "matomo";
restart = "unless-stopped";
networks = [ "external" ];
volumes = [
"/etc/localtime:/etc/localtime:ro"
"${serverCfg.configPath}/matomo:/var/www/html/config:rw"
"${serverCfg.configPath}/traefik/access.log:/var/log/taccess.log:ro"
];
environment = { };
labels = {
"traefik.http.routers.matomo.rule" =
"Host(`matomo.${serverCfg.hostDomain}`)";
"traefik.http.routers.matomo.entrypoints" = "web-secure";
"traefik.http.routers.matomo.tls" = "true";
};
};
searx.service = {
image = "searxng/searxng:latest";
container_name = "searx";
restart = "unless-stopped";
networks = [ "external" ];
volumes = [ "/etc/localtime:/etc/localtime:ro" ];
environment = {
"BASE_URL" = "https://searx.${serverCfg.hostDomain}";
"AUTOCOMPLETE" = "true";
"INSTANCE_NAME" = "searx${serverCfg.shortName}";
};
labels = {
"traefik.http.routers.matomo.rule" =
"Host(`searx.${serverCfg.hostDomain}`)";
"traefik.http.routers.matomo.entrypoints" = "web-secure";
"traefik.http.routers.matomo.tls" = "true";
};
};

View File

@@ -1,12 +1,6 @@
{ config, lib, ... }:
let
cfg = config.syscfg.server;
DBlistNames = config.syscfg.server.db;
DBcontainerNames = lib.mapAttrsToList
(name: cfg: name)
(lib.filterAttrs (name: cfg: cfg.db or false) config.syscfg.server.containers);
DBallApps = lib.unique (DBlistNames ++ DBcontainerNames);
in{
boot.kernel.sysctl = {
"net.ipv4.ip_forward" = 1;
@@ -15,20 +9,6 @@ in{
networking.nftables.enable = true;
networking.nftables.ruleset = ''
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
ct state established,related accept
iifname "lo" accept
iifname { "podman*", "veth*" } accept
tcp dport {422, 22} accept
${if builtins.length DBallApps > 0 then ''tcp dport {5432, 6379} accept'' else ""}
${if cfg.web then ''tcp dport {80, 443} accept'' else ""}
${if cfg.web then ''udp dport {80, 443} accept'' else ""}
${if cfg.wireguard then ''tcp dport {1515} accept'' else ""}
${if cfg.wireguard then ''udp dport {1515} accept'' else ""}
}
}
${if cfg.nftables.enable then ''
table inet nat {
chain prerouting {

View File

@@ -0,0 +1,13 @@
INFOMANIAK_API_KEY: abc
AUTHENTIK: |
DB_PASSWORD=abc
AUTHENTIK_POSTGRESQL__PASSWORD=abc
AUTHENTIK_POSTGRESQL__SSLMODE=disable
AUTHENTIK_SECRET_KEY=abc
NEXTCLOUD: |
DB_PASSWORD=abc
POSTGRES_PASSWORD=abc
ETHERPAD: |
DB_PASSWORD=abc
ETHERPAD_DB_PASSWORD=abc
ETHERPAD_ADMIN_PASSWORD=abc

View File

@@ -40,6 +40,20 @@
port = 9000;
pubPort = 9999;
};
collabora = {
enable = true;
db = false;
subdomain = "office";
ip = "10.88.0.127";
port = 9980;
};
etherpad = {
enable = true;
db = true;
subdomain = "pad";
ip = "10.88.0.128";
port = 80;
};
};
};
};