style: format tree

This commit is contained in:
nhnn
2025-06-18 19:53:44 +03:00
parent ed990906bd
commit 86233cac27
44 changed files with 2523 additions and 2253 deletions

View File

@@ -5,37 +5,40 @@
nixpkgs-24-11.url = "github:NixOS/nixpkgs/nixos-24.11";
};
outputs = {nixpkgs-24-11, ...}: {
nixosModules.default = import ./module.nix nixpkgs-24-11.legacyPackages.x86_64-linux;
configPathsNeeded =
builtins.fromJSON (builtins.readFile ./config-paths-needed.json);
meta = {lib, ...}: {
spModuleSchemaVersion = 1;
id = "vikunja";
name = "Vikunja";
description = "Vikunja, the fluffy, open-source, self-hostable to-do app.";
svgIcon = builtins.readFile ./icon.svg;
isMovable = true;
isRequired = false;
backupDescription = "Tasks and attachments.";
systemdServices = [
"vikunja.service"
];
folders = [
"/var/lib/vikunja"
];
postgreDatabases = [
"vikunja"
];
license = [
lib.licenses.agpl3Plus
];
homepage = "https://vikunja.io";
sourcePage = "https://github.com/go-vikunja/vikunja";
supportLevel = "normal";
sso = {
userGroup = "sp.vikunja.users";
};
outputs =
{ nixpkgs-24-11, ... }:
{
nixosModules.default = import ./module.nix nixpkgs-24-11.legacyPackages.x86_64-linux;
configPathsNeeded = builtins.fromJSON (builtins.readFile ./config-paths-needed.json);
meta =
{ lib, ... }:
{
spModuleSchemaVersion = 1;
id = "vikunja";
name = "Vikunja";
description = "Vikunja, the fluffy, open-source, self-hostable to-do app.";
svgIcon = builtins.readFile ./icon.svg;
isMovable = true;
isRequired = false;
backupDescription = "Tasks and attachments.";
systemdServices = [
"vikunja.service"
];
folders = [
"/var/lib/vikunja"
];
postgreDatabases = [
"vikunja"
];
license = [
lib.licenses.agpl3Plus
];
homepage = "https://vikunja.io";
sourcePage = "https://github.com/go-vikunja/vikunja";
supportLevel = "normal";
sso = {
userGroup = "sp.vikunja.users";
};
};
};
};
}

View File

@@ -1,8 +1,10 @@
latestPkgs: {
latestPkgs:
{
config,
lib,
...
}: let
}:
let
sp = config.selfprivacy;
cfg = sp.modules.vikunja;
oauthClientID = "vikunja";
@@ -13,18 +15,16 @@ latestPkgs: {
# SelfPrivacy uses SP Module ID to identify the group!
usersGroup = "sp.vikunja.users";
oauthClientSecretFP =
auth-passthru.mkOAuth2ClientSecretFP oauthClientID;
oauthClientSecretFP = auth-passthru.mkOAuth2ClientSecretFP oauthClientID;
vikunjaPackage = latestPkgs.vikunja.overrideAttrs (old: {
doCheck = false; # Tests are slow.
patches =
(old.patches or [])
++ [
./load-client-secret-from-env.patch
];
patches = (old.patches or [ ]) ++ [
./load-client-secret-from-env.patch
];
});
in {
in
{
options.selfprivacy.modules.vikunja = {
enable =
(lib.mkOption {
@@ -63,157 +63,168 @@ in {
};
};
config =
lib.mkIf cfg.enable
{
assertions = [
{
assertion = sp.sso.enable;
message = "Vikunja cannot be enabled when SSO is disabled.";
}
];
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = sp.sso.enable;
message = "Vikunja cannot be enabled when SSO is disabled.";
}
];
fileSystems = lib.mkIf sp.useBinds {
"/var/lib/vikunja" = {
device = "/volumes/${cfg.location}/vikunja";
options = ["bind"];
};
};
users = {
users.vikunja = {
isSystemUser = true;
group = "vikunja";
};
groups.vikunja = {};
};
services.postgresql = {
ensureDatabases = ["vikunja"];
ensureUsers = [
{
name = "vikunja";
ensureDBOwnership = true;
}
];
};
services.vikunja = {
enable = true;
package = vikunjaPackage;
frontendScheme = "https";
frontendHostname = "${cfg.subdomain}.${sp.domain}";
port = 4835;
database = {
type = "postgres";
host = "/run/postgresql";
};
settings = {
service = {
enableregistration = false;
enabletotp = false;
enableuserdeletion = true;
};
auth = {
local.enabled = false;
openid = {
enabled = true;
providers = [
{
name = oauth2-provider-name;
authurl = lib.strings.removeSuffix "/.well-known/openid-configuration" oauthDiscoveryURL;
clientid = oauthClientID;
clientsecret = ""; # There's patch for our Vikunja to make it load client secret from environment variable.
scope = "openid profile email";
}
];
};
};
};
};
services.nginx.virtualHosts."${cfg.subdomain}.${sp.domain}" = {
useACMEHost = sp.domain;
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security $hsts_header;
#add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always;
add_header 'Referrer-Policy' 'origin-when-cross-origin';
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
'';
locations = {
"/" = {
proxyPass = "http://127.0.0.1:4835";
};
};
};
systemd = {
services.vikunja = {
unitConfig.RequiresMountsFor = lib.mkIf sp.useBinds "/volumes/${cfg.location}/vikunja";
serviceConfig = {
Slice = "vikunja.slice";
LoadCredential = "oauth2-secret:${oauthClientSecretFP}";
DynamicUser = lib.mkForce false;
User = "vikunja";
Group = "vikunja";
AmbientCapabilities = [""];
LockPersonality = true;
MemoryDenyWriteExecute = true;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateTmp = true;
PrivateUsers = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "strict";
RestrictAddressFamilies = ["AF_UNIX" "AF_INET" "AF_INET6"];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
RemoveIPC = true;
SystemCallFilter = ["@system-service" "~@cpu-emulation" "~@debug" "~@keyring" "~@memlock" "~@obsolete" "~@privileged" "~@setuid"];
};
environment.SP_VIKUNJA_CLIENT_SECRET_PATH = "%d/oauth2-secret";
};
slices.vikunja = {
description = "Vikunja service slice";
};
};
selfprivacy.auth.clients.${oauthClientID} = {
inherit usersGroup;
subdomain = cfg.subdomain;
isTokenNeeded = false;
originLanding = "https://${cfg.subdomain}.${sp.domain}/";
originUrl = "https://${cfg.subdomain}.${sp.domain}/auth/openid/${lib.strings.toLower oauth2-provider-name}";
clientSystemdUnits = ["vikunja.service"];
enablePkce = false;
linuxUserOfClient = "vikunja";
linuxGroupOfClient = "vikunja";
fileSystems = lib.mkIf sp.useBinds {
"/var/lib/vikunja" = {
device = "/volumes/${cfg.location}/vikunja";
options = [ "bind" ];
};
};
users = {
users.vikunja = {
isSystemUser = true;
group = "vikunja";
};
groups.vikunja = { };
};
services.postgresql = {
ensureDatabases = [ "vikunja" ];
ensureUsers = [
{
name = "vikunja";
ensureDBOwnership = true;
}
];
};
services.vikunja = {
enable = true;
package = vikunjaPackage;
frontendScheme = "https";
frontendHostname = "${cfg.subdomain}.${sp.domain}";
port = 4835;
database = {
type = "postgres";
host = "/run/postgresql";
};
settings = {
service = {
enableregistration = false;
enabletotp = false;
enableuserdeletion = true;
};
auth = {
local.enabled = false;
openid = {
enabled = true;
providers = [
{
name = oauth2-provider-name;
authurl = lib.strings.removeSuffix "/.well-known/openid-configuration" oauthDiscoveryURL;
clientid = oauthClientID;
clientsecret = ""; # There's patch for our Vikunja to make it load client secret from environment variable.
scope = "openid profile email";
}
];
};
};
};
};
services.nginx.virtualHosts."${cfg.subdomain}.${sp.domain}" = {
useACMEHost = sp.domain;
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security $hsts_header;
#add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always;
add_header 'Referrer-Policy' 'origin-when-cross-origin';
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
'';
locations = {
"/" = {
proxyPass = "http://127.0.0.1:4835";
};
};
};
systemd = {
services.vikunja = {
unitConfig.RequiresMountsFor = lib.mkIf sp.useBinds "/volumes/${cfg.location}/vikunja";
serviceConfig = {
Slice = "vikunja.slice";
LoadCredential = "oauth2-secret:${oauthClientSecretFP}";
DynamicUser = lib.mkForce false;
User = "vikunja";
Group = "vikunja";
AmbientCapabilities = [ "" ];
LockPersonality = true;
MemoryDenyWriteExecute = true;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateTmp = true;
PrivateUsers = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "strict";
RestrictAddressFamilies = [
"AF_UNIX"
"AF_INET"
"AF_INET6"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
RemoveIPC = true;
SystemCallFilter = [
"@system-service"
"~@cpu-emulation"
"~@debug"
"~@keyring"
"~@memlock"
"~@obsolete"
"~@privileged"
"~@setuid"
];
};
environment.SP_VIKUNJA_CLIENT_SECRET_PATH = "%d/oauth2-secret";
};
slices.vikunja = {
description = "Vikunja service slice";
};
};
selfprivacy.auth.clients.${oauthClientID} = {
inherit usersGroup;
subdomain = cfg.subdomain;
isTokenNeeded = false;
originLanding = "https://${cfg.subdomain}.${sp.domain}/";
originUrl = "https://${cfg.subdomain}.${sp.domain}/auth/openid/${lib.strings.toLower oauth2-provider-name}";
clientSystemdUnits = [ "vikunja.service" ];
enablePkce = false;
linuxUserOfClient = "vikunja";
linuxGroupOfClient = "vikunja";
};
};
}