{ myLib, ... }: let # TODO: make module of this. tailscaleSecretName = "tailscale-auth"; inbucketSAName = "inbucket"; in { kubernetes.resources = { secrets.${tailscaleSecretName}.stringData.TS_AUTHKEY = "ref+sops://secrets/kubernetes.yaml#/tailscale/authKey"; roles.tailscale.rules = [ { apiGroups = [ "" ]; resources = [ "secrets" ]; verbs = [ "create" ]; } { apiGroups = [ "" ]; resourceNames = [ tailscaleSecretName ]; resources = [ "secrets" ]; verbs = [ "get" "update" "patch" ]; } ]; roleBindings.inbucket-tailscale = { subjects = [{ kind = "ServiceAccount"; name = inbucketSAName; }]; roleRef = { kind = "Role"; name = "tailscale"; apiGroup = "rbac.authorization.k8s.io"; }; }; serviceAccounts.${inbucketSAName} = { }; deployments.inbucket.spec = { selector.matchLabels.app = "inbucket"; template = { metadata.labels.app = "inbucket"; spec = { serviceAccountName = inbucketSAName; containers = { inbucket = { image = "inbucket/inbucket:edge"; env.INBUCKET_WEB_ADDR.value = "0.0.0.0:80"; ports = { web.containerPort = 80; smtp.containerPort = 2500; }; }; tailscale-sidecar = { imagePullPolicy = "Always"; image = "ghcr.io/tailscale/tailscale:latest"; env = { TS_HOSTNAME.value = "inbucket"; TS_KUBE_SECRET.value = tailscaleSecretName; TS_USERSPACE.value = "false"; TS_DEBUG_FIREWALL_MODE.value = "auto"; TS_AUTHKEY.valueFrom.secretKeyRef = { name = tailscaleSecretName; key = "TS_AUTHKEY"; optional = true; }; }; securityContext.capabilities.add = [ "NET_ADMIN" ]; }; }; }; }; }; services = { web.spec = { type = "LoadBalancer"; loadBalancerIP = myLib.globals.inbucketWebIPv4; selector.app = "inbucket"; ports.web = { port = 80; targetPort = "web"; }; }; email.spec = { type = "LoadBalancer"; loadBalancerIP = myLib.globals.inbucketEmailIPv4; selector.app = "inbucket"; ports = [{ port = 25; targetPort = "smtp"; }]; }; }; }; }