diff --git a/README.md b/README.md
index db130f1..ecbfd92 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,8 @@
-# radicale
\ No newline at end of file
+# radicale
+
+[](https://drone.theautomation.nl/theautomation/radicale)
+
+
+
+
+Application running in Kubernetes
\ No newline at end of file
diff --git a/cicd/.prettierignore b/cicd/.prettierignore
new file mode 100644
index 0000000..e69de29
diff --git a/cicd/.prettierrc.yaml b/cicd/.prettierrc.yaml
new file mode 100644
index 0000000..00c36a1
--- /dev/null
+++ b/cicd/.prettierrc.yaml
@@ -0,0 +1,4 @@
+---
+printWidth: 88
+tabWidth: 2
+useTabs: true
diff --git a/cicd/.yamllint.yaml b/cicd/.yamllint.yaml
new file mode 100644
index 0000000..a415b3e
--- /dev/null
+++ b/cicd/.yamllint.yaml
@@ -0,0 +1,29 @@
+---
+rules:
+ braces: enable
+ brackets: enable
+ colons: enable
+ commas: enable
+ comments:
+ level: warning
+ comments-indentation:
+ level: warning
+ document-end: disable
+ document-start:
+ level: warning
+ empty-lines: enable
+ empty-values: disable
+ hyphens: enable
+ indentation: enable
+ key-duplicates: enable
+ key-ordering: disable
+ line-length:
+ level: warning
+ max: 88
+ new-line-at-end-of-file: enable
+ new-lines: enable
+ octal-values: disable
+ quoted-strings: disable
+ trailing-spaces: enable
+ truthy:
+ level: warning
diff --git a/cicd/pipeline.yaml b/cicd/pipeline.yaml
new file mode 100644
index 0000000..9e6a46d
--- /dev/null
+++ b/cicd/pipeline.yaml
@@ -0,0 +1,119 @@
+---
+kind: pipeline
+type: docker
+name: validate
+
+steps:
+ - name: prettier
+ image: tmknom/prettier:latest
+ commands:
+ - prettier --config "./cicd/.prettierrc.yaml" --ignore-path "./cicd/.prettierignore" --check "./src/config/**/*.yaml"
+
+ - name: yamllint
+ image: sdesbure/yamllint:latest
+ commands:
+ - yamllint -c ./cicd/.yamllint.yaml .
+
+---
+kind: pipeline
+type: docker
+name: build
+
+depends_on:
+ - validate
+
+steps:
+ - name: build and push image
+ image: quay.io/buildah/stable
+ privileged: true
+ network_mode: host
+ environment:
+ REGISTRY_HOST: "harbor.k8s.lan/k8s"
+ CONTAINERFILE: "./deploy/container/Containerfile"
+ STORAGE_DRIVER: "overlay"
+ FORMAT: "docker"
+ CONTEXT: "."
+ TLSVERIFY: "false"
+ USERNAME: "robot-drone-ci"
+ PASSWORD:
+ from_secret: harbor_registry_drone_password
+ commands:
+ - |
+ echo "Build image..."
+ buildah --storage-driver=$${STORAGE_DRIVER} bud --format=$${FORMAT} \
+ --tls-verify=$${TLSVERIFY} -f $${CONTAINERFILE} \
+ -t $${REGISTRY_HOST}/$${DRONE_REPO_NAME}:latest \
+ -t $${REGISTRY_HOST}/$${DRONE_REPO_NAME}:$${DRONE_BUILD_NUMBER} \
+ - |
+ echo "Push image with latest tag..."
+ buildah push --creds=$${USERNAME}:$${PASSWORD} \
+ --tls-verify=$${TLSVERIFY} \
+ $${REGISTRY_HOST}/$${DRONE_REPO_NAME}:latest \
+ docker://$${REGISTRY_HOST}/$${DRONE_REPO_NAME}:latest
+ - |
+ echo "Push image with buildnumber tag..."
+ buildah push --creds=$${USERNAME}:$${PASSWORD} \
+ --tls-verify=$${TLSVERIFY} \
+ --digestfile=/tmp/image-digest \
+ $${REGISTRY_HOST}/$${DRONE_REPO_NAME}:$${DRONE_BUILD_NUMBER} \
+ docker://$${REGISTRY_HOST}/$${DRONE_REPO_NAME}:$${DRONE_BUILD_NUMBER}
+
+---
+kind: pipeline
+type: docker
+name: deploy
+
+depends_on:
+ - build
+
+steps:
+ - name: upgrade k8s manifest
+ image: alpine:3
+ network_mode: host
+ environment:
+ REGISTRY_NAME: "k8s"
+ commands:
+ - sed -i -e
+ "s%/$${REGISTRY_NAME}/$${DRONE_REPO_NAME}:.*%/$${REGISTRY_NAME}/$${DRONE_REPO_NAME}:$${DRONE_BUILD_NUMBER}\"%1"
+ ./deploy/k8s/manifest.yaml
+
+ - name: push k8s manifest
+ image: appleboy/drone-git-push
+ settings:
+ remote_name: "git@github.com:${DRONE_REPO}"
+ branch: ${DRONE_BRANCH}
+ force: false
+ commit: true
+ commit_message: "[bot] [skip ci] bump image tag"
+ author_name: ci-bot
+ ssh_key:
+ from_secret: github_ssh_key
+
+ - name: apply k8s manifest
+ image: bitnami/kubectl
+ volumes:
+ - name: kubeconfig
+ path: /.kube
+ network_mode: host
+ commands:
+ - cat ./deploy/k8s/manifest.yaml
+ - kubectl apply -f ./deploy/k8s/manifest.yaml
+
+volumes:
+ - name: kubeconfig
+ host:
+ path: /var/lib/.kube
+
+---
+kind: secret
+name: harbor_registry_drone_password
+get:
+ path: harbor-registry-drone-password
+ name: harbor-robot-password
+
+---
+kind: secret
+name: github_ssh_key
+get:
+ path: github-ssh-keys
+ name: id_rsa
diff --git a/deploy/container/Containerfile b/deploy/container/Containerfile
new file mode 100644
index 0000000..46a1700
--- /dev/null
+++ b/deploy/container/Containerfile
@@ -0,0 +1,61 @@
+FROM alpine:3.14
+
+ARG COMMIT_ID
+ENV COMMIT_ID ${COMMIT_ID}
+
+ARG VERSION
+ENV VERSION ${VERSION:-3.1.8}
+
+ARG BUILD_UID
+ENV BUILD_UID ${BUILD_UID:-1000}
+
+ARG BUILD_GID
+ENV BUILD_GID ${BUILD_GID:-1000}
+
+ARG TAKE_FILE_OWNERSHIP
+ENV TAKE_FILE_OWNERSHIP ${TAKE_FILE_OWNERSHIP:-true}
+
+LABEL maintainer="Thomas Queste " \
+ org.label-schema.name="Radicale Docker Image" \
+ org.label-schema.description="Enhanced Docker image for Radicale, the CalDAV/CardDAV server" \
+ org.label-schema.url="https://github.com/Kozea/Radicale" \
+ org.label-schema.version=$VERSION \
+ org.label-schema.vcs-ref=$COMMIT_ID \
+ org.label-schema.vcs-url="https://github.com/tomsquest/docker-radicale" \
+ org.label-schema.schema-version="1.0"
+
+RUN apk add --no-cache --virtual=build-dependencies \
+ gcc \
+ musl-dev \
+ libffi-dev \
+ python3-dev \
+ && apk add --no-cache \
+ curl \
+ git \
+ openssh \
+ shadow \
+ su-exec \
+ tzdata \
+ wget \
+ python3 \
+ py3-tz \
+ py3-pip \
+ && python3 -m pip install --upgrade pip \
+ && python3 -m pip install radicale==$VERSION passlib[bcrypt] \
+ && apk del --purge build-dependencies \
+ && addgroup -g $BUILD_GID radicale \
+ && adduser -D -s /bin/false -H -u $BUILD_UID -G radicale radicale \
+ && mkdir -p /config /data \
+ && chmod -R 770 /data \
+ && chown -R radicale:radicale /data \
+ && rm -fr /root/.cache
+
+COPY config /config/config
+
+HEALTHCHECK --interval=30s --retries=3 CMD curl --fail http://localhost:5232 || exit 1
+VOLUME /config /data
+EXPOSE 5232
+
+COPY docker-entrypoint.sh /usr/local/bin
+ENTRYPOINT ["docker-entrypoint.sh"]
+CMD ["radicale", "--config", "/config/config"]
\ No newline at end of file
diff --git a/deploy/k8s/manifest.yaml b/deploy/k8s/manifest.yaml
new file mode 100644
index 0000000..a0fa83b
--- /dev/null
+++ b/deploy/k8s/manifest.yaml
@@ -0,0 +1,181 @@
+---
+kind: PersistentVolume
+apiVersion: v1
+metadata:
+ name: pv-nfs-radicale-data
+ labels:
+ app: radicale
+spec:
+ storageClassName: "freenas-nfs-manual-csi"
+ capacity:
+ storage: 1Gi
+ accessModes:
+ - ReadWriteMany
+ persistentVolumeReclaimPolicy: Retain
+ mountOptions:
+ - nfsvers=4
+ - nolock
+ - noatime
+ csi:
+ driver: org.democratic-csi.node-manual
+ readOnly: false
+ fsType: nfs
+ volumeHandle: pv-nfs-radicale-data
+ volumeAttributes:
+ server: storage-server-lagg.lan
+ share: /mnt/r01_1tb/k8s/radicale-data/
+ node_attach_driver: nfs
+ provisioner_driver: node-manual
+
+---
+kind: PersistentVolumeClaim
+apiVersion: v1
+metadata:
+ name: pvc-nfs-radicale-data
+ namespace: tools
+ labels:
+ app: radicale
+ annotations:
+ volume.beta.kubernetes.io/storage-class: "freenas-nfs-manual-csi"
+spec:
+ storageClassName: freenas-nfs-manual-csi
+ accessModes:
+ - ReadWriteMany
+ resources:
+ requests:
+ storage: 1Gi
+ volumeName: pv-nfs-radicale-data
+
+---
+kind: SealedSecret
+apiVersion: bitnami.com/v1alpha1
+metadata:
+ name: radical-basic-auth
+ namespace: tools
+spec:
+ encryptedData:
+ auth: AgCgBfjCsDeQKfmp48MHe3w4CqdQ3bsC7fGGFRUa16S5OYkTD/xaJSAbj4832eYXrJIr+u9RcPOM4taFn/XaEbAVEritgIGFkb+QX1Awhm480OKv/EXv5eROo9tLFL+NrLUjdsSxRMy7BiOqWy6gArsqbjjxmz3obh6WWvTW/wyagTiNQYVSsKo4+6qEsGzMSrohGJJFdu7sA6LrYrZlv/iNMdOcW9ZUFbxzlcIb9SmHXNOPKfXTvXPxqzu7l1vyqqEeDQefF7okeF8QiNm8iYOTtmOqajbhYEuPBMARdxPOZ8gdQBjjPdBzYM6d2FTjLa+GU91z64ssSx8CW8JPAm4o1y1oSnO6Lk38Vdyuw2Dwi9A5lhisROI063tqt3PCA1BeoYQkZMHdHzvS0kZNhPSaBXW7QNyz8NYuVNsRY0dfa09+GPs5VUlxki78BmmgkCmzuAInN7wGfy6iU1kYXY8x6/q6aO0rC6FjwcSX+P6Uj29WU3waPlYAQWXn0+8JE3n1Q46IV6KSTX+jH89cQ7a1qjmLI4mBgJrf+MLflmVoNVUEqP7bTnkoO/5EkkWbIR0yvsUFAOq2gErHeHPyixdVenZ9K97tASeJuIAKNvoeZXvbkKRVrHgjnippzdI/SBD72v0rJtepe15hb5XsAs41D7TQFuCp8LWEBIdqqKUICqWF67sXkoK7VOe4EfqbSycwGLCYVsGfHWjdNi8CDeAlexa9xDakAUKnE7lDEd7t4PWMrflQ4znVU9cg5UAWNfzasg==
+ template:
+ metadata:
+ labels:
+ app: radicale
+ name: radicale-basic-auth
+ namespace: tools
+ type: Opaque
+
+---
+kind: ConfigMap
+apiVersion: v1
+metadata:
+ name: config
+ namespace: tools
+ labels:
+ app: radicale
+data:
+ config: |-
+ [server]
+ hosts = 0.0.0.0:5232
+ [auth]
+ type = http_x_remote_user
+ [storage]
+ filesystem_folder = /data/collections
+ [web]
+ type = none
+ [logging]
+ # Threshold for the logger
+ # Value: debug | info | warning | error | critical
+ level = debug
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: radicale
+ namespace: tools
+ labels:
+ app: radicale
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: radicale
+ template:
+ metadata:
+ labels:
+ app: radicale
+ spec:
+ securityContext:
+ fsGroup: 1000
+ containers:
+ - name: radicale
+ image: "harbor.k8s.lan/k8s/radicale:118"
+ resources: {}
+ securityContext:
+ runAsUser: 1000
+ runAsGroup: 1000
+ ports:
+ - containerPort: 5232
+ protocol: TCP
+ volumeMounts:
+ - name: collections
+ mountPath: /data/collections
+ - name: config
+ mountPath: /config/config
+ subPath: config
+ readOnly: true
+ volumes:
+ - name: config
+ configMap:
+ name: config
+ - name: collections
+ persistentVolumeClaim:
+ claimName: pvc-nfs-radicale-data
+ imagePullSecrets:
+ - name: harbor-registry-creds
+
+---
+kind: Service
+apiVersion: v1
+metadata:
+ name: radicale
+ namespace: tools
+ labels:
+ app: radicale
+spec:
+ selector:
+ app: radicale
+ type: ClusterIP
+ ports:
+ - name: dav
+ targetPort: 5232
+ port: 5232
+
+---
+kind: Ingress
+apiVersion: networking.k8s.io/v1
+metadata:
+ name: radicale
+ namespace: tools
+ labels:
+ app: radicale
+ annotations:
+ nginx.ingress.kubernetes.io/auth-type: basic
+ nginx.ingress.kubernetes.io/auth-secret: radicale/radicale-basic-auth
+ nginx.ingress.kubernetes.io/configuration-snippet: |-
+ proxy_set_header X-Remote-User $remote_user;
+spec:
+ ingressClassName: nginx-public
+ rules:
+ - host: radicale.theautomation.nl
+ http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: radicale
+ port:
+ number: 5232
+ tls:
+ - hosts:
+ - radicale.theautomation.nl
+ secretName: cloudflare-tls
diff --git a/src/.gitkeep b/src/.gitkeep
new file mode 100644
index 0000000..e69de29