feat: add koillection

This commit is contained in:
Leon Schwarzäugl 2025-06-13 17:23:22 +02:00
parent 86e1e1984b
commit 80d4a38a1c
Signed by: swarsel
GPG key ID: 26A54C31F2A4FD84
4 changed files with 224 additions and 2 deletions

View file

@ -4278,6 +4278,7 @@ Modules that need to be loaded on the NixOS level. Note that these will not be a
jenkins = lib.mkDefault false; jenkins = lib.mkDefault false;
kanidm = lib.mkDefault true; kanidm = lib.mkDefault true;
firefly = lib.mkDefault true; firefly = lib.mkDefault true;
koillection = lib.mkDefault true;
}; };
}; };
}; };
@ -9425,6 +9426,117 @@ To get other URLs (token, etc.), use https://<kanidmDomain>/oauth2/openid/<clien
} }
#+end_src #+end_src
**** Koillection
#+begin_src nix :tangle modules/nixos/server/koillection.nix
{ lib, config, ... }:
let
serviceDomain = "swag.swarsel.win";
serviceUser = "koillection";
serviceDB = "koillection";
serviceName = "koillection";
servicePort = 2282;
postgresUser = config.systemd.services.postgresql.serviceConfig.User; # postgres
postgresPort = config.services.postgresql.settings.port; # 5432
containerRev = "sha256:96693e41a6eb2aae44f96033a090378270f024ddf4e6095edf8d57674f21095d";
in
{
options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
sops.secrets = {
koillection-db-password = { owner = postgresUser; group = postgresUser; mode = "0440"; };
koillection-env-file = { };
};
virtualisation.oci-containers.containers = {
koillection = {
image = "koillection/koillection@${containerRev}";
ports = [
"${toString servicePort}:80"
];
environment = {
APP_DEBUG = "0";
APP_ENV = "prod";
HTTPS_ENABLED = "1";
UPLOAD_MAX_FILESIZE = "512M";
PHP_MEMORY_LIMIT = "512M";
PHP_TZ = config.repo.secrets.common.location.timezone;
CORS_ALLOW_ORIGIN = "https?://(localhost|swag\\.swarsel\\.win)(:[0-9]+)?$";
DB_DRIVER = "pdo_pgsql";
DB_NAME = serviceDB;
DB_HOST = "host.docker.internal";
DB_USER = serviceUser;
# DB_PASSWORD set in koillection-env-file
DB_PORT = "${toString postgresPort}";
DB_VERSION = "16";
};
environmentFiles = [
config.sops.secrets.koillection-env-file.path
];
extraOptions = [
"--add-host=host.docker.internal:host-gateway" # podman
];
};
};
networking.firewall.allowedTCPPorts = [ postgresPort ];
systemd.services.postgresql.postStart =
let
passwordPath = config.sops.secrets.koillection-db-password.path;
in
''
$PSQL -tA <<'EOF'
DO $$
DECLARE password TEXT;
BEGIN
password := trim(both from replace(pg_read_file('${passwordPath}'), E'\n', '''));
EXECUTE format('ALTER ROLE ${serviceDB} WITH PASSWORD '''%s''';', password);
END $$;
EOF
'';
services = {
postgresql = {
enable = true;
enableTCPIP = true;
ensureDatabases = [ serviceDB ];
ensureUsers = [
{
name = serviceDB;
ensureDBOwnership = true;
}
];
authentication = ''
host ${serviceDB} ${serviceDB} 10.88.0.0/16 scram-sha-256
'';
};
nginx = {
virtualHosts = {
"${serviceDomain}" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://localhost:${toString servicePort}";
};
};
};
};
};
};
};
}
#+end_src
*** Darwin *** Darwin
:PROPERTIES: :PROPERTIES:
:CUSTOM_ID: h:ac0cd8b3-06cf-4dca-ba73-6100c8fedb47 :CUSTOM_ID: h:ac0cd8b3-06cf-4dca-ba73-6100c8fedb47

View file

@ -0,0 +1,106 @@
{ lib, config, ... }:
let
serviceDomain = "swag.swarsel.win";
serviceUser = "koillection";
serviceDB = "koillection";
serviceName = "koillection";
servicePort = 2282;
postgresUser = config.systemd.services.postgresql.serviceConfig.User; # postgres
postgresPort = config.services.postgresql.settings.port; # 5432
containerRev = "sha256:96693e41a6eb2aae44f96033a090378270f024ddf4e6095edf8d57674f21095d";
in
{
options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
sops.secrets = {
koillection-db-password = { owner = postgresUser; group = postgresUser; mode = "0440"; };
koillection-env-file = { };
};
virtualisation.oci-containers.containers = {
koillection = {
image = "koillection/koillection@${containerRev}";
ports = [
"${toString servicePort}:80"
];
environment = {
APP_DEBUG = "0";
APP_ENV = "prod";
HTTPS_ENABLED = "1";
UPLOAD_MAX_FILESIZE = "512M";
PHP_MEMORY_LIMIT = "512M";
PHP_TZ = config.repo.secrets.common.location.timezone;
CORS_ALLOW_ORIGIN = "https?://(localhost|swag\\.swarsel\\.win)(:[0-9]+)?$";
DB_DRIVER = "pdo_pgsql";
DB_NAME = serviceDB;
DB_HOST = "host.docker.internal";
DB_USER = serviceUser;
# DB_PASSWORD set in koillection-env-file
DB_PORT = "${toString postgresPort}";
DB_VERSION = "16";
};
environmentFiles = [
config.sops.secrets.koillection-env-file.path
];
extraOptions = [
"--add-host=host.docker.internal:host-gateway" # podman
];
};
};
networking.firewall.allowedTCPPorts = [ postgresPort ];
systemd.services.postgresql.postStart =
let
passwordPath = config.sops.secrets.koillection-db-password.path;
in
''
$PSQL -tA <<'EOF'
DO $$
DECLARE password TEXT;
BEGIN
password := trim(both from replace(pg_read_file('${passwordPath}'), E'\n', '''));
EXECUTE format('ALTER ROLE ${serviceDB} WITH PASSWORD '''%s''';', password);
END $$;
EOF
'';
services = {
postgresql = {
enable = true;
enableTCPIP = true;
ensureDatabases = [ serviceDB ];
ensureUsers = [
{
name = serviceDB;
ensureDBOwnership = true;
}
];
authentication = ''
host ${serviceDB} ${serviceDB} 10.88.0.0/16 scram-sha-256
'';
};
nginx = {
virtualHosts = {
"${serviceDomain}" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://localhost:${toString servicePort}";
};
};
};
};
};
};
};
}

View file

@ -37,6 +37,7 @@
jenkins = lib.mkDefault false; jenkins = lib.mkDefault false;
kanidm = lib.mkDefault true; kanidm = lib.mkDefault true;
firefly = lib.mkDefault true; firefly = lib.mkDefault true;
koillection = lib.mkDefault true;
}; };
}; };
}; };

View file

@ -65,6 +65,9 @@ oauth2-cookie-secret: ENC[AES256_GCM,data:l8BPYA7t9NG9MPFs/LDlFHqwbnwsvie7FM5v61
kanidm-oauth2-proxy-client: ENC[AES256_GCM,data:+mcA/sz3AZuw+I44iIdOEfDmtjEVdxi2fg==,iv:m4NpieUicS7xsR+F5AgPqkcUFRF+CGOA8IK6GeS9tgM=,tag:1wypxpiHPdQBD8Td/PSdMw==,type:str] kanidm-oauth2-proxy-client: ENC[AES256_GCM,data:+mcA/sz3AZuw+I44iIdOEfDmtjEVdxi2fg==,iv:m4NpieUicS7xsR+F5AgPqkcUFRF+CGOA8IK6GeS9tgM=,tag:1wypxpiHPdQBD8Td/PSdMw==,type:str]
#ENC[AES256_GCM,data:Y1BVSKrxqnK/8yk=,iv:Bg8OSExGPV9kwkuDb/69BXMyDnzbr1TAnVZEOxNWljo=,tag:Cq76DQ1g26pFLHwZP3pqYQ==,type:comment] #ENC[AES256_GCM,data:Y1BVSKrxqnK/8yk=,iv:Bg8OSExGPV9kwkuDb/69BXMyDnzbr1TAnVZEOxNWljo=,tag:Cq76DQ1g26pFLHwZP3pqYQ==,type:comment]
firefly-iii-app-key: ENC[AES256_GCM,data:hzgl8eRL0irNRP5TO7G1rNtNM7fXCkmbcaX4QoTsM0xA1rgyKwiy6a4lYDjoXZyOMy5p,iv:q5eepIELwIecyQ56A6THUOu+rebK3irKVYb7/gNHlU8=,tag:+M/KTX1JzPzXeK4TRzW42w==,type:str] firefly-iii-app-key: ENC[AES256_GCM,data:hzgl8eRL0irNRP5TO7G1rNtNM7fXCkmbcaX4QoTsM0xA1rgyKwiy6a4lYDjoXZyOMy5p,iv:q5eepIELwIecyQ56A6THUOu+rebK3irKVYb7/gNHlU8=,tag:+M/KTX1JzPzXeK4TRzW42w==,type:str]
#ENC[AES256_GCM,data:IfT5loUt/GO7Nz8=,iv:ApxflDybVNaaWObZMw2S/JeUTDbYrzkiR8bRhL8WvHU=,tag:GfHdPmcX/DGqeWq2OYrpmg==,type:comment]
koillection-env-file: ENC[AES256_GCM,data:X1dndR7XIhGCwbRQzET5MbzW71PT7WmyryNbOhCKx2I=,iv:bP/90aJT+eA8EmwoFZ7uXxOWfOprpHfc9CvL/A9Os5M=,tag:ZxFDInJBtFrulvOL9PwNJQ==,type:str]
koillection-db-password: ENC[AES256_GCM,data:5Ue4l8CMZpjRpcryEtzPyR2Zf7M=,iv:Ol/G6nFY5H/SIY7l4o5woqFVeLfnv3FJfaAZIqI4NHA=,tag:hYorZv2nyLvsJ8AT2xTkBA==,type:str]
sops: sops:
age: age:
- recipient: age1h72072slm2pthn9m2qwjsyy2dsazc6hz97kpzh4gksvv0r2jqecqul8w63 - recipient: age1h72072slm2pthn9m2qwjsyy2dsazc6hz97kpzh4gksvv0r2jqecqul8w63
@ -76,8 +79,8 @@ sops:
MEZ1UWw3alF1WnJZMFZvMFBpbDFJZlUKGRnoEEgjgJ9SSblmldtY6d8MdAy01yxl MEZ1UWw3alF1WnJZMFZvMFBpbDFJZlUKGRnoEEgjgJ9SSblmldtY6d8MdAy01yxl
qkvEIoXbL+ky2ira7EgjD0legThzCnmlXUlcSn3SpwbkAGgcfd2kWA== qkvEIoXbL+ky2ira7EgjD0legThzCnmlXUlcSn3SpwbkAGgcfd2kWA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2025-06-12T18:54:27Z" lastmodified: "2025-06-13T12:36:23Z"
mac: ENC[AES256_GCM,data:5SPDEOz+PBoavltKbVCAAFOexS3In1+jOUdP3V59ssWevKnxX09ALENfwQW4DkL/U4wrryKp9zQ1qmg43SPK2cWrbswsIhzupYE+VvhR3pORiCk/k3GhtE9jnQPD3W7WvNz29rMthgyo5AY/QERfd+YiuMLGmKofoqaWWpKnhRA=,iv:FTDBDKlRgUja5zRIzpO8d6IfCjvmMq1RDRSi3AfmB3A=,tag:zV0boAnx98PxgK1H3jRWOA==,type:str] mac: ENC[AES256_GCM,data:u0OK9URSDN58qk/DE6byXeOs7X59wsxaDvbisk1vbGLPW2DJ6RPcobTSxZhBEWSHr9J4ov9J+WaXSibLyQpljNDsdLPWTW/PrU5ThHCZc/lQ2mN5WZysFCj83sAiY8Z7pCCOcn4iy5lVuJuiU5+C5kEMwyRdTXiYO2Jk2LaWN9g=,iv:s9gPp/pm7J8hxSZhf2nD9qpE/AXBbAmufyYxQ/rvBY4=,tag:iBmL3LPV+NLrcE4eMjnQ1A==,type:str]
pgp: pgp:
- created_at: "2024-12-17T16:24:32Z" - created_at: "2024-12-17T16:24:32Z"
enc: |- enc: |-