{ config, lib, globals, ... }: { options.radicale.enable = lib.mkEnableOption "radicale"; config = lib.mkIf config.radicale.enable { kubernetes.resources = { configMaps.server.data = { users = "pim:$apr1$GUiTihkS$dDCkaUxFx/O86m6NCy/yQ."; config = lib.generators.toINI {} { server = { hosts = "0.0.0.0:5232, [::]:5232"; ssl = false; }; encoding = { request = "utf-8"; stock = "utf-8"; }; auth = { realm = "Radicale - Password Required"; type = "htpasswd"; htpasswd_filename = "/config/users"; htpasswd_encryption = "md5"; }; rights.type = "owner_only"; storage = { type = "multifilesystem"; filesystem_folder = "/data"; }; logging = {}; headers = {}; }; }; deployments.server.spec = { selector.matchLabels.app = "radicale"; strategy = { type = "RollingUpdate"; rollingUpdate = { maxSurge = 0; maxUnavailable = 1; }; }; template = { metadata.labels.app = "radicale"; spec = { containers.radicale = { image = globals.images.radicale; ports.web.containerPort = 5232; imagePullPolicy = "IfNotPresent"; volumeMounts = [ { name = "data"; mountPath = "/data"; } { name = "config"; mountPath = "/config/config"; subPath = "config"; } { name = "config"; mountPath = "/config/users"; subPath = "users"; } ]; }; volumes = { data.persistentVolumeClaim.claimName = "data"; config.configMap.name = "server"; }; securityContext = { fsGroup = 2999; fsGroupChangePolicy = "OnRootMismatch"; }; }; }; }; services.server.spec = { type = "LoadBalancer"; loadBalancerIP = globals.radicaleIPv4; selector.app = "radicale"; ports.web = { port = 80; targetPort = "web"; }; }; }; lab = { tailscaleIngresses.tailscale = { host = "radicale"; service.name = "server"; }; longhorn.persistentVolumeClaim.data = { volumeName = "radicale"; storage = "200Mi"; }; }; }; }