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 + +[![Build Status](https://drone.theautomation.nl/api/badges/theautomation/radicale/status.svg)](https://drone.theautomation.nl/theautomation/radicale) +![GitHub repo size](https://img.shields.io/github/repo-size/theautomation/radicale-code?logo=Github) +![GitHub commit activity](https://img.shields.io/github/commit-activity/y/theautomation/radicale-code?logo=github) +![GitHub last commit (branch)](https://img.shields.io/github/last-commit/theautomation/radicale-code/main?logo=github) + +Application running in Kubernetes K8s \ 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