My Nix Configuration

[marvin.services] planka: use native instead of docker

+97 -32
+97 -32
hosts/marvin/services/planka.nix
··· 1 1 { 2 + lib, 2 3 config, 3 4 self, 5 + self', 6 + pkgs, 4 7 ... 5 8 }: 6 9 let 7 - dataDir = "/var/lib/planka"; 8 10 d = self.lib.data.services.planka; 11 + 12 + commonServiceConfig = { 13 + EnvironmentFile = config.age.secrets.planka-env.path; 14 + StateDirectory = "planka"; 15 + WorkingDirectory = "/var/lib/planka"; 16 + User = "planka"; 17 + Group = "planka"; 18 + 19 + # Hardening 20 + LockPersonality = true; 21 + NoNewPrivileges = true; 22 + PrivateDevices = true; 23 + PrivateMounts = true; 24 + PrivateTmp = true; 25 + PrivateUsers = true; 26 + ProtectClock = true; 27 + ProtectControlGroups = true; 28 + ProtectHome = true; 29 + ProtectHostname = true; 30 + ProtectKernelLogs = true; 31 + ProtectKernelModules = true; 32 + ProtectKernelTunables = true; 33 + ProtectProc = "invisible"; 34 + RemoveIPC = true; 35 + RestrictRealtime = true; 36 + RestrictSUIDSGID = true; 37 + UMask = "0660"; 38 + RestrictAddressFamilies = [ 39 + "AF_UNIX" 40 + "AF_INET" 41 + "AF_INET6" 42 + ]; 43 + }; 9 44 in 10 45 { 11 - virtualisation.oci-containers.containers = { 12 - planka-server = { 13 - image = "ghcr.io/plankanban/planka:2.0.0-rc.4"; 14 - ports = [ "${toString d.port}:1337" ]; 15 - environment = { 16 - BASE_URL = "https://${d.extUrl}"; 17 - DATABASE_URL = "postgresql://planka@planka-db/planka"; 18 - # Default Admin 19 - DEFAULT_ADMIN_EMAIL = "pyrox@pyrox.dev"; 20 - DEFAULT_ADMIN_USERNAME = "pyrox"; 21 - TRUST_PROXY = "true"; 22 - DEFAULT_LANGUAGE = "en-US"; 46 + systemd = { 47 + tmpfiles.settings = { 48 + "10-planka"."/var/lib/planka".d = { 49 + group = "planka"; 50 + user = "planka"; 51 + mode = "0755"; 23 52 }; 24 - environmentFiles = [ config.age.secrets.planka-env.path ]; 25 - volumes = [ 26 - "${dataDir}/user-avatars:/app/public/user-avatars" 27 - "${dataDir}/project-background-images:/app/public/project-background-images" 28 - "${dataDir}/attachments:/app/private/attachments" 29 - "${dataDir}/favicons:/app/public/favicons" 30 - "${dataDir}/background-images:/app/public/background-images" 31 - ]; 32 - extraOptions = [ "--network=planka" ]; 33 53 }; 34 - planka-db = { 35 - image = "postgres:16-alpine"; 36 - volumes = [ "${dataDir}/db:/var/lib/postgresql/data" ]; 37 - environment = { 38 - POSTGRES_USER = "planka"; 39 - POSTGRES_DB = "planka"; 40 - POSTGRES_HOST_AUTH_METHOD = "trust"; 54 + services = { 55 + planka-init-db = { 56 + wantedBy = [ "multi-user.target" ]; 57 + after = [ "postgres.target" ]; 58 + description = "Planka Kanban Database Init Script"; 59 + path = [ 60 + pkgs.nodejs 61 + ]; 62 + script = '' 63 + if [ ! -f /var/lib/planka/db-init-ran ]; then 64 + node run ${self'.packages.planka}/lib/node_modules/planka/db/init.js && \ 65 + touch /var/lib/planka/db-init-ran 66 + fi 67 + ''; 68 + serviceConfig = commonServiceConfig // { 69 + Type = "oneshot"; 70 + SyslogIdentifier = "planka-init-db"; 71 + }; 41 72 }; 42 - extraOptions = [ "--network=planka" ]; 73 + planka-server = { 74 + after = [ "planka-init-db.service" ]; 75 + wantedBy = [ "multi-user.target" ]; 76 + description = "Planka Kanban Server"; 77 + documentation = [ "https://docs.planka.cloud" ]; 78 + environment = { 79 + DATABASE_URL = "postgresql://%2Frun%2Fpostgresql/planka"; 80 + DEFAULT_ADMIN_EMAIL = "pyrox@pyrox.dev"; 81 + DEFAULT_ADMIN_USERNAME = "pyrox"; 82 + TRUST_PROXY = "true"; 83 + DEFAULT_LANGUAGE = "en-US"; 84 + BASE_URL = "https://${d.extUrl}"; 85 + NODE_ENV = "production"; 86 + }; 87 + serviceConfig = commonServiceConfig // { 88 + Type = "simple"; 89 + ExecStart = "${lib.getExe self'.packages.planka} --port ${toString d.port}"; 90 + SyslogIdentifier = "planka"; 91 + }; 92 + }; 43 93 }; 44 94 }; 95 + users.users.planka = { 96 + isSystemUser = true; 97 + group = "planka"; 98 + }; 99 + users.groups.planka = { }; 100 + services.postgresql = { 101 + ensureUsers = [ 102 + { 103 + name = "planka"; 104 + ensureDBOwnership = true; 105 + ensureClauses.login = true; 106 + } 107 + ]; 108 + ensureDatabases = [ "planka" ]; 109 + }; 45 110 age.secrets.planka-env = { 46 111 file = ./secrets/planka-env.age; 47 - owner = "thehedgehog"; 48 - group = "misc"; 112 + owner = "planka"; 113 + group = "planka"; 49 114 }; 50 115 services.anubis.instances.planka = { 51 116 settings = {