From d241321971ecfe569eed65ac76d08fcf176b2be9 Mon Sep 17 00:00:00 2001 From: Danny Grove Date: Sun, 13 Jul 2025 20:01:05 -0700 Subject: [PATCH] radicale: initial commit --- kustomizations/radicale/README.md | 13 +++ kustomizations/radicale/files/config | 13 +++ kustomizations/radicale/ingress.yaml | 28 +++++ kustomizations/radicale/kustomization.yaml | 21 ++++ kustomizations/radicale/secret-generator.yaml | 6 + kustomizations/radicale/service.yaml | 11 ++ kustomizations/radicale/serviceaccount.yaml | 5 + kustomizations/radicale/statefulset.yaml | 69 ++++++++++++ kustomizations/radicale/users.enc.yaml | 103 ++++++++++++++++++ 9 files changed, 269 insertions(+) create mode 100644 kustomizations/radicale/README.md create mode 100644 kustomizations/radicale/files/config create mode 100644 kustomizations/radicale/ingress.yaml create mode 100644 kustomizations/radicale/kustomization.yaml create mode 100644 kustomizations/radicale/secret-generator.yaml create mode 100644 kustomizations/radicale/service.yaml create mode 100644 kustomizations/radicale/serviceaccount.yaml create mode 100644 kustomizations/radicale/statefulset.yaml create mode 100644 kustomizations/radicale/users.enc.yaml diff --git a/kustomizations/radicale/README.md b/kustomizations/radicale/README.md new file mode 100644 index 0000000..d6cf228 --- /dev/null +++ b/kustomizations/radicale/README.md @@ -0,0 +1,13 @@ +# Radicale + +## Creating an account + +Currently to create a radicale account you will need to generate and hash a password with `htpasswd` and `bcrypt`. + +You can generate your password using a password manager or `openssl` with at least 32 characters. + +```sh +htpasswd -Bn @distrust.co +``` + +You will then need to add the output to users.enc.yaml which is encrypted with SOPS diff --git a/kustomizations/radicale/files/config b/kustomizations/radicale/files/config new file mode 100644 index 0000000..f3dae5f --- /dev/null +++ b/kustomizations/radicale/files/config @@ -0,0 +1,13 @@ +[server] +hosts = 0.0.0.0:5232 + +[auth] +type = htpasswd +htpasswd_filename = /config/user +htpasswd_encryption = bcrypt + +[rights] +type = owner_only + +[storage] +filesystem_folder = /var/lib/radicale/collections diff --git a/kustomizations/radicale/ingress.yaml b/kustomizations/radicale/ingress.yaml new file mode 100644 index 0000000..9b9d800 --- /dev/null +++ b/kustomizations/radicale/ingress.yaml @@ -0,0 +1,28 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: radicale-ingress + annotations: + nginx.ingress.kubernetes.io/ssl-redirect: "true" + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + cert-manager.io/cluster-issuer: letsencrypt + external-dns.alpha.kubernetes.io/hostname: radicale.distrust.co + nginx.ingress.kubernetes.io/proxy-buffer-size: "16k" + nginx.ingress.kubernetes.io/proxy-buffers-number: "8" +spec: + ingressClassName: nginx + tls: + - hosts: + - radicale.distrust.co + secretName: radicale-tls + rules: + - host: radicale.distrust.co + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: radicale + port: + number: 5232 diff --git a/kustomizations/radicale/kustomization.yaml b/kustomizations/radicale/kustomization.yaml new file mode 100644 index 0000000..97f82a4 --- /dev/null +++ b/kustomizations/radicale/kustomization.yaml @@ -0,0 +1,21 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +labels: + - pairs: + app.kubernetes.io/name: radicale + includeSelectors: true +resources: +- ./statefulset.yaml +- ./service.yaml +- ./serviceaccount.yaml +- ./ingress.yaml +enerators: +- secret-generator.yaml +configMapGenerator: + - name: radicale + files: + - config=files/config +images: + - name: radicale + newName: drgrovellc/radicale + digest: sha256:055e686577ec543b33ff905b09f798a3a178393c14799a85867d86519a8d0a35 diff --git a/kustomizations/radicale/secret-generator.yaml b/kustomizations/radicale/secret-generator.yaml new file mode 100644 index 0000000..df6261d --- /dev/null +++ b/kustomizations/radicale/secret-generator.yaml @@ -0,0 +1,6 @@ +apiVersion: viaduct.ai/v1 +kind: ksops +metadata: + name: radicale-secrets +files: + - ./users.enc.yaml diff --git a/kustomizations/radicale/service.yaml b/kustomizations/radicale/service.yaml new file mode 100644 index 0000000..ed469f3 --- /dev/null +++ b/kustomizations/radicale/service.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: radicale +spec: + type: ClusterIP + ports: + - port: 5232 + targetPort: http + protocol: TCP + name: http diff --git a/kustomizations/radicale/serviceaccount.yaml b/kustomizations/radicale/serviceaccount.yaml new file mode 100644 index 0000000..6bb69e3 --- /dev/null +++ b/kustomizations/radicale/serviceaccount.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: radicale +automountServiceAccountToken: true diff --git a/kustomizations/radicale/statefulset.yaml b/kustomizations/radicale/statefulset.yaml new file mode 100644 index 0000000..d3e8b15 --- /dev/null +++ b/kustomizations/radicale/statefulset.yaml @@ -0,0 +1,69 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: radicale +spec: + template: + spec: + serviceAccountName: radicale + securityContext: + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 1000 + containers: + - name: radicale + image: radicale + env: + - name: RADICALE_CONFIG + value: /config/config + ports: + - name: http + containerPort: 5232 + protocol: TCP + livenessProbe: + httpGet: + path: / + port: http + readinessProbe: + httpGet: + path: / + port: http + securityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + seccompProfile: + type: "RuntimeDefault" + capabilities: + drop: + - ALL + volumeMounts: + - name: config + mountPath: /config/config + subPath: config + - name: user + mountPath: /config/user + subPath: users + - name: radicale + mountPath: /var/lib/radicale + volumes: + - name: config + configMap: + name: radicale + items: + - key: config + path: config + - name: user + secret: + optional: true + secretName: radicale-users + items: + - key: users + path: users + volumeClaimTemplates: + - metadata: + name: radicale + spec: + accessModes: [ "ReadWriteOnce" ] + resources: + requests: + storage: 5Gi diff --git a/kustomizations/radicale/users.enc.yaml b/kustomizations/radicale/users.enc.yaml new file mode 100644 index 0000000..96a29da --- /dev/null +++ b/kustomizations/radicale/users.enc.yaml @@ -0,0 +1,103 @@ +data: ENC[AES256_GCM,data:6uHlO1HW3qJXmwoCkAtvlmVj10NTSzblkYrgT6+OjcY64b7+AAZZtefwNjXvTQ8fDXbbrGAK2SK5Rlbcy08W6Rl/JDKAiomSqmrSfXpszEdumkdciODm2wOosTC6EjRudPpnfliqowisAszNTanH7mocsOClqww6XVAMmtzHKbjzYUeg4Iyz5MOCIrtNHxiA/Eb0UGvtGhbuqgci/zSly6bvzV2eMZl9XtDn1fhKM5IMqFwt5OpSIfOG,iv:Ew42raYQoumx9KQWzlLnBf/75RdwbBXKnoSfEVA38y8=,tag:lRDMH+eRGhfKAQNEsI6HFg==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2025-07-13T19:45:29Z" + mac: ENC[AES256_GCM,data:6MBapMxTVHBUxGFZdoS8pc682CAzqH49s/m/gl1n94tUc5S3x7YLcB29Ebmj4g5yLCqWLmc7bYbvlfviNrE8WZAKVEQhWd16J4Sl91q2JUmlRDyMJjHzxZEEZaZ7Wc1fgVsbJw0kRTxYGSg+J5rreirYl0IllVh/yFNmy+36yIk=,iv:Bk2EkF4BwJM4oBebOeiUzKExvthvEsLhUdR6iLsEDlk=,tag:+6Skc/pm8t+lXwacO5vG/w==,type:str] + pgp: + - created_at: "2025-07-13T06:51:55Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA82rPM2mSf/aARAAjtuwpAk5OCIRUXTwig8V+Md3mzZ5B/mXaEipSL+bz8aK + Nro9p82GsnMIgHS7qpMwcc53NSNL0wmju3tcB/TaFsRVot1QTcIraPP2saDx02Mm + wKg0pcqDk55X+htHY1iYZS9JO1bVz7EmJjPsfcEdvBm2JNCjZeNToy7mnjFWBBlu + OqX0V2qrWcm3lG2HMBUGOHQ8o3iC7OWBTIKSDMx8dJb7L4NlB3LxtfsibmsrvOk1 + AtUXKf6DjjRcRV3LiVFFhswPfbUx9uYrNLQM3g2J5jxyoWHVCLdVqsBGe03zxmlA + iAglRbYNbhayoWH/1j/10VbtEuRSURKtCPWysaOr+u/UOWpbRi0S3WTkx2E603wC + k2msofhS8iQv8Dp2Y5zcdFvLnWpCzdXFWPedLE08fKKHkht40Pdh8rq09Y8eepAT + HUvuaJSfG1/RZX3IRoyHTyFmVrRF1ZEPDxcMKD8Kx3Vn7dfXVO3Bxx7dBTyY4UzO + Vzx8KJBulCib2jDY0CqBNL50Kgy935rHhBRUlx4MBxhSKnkKHIiXYalINZUxHUxn + YzztQbxLnOgb94z2dEPEu6xxgSLC40XNY65SzwtEKHkR7QNkyRqm1VXbT6tEpYRg + VgDKZgBWLQ68G+DDkDbUCkGy4w3umMSfuX8rlNEUG9C0Kk5CXffyKqA8J3+T97bS + XAGZYbFMTTgpa1Z/vnmAfsr/CUvAUflkgtvJH7wxXVL41a/12IQ/kx1mxMxh3JjS + 0R2phlMwSy5ct1scgJQZIc+fvgjMthNl1b5XqnWE0eRwVduKpi3/uzCZhzXd + =tMGM + -----END PGP MESSAGE----- + fp: 6B61ECD76088748C70590D55E90A401336C8AAA9 + - created_at: "2025-07-13T06:51:55Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAw95Vf08z8oUARAAzSCXQxhGwwO1cQjgpy539UqhS/3SDqB2c2fAm8rvKMEq + E8dtU5/Oc5FRhRRWEIP9XeDJlPz9rDn4E3KYa0ZYNUchl75ItHID6oBg3OOSZmIN + ciVaffQXyRa6pRCjeaQU9VZY67FBbCueBbCe/mYyGZQMfHg4Y2asOIr3qOgYIgnC + sAZoG2NT+9deabzLY8irLTAM5IMbO59ulM0H7j0IdTLB9D7u+fU7EMg9jQb/J9ha + IITSh7jGhpNbtJ0neRyUnX26r50JeLY4b1UCAd1HjA5Rycgrx1rXoZbmGB4dFZ0V + ZiIaGBe/8BF5GGXkHJgO/Y5g+jfpmO6HYV5NrCB049nd82YowK9LkgMNp3V1vPn6 + 5RxWsVSV29CyplO6rEq9lH2VHB1HLkboOomklVDyG9mo+jbY3TL/Ak4nWfx+96rV + JSyAadEtC+HcXN5ECDO+F7uAEDi0isdWF97xgARvjyDezEEyxTA8xWsIpL8LRWjZ + IBlihxlpyQJ13WSFP6tAp60wO83LLJiC9rvuIBmrCUwKb+LtxUqrWtZnZ8yIsCXk + V1xqGixSigR3RJvbSzICKdMDuhs+cghiurTkKNE2QG9+NQeees2DUIqURjRM//Av + 6hEJxjH/bJ2JlA1/YIkYkMxc9WpKRXmitVaHpkoFumphVIfA4CbQZo/Nv2LbatDS + XAHAUl75H53Hf3awGph4kOoykimetr8i14bVM0Kr/jdAxcvJkanScej2huzTHzQK + ywl3clswBKzhfCBFejdhrrZoKsT1h7Mf23FEwhwP4aMcVZe+iSqoifWXKRM5 + =jFLv + -----END PGP MESSAGE----- + fp: 88823A75ECAA786B0FF38B148E401478A3FBEF72 + - created_at: "2025-07-13T06:51:55Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4Dr/MjkOzuuRESAQdAEpot/CyllATM3Ycyb5dvalqAbJBHskFKLR7nbFc6Z2kw + R2XDTbHQ51WSv7teBei+gA9elRjrsx5RfUSh/mC/WrOZvnn4NyHf6cDkjtd3EO1I + 0lwBT732FGcKQEE7CZXoc/AwtCd66OYqwdYiiMm29LuVcW71UlrGkLFPyqQ+y2jb + Fl00rVXjHLLXFzcEfZf5+JFoPv3JM+h8nXQZEkpKI6Ykw9ZcxagoZyyySYdqtw== + =ZP5M + -----END PGP MESSAGE----- + fp: 3D7C8D39E8C4DF771583D3F0A8A091FD346001CA + - created_at: "2025-07-13T06:51:55Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA5Wf+FyJ+zFJAQ/7BIqCa7lsEE4tyhxoiA6DBO9/+xP4LlA/CPPCu4zWLb2T + zy0axtIWtdSAWecWXm0vQ9B+YB0Jbhb69Qj1mrjCgGyM8ckduBxvYlT1qbGREJCW + CtFqiAvWcDAsKZ3BOxA4GsqU4aGK9KMOZCcFGQx9Bg8CFpOx7gbMFb+VkziA/Dgx + FGvBmNvtqqdqV7yViUxvYAwb7Buik8e77FCyBc5fxdjGU34/x7AD0jPJcN3Ac0n0 + zqGBaM9ivs3G2R4rq2JVfWOdj/qmrH/P0CWDN8cOB7H37+IpvIjs80RIjguB4OFo + HxJFviuQ9LGpw8IKj2161iSccuAwhOpHdOLS8C6yzw7SJZncwCDeLlQWVhJb99ae + Tq23m68KYTkpM6cIT5iG4k/grgkKvqk82YNkMCktPBwsEQ/wxOH9ZQ9Ry1LRtmIF + BUH33sASnt3A3IAavYQucAcOkYsQJFlaLbeVoVS8J7nXA6xRzv9qaJeeulVIaBpc + fwSP6mI8mscrSp24F14EcP3n5W6Gr68oEw2qdUi3CFLtr+Ih8T2REWzOJYDIArCM + cY/tS1WVDDikmzS9aNcEt0okPz6HNaKu7qONby3L9XxSDxZYg4tmV/ZiWIZuvVwL + 6iipL+wYMYk3ot066ewoLqOeZcZH/04P9QgoNwnUaSqsfaIQfPJZCngyCEKdYNXS + XAGIFLlG48rAKmE7OYuOFQeuwgNpdFb07kaWw64NKTRxTkw0hZjm87CHfdZ3CPnX + Jp04LP46X74s+SiWmfHM5W21Ub68Li4l135DA3CKiOn+Sq04Q5xh0giSZWHG + =ikQP + -----END PGP MESSAGE----- + fp: F4BF5C81EC78A5DD341C91EEDC4B7D1F52E0BA4D + - created_at: "2025-07-13T06:51:55Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA8KRInHl7Vz+AQ//blhfF6tdUKH+4HWC2p0hhCBwzZ/eGcDBvk66N4Yvo7w5 + k38fd/kI0EqKecagLNlScnS8mRwhjAaKwUGUjyWYQ5CkVEtb+SG2fAnEU57ju3xV + ei5P1lBfkcKPR5uSC9vXO/oCg7XHN9fAi67yh1paBhN7azjplm8BGunhFD7PzULO + b+g9xa1ueC2c4UpLd4rf55Us10tFJ/Id3QK5FhbB1L+Mae+Wjs0sxRN2qPmkiAvu + ilaPw7PfnztNs3bj6/pzyH1EdaeRIiZzoC+0e9LiA6bBkj4tSfAWEHH84uFYDv98 + gfSe5Lp5DEpoZSy2ecx3XOtCPSKGv8FfeVfwb4EZ/EyYRJDEkOAkEDPIlQs9agy0 + FYOiovwAjVAU2Y/IC5q0lVH4WQZGY/k+EVeu9ZAMHkZ1/TDIxva/WsMM91ja5uWC + LMRUXJ1TO/LjNI1T9XI20bKkl2WOj0Y/1YVOoJAxTbnkXzsn1xU7Qe7DiehYKl+d + OE+dNjN/D4DR5NmEfTPmsNEX6Z3sK1GyEOxw19/JM3QHIdjoKw3a15hQjxmM/ksH + KNEu0YQ/l7CDDnVT7MLDpjx1luoMQ9eW3I3hMAZgxkjkmTk2xeNYTAvDLFmKk2D8 + 7MFogZB2o2giaBgFgWB+9KCgzipHSlnIQd//BSvwtL1/GFILSPzLEfOWAXv2zE7S + XAHdCNhyj7n7zQDwDb5V84QxbUne/D22RY4NpJybMfrXuKW9n2fOD4wxiWZnl6hD + ieC1qFcETi20i2LzC2M3uJAz/LHVpyLaNNaaIDMZF3gme1yKe3/u46z1WJhX + =LEyb + -----END PGP MESSAGE----- + fp: C92FE5A3FBD58DD3EC5AA26BB10116B8193F2DBD + unencrypted_suffix: _unencrypted + version: 3.8.1 -- 2.40.1