diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index adca075..2cafe78 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -47,7 +47,7 @@ test-schema:
stage: build_and_test
script:
- lein uberjar
- - java -jar target/uberjar/c4k-nextcloud-standalone.jar valid-config.edn valid-auth.edn | kubeconform --kubernetes-version 1.19.0 --strict --skip Certificate -
+ - java -jar target/uberjar/c4k-nextcloud-standalone.jar valid-config.edn valid-auth.edn | kubeconform --kubernetes-version 1.19.0 --strict --skip "Certificate,CronJob" -
artifacts:
paths:
- target/uberjar
diff --git a/README.md b/README.md
index 9af9e4c..eebf0d7 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,42 @@
-# meissa-cloud
+# convention 4 kubernetes: c4k-nextcloud
+[![Clojars Project](https://img.shields.io/clojars/v/org.domaindrivenarchitecture/c4k-nextcloud.svg)](https://clojars.org/org.domaindrivenarchitecture/c4k-nextcloud) [![pipeline status](https://gitlab.com/domaindrivenarchitecture/c4k-nextcloud/badges/master/pipeline.svg)](https://gitlab.com/domaindrivenarchitecture/c4k-nextcloud/-/commits/master)
-# backup manuell triggern
+[ chat over e-mail](mailto:buero@meissa-gmbh.de?subject=community-chat) | [ team@social.meissa-gmbh.de](https://social.meissa-gmbh.de/@team) | [Website & Blog](https://domaindrivenarchitecture.org)
-# restore manuell triggern
\ No newline at end of file
+## Purpose
+
+c4k-nextcloud provides a k8s deployment for nextcloud containing:
+* adjusted nextcloud docker image
+* nextcloud
+* ingress having a letsencrypt managed certificate
+* postgres database
+
+The package aims to a low load sceanrio.
+
+## Status
+
+Stable - we use this setup on production.
+
+## Try out
+
+Click on the image to try out live in your browser:
+
+[![Try it out](doc/tryItOut.png "Try out yourself")](https://domaindrivenarchitecture.org/pages/dda-provision/c4k-nextcloud/)
+
+Your input will stay in your browser. No server interaction is required.
+
+You will also be able to try out on cli:
+```
+target/graalvm/c4k-nextcloud src/test/resources/valid-config.edn src/test/resources/valid-auth.edn | kubeval -
+target/graalvm/c4k-nextcloud src/test/resources/valid-config.edn src/test/resources/valid-auth.edn | kubectl apply -f -
+```
+
+## Documentation
+* [Example Setup on Hetzner](doc/SetupOnHetzner.md)
+* Backup and Restore
+
+## License
+
+Copyright © 2021 meissa GmbH
+Licensed under the [Apache License, Version 2.0](LICENSE) (the "License")
+Pls. find licenses of our subcomponents [here](doc/SUBCOMPONENT_LICENSE)
\ No newline at end of file
diff --git a/doc/SetupOnHetzner.md b/doc/SetupOnHetzner.md
index 3117fa1..9872457 100644
--- a/doc/SetupOnHetzner.md
+++ b/doc/SetupOnHetzner.md
@@ -17,7 +17,7 @@ resource "aws_s3_bucket" "backup" {
}
}
-resource "hcloud_server" "jira_09_2021" {
+resource "hcloud_server" "cloud_09_2021" {
name = "the name"
image = "ubuntu-20.04"
server_type = "cx31"
@@ -31,14 +31,14 @@ resource "hcloud_server" "jira_09_2021" {
resource "aws_route53_record" "v4_neu" {
zone_id = the_dns_zone
- name = "jira-neu"
+ name = "cloud-neu"
type = "A"
ttl = "300"
- records = [hcloud_server.jira_09_2021.ipv4_address]
+ records = [hcloud_server.cloud_09_2021.ipv4_address]
}
output "ipv4" {
- value = hcloud_server.jira_09_2021.ipv4_address
+ value = hcloud_server.cloud_09_2021.ipv4_address
}
```
@@ -52,23 +52,23 @@ For k8s installation we use our [dda-k8s-crate](https://github.com/DomainDrivenA
{:user :k8s
:k8s {:external-ip "ip-from-above"}
:cert-manager :letsencrypt-prod-issuer
- :persistent-dirs ["jira", "postgres"]
+ :persistent-dirs ["cloud", "postgres"]
}
```
-## kubectl apply c4k-jira
+## kubectl apply c4k-nextcloud
-The last step for applying the jira deployment is
+The last step for applying the nextcloud deployment is
```
-c4k-jira config.edn auth.edn | kubectl apply -f -
+c4k-nextcloud config.edn auth.edn | kubectl apply -f -
```
with the following config.edn:
```
{:fqdn "the-fqdn-from aws_route53_record.v4_neu"
- :jira-data-volume-path "/var/jira" ;; Volume was configured at dda-k8s-crate, results in a PersistentVolume definition.
+ :nextcloud-data-volume-path "/var/cloud" ;; Volume was configured at dda-k8s-crate, results in a PersistentVolume definition.
:postgres-data-volume-path "/var/postgres" ;; Volume was configured at dda-k8s-crate, results in a PersistentVolume definition.
:restic-repository "s3:s3.amazonaws.com/your-bucket/your-folder"}
```
diff --git a/doc/tryItOut.png b/doc/tryItOut.png
new file mode 100644
index 0000000..19ff34b
Binary files /dev/null and b/doc/tryItOut.png differ
diff --git a/infrastructure/docker-nextcloud/image/Dockerfile b/infrastructure/docker-nextcloud/image/Dockerfile
index 8b3d9e9..61ac8ab 100644
--- a/infrastructure/docker-nextcloud/image/Dockerfile
+++ b/infrastructure/docker-nextcloud/image/Dockerfile
@@ -1,4 +1,4 @@
-FROM nextcloud:19
+FROM nextcloud:22
# Prepare Entrypoint Script
ADD resources /tmp
diff --git a/infrastructure/docker-nextcloud/image/resources/install.sh b/infrastructure/docker-nextcloud/image/resources/install.sh
index b92fc18..2111956 100755
--- a/infrastructure/docker-nextcloud/image/resources/install.sh
+++ b/infrastructure/docker-nextcloud/image/resources/install.sh
@@ -1,6 +1,8 @@
#!/bin/bash
set -Eeo pipefail
+apt update && apt -qqy install postgresql-client > /dev/null
+
mkdir /var/data
install -m 0700 /tmp/install-debug.sh /usr/local/bin/
diff --git a/public/index.html b/public/index.html
new file mode 100644
index 0000000..9cda1d2
--- /dev/null
+++ b/public/index.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+ c4k-nextcloud
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/shadow-cljs.edn b/shadow-cljs.edn
index 330e8e8..6bea133 100644
--- a/shadow-cljs.edn
+++ b/shadow-cljs.edn
@@ -4,7 +4,8 @@
"src/test/cljc"
"src/test/cljs"
"src/test/resources"]
- :dependencies [[org.domaindrivenarchitecture/c4k-common-cljs "0.3.2-SNAPSHOT"]]
+ :dependencies [[org.domaindrivenarchitecture/c4k-common-cljs "0.4.3"]
+ [hickory "0.7.1"]]
:builds {:frontend {:target :browser
:modules {:main {:init-fn dda.c4k-nextcloud.browser/init}}
:release {}
diff --git a/src/main/cljs/dda/c4k_nextcloud/browser.cljs b/src/main/cljs/dda/c4k_nextcloud/browser.cljs
index 94012b6..eee519c 100644
--- a/src/main/cljs/dda/c4k_nextcloud/browser.cljs
+++ b/src/main/cljs/dda/c4k_nextcloud/browser.cljs
@@ -6,6 +6,34 @@
[dda.c4k-common.browser :as br]
[dda.c4k-common.postgres :as pgc]))
+(defn generate-content
+ []
+ (into [] (concat [(assoc (br/generate-needs-validation) :content
+ (into [] (concat (br/generate-input-field "fqdn" "Your fqdn:" "nextcloud-neu.prod.meissa-gmbh.de")
+ (br/generate-input-field "nextcloud-data-volume-path" "(Optional) Your nextcloud-data-volume-path:" "/var/nextcloud")
+ (br/generate-input-field "postgres-data-volume-path" "(Optional) Your postgres-data-volume-path:" "/var/postgres")
+ (br/generate-input-field "restic-repository" "(Optional) Your restic-repository:" "restic-repository")
+ (br/generate-input-field "issuer" "(Optional) Your issuer prod/staging:" "")
+ [(br/generate-br)]
+ (br/generate-text-area "auth" "Your auth.edn:" "{:postgres-db-user \"nextcloud\"
+ :postgres-db-password \"nextcloud-db-password\"
+ :nextcloud-admin-password \"nextcloud-admin-password\"
+ :nextcloud-admin-user \"nextcloud-admin-user\"
+ :aws-access-key-id \"aws-id\"
+ :aws-secret-access-key \"aws-secret\"
+ :restic-password \"restic-password\"}"
+ "5")
+ [(br/generate-br)]
+ (br/generate-button "generate-button" "Generate c4k yaml"))))]
+ (br/generate-output "c4k-nextcloud-output" "Your c4k deployment.yaml:" "25"))))
+
+(defn generate-content-div
+ []
+ {:type :element
+ :tag :div
+ :content
+ (generate-content)})
+
(defn config-from-document []
(let [nextcloud-data-volume-path (br/get-content-from-element "nextcloud-data-volume-path" :optional true)
postgres-data-volume-path (br/get-content-from-element "postgres-data-volume-path" :optional true)
@@ -32,7 +60,12 @@
(br/validate! "auth" core/auth? :deserializer edn/read-string)
(br/set-validated!))
+(defn add-validate-listener [name]
+ (-> (br/get-element-by-id name)
+ (.addEventListener "blur" #(do (validate-all!)))))
+
(defn init []
+ (br/append-hickory (generate-content-div))
(-> js/document
(.getElementById "generate-button")
(.addEventListener "click"
@@ -41,22 +74,9 @@
(config-from-document)
(br/get-content-from-element "auth" :deserializer edn/read-string))
(br/set-output!)))))
- (-> (br/get-element-by-id "fqdn")
- (.addEventListener "blur"
- #(do (validate-all!))))
- (-> (br/get-element-by-id "nextcloud-data-volume-path")
- (.addEventListener "blur"
- #(do (validate-all!))))
- (-> (br/get-element-by-id "postgres-data-volume-path")
- (.addEventListener "blur"
- #(do (validate-all!))))
- (-> (br/get-element-by-id "restic-repository")
- (.addEventListener "blur"
- #(do (validate-all!))))
- (-> (br/get-element-by-id "issuer")
- (.addEventListener "blur"
- #(do (validate-all!))))
- (-> (br/get-element-by-id "auth")
- (.addEventListener "blur"
- #(do (validate-all!))))
- )
\ No newline at end of file
+ (add-validate-listener "fqdn")
+ (add-validate-listener "nextcloud-data-volume-path")
+ (add-validate-listener "postgres-data-volume-path")
+ (add-validate-listener "restic-repository")
+ (add-validate-listener "issuer")
+ (add-validate-listener "auth"))
diff --git a/src/main/resources/backup/backup-restore.yaml b/src/main/resources/backup/backup-restore.yaml
index c13e166..2c6aafb 100644
--- a/src/main/resources/backup/backup-restore.yaml
+++ b/src/main/resources/backup/backup-restore.yaml
@@ -12,12 +12,21 @@ spec:
imagePullPolicy: IfNotPresent
command: ["/entrypoint-start-and-wait.sh"]
env:
- - name: POSTGRES_USER_FILE
- value: /var/run/secrets/cloud-secrets/postgres-user
- - name: POSTGRES_DB_FILE
- value: /var/run/secrets/cloud-secrets/postgres-db
- - name: POSTGRES_PASSWORD_FILE
- value: /var/run/secrets/cloud-secrets/postgres-password
+ - name: POSTGRES_USER
+ valueFrom:
+ secretKeyRef:
+ name: postgres-secret
+ key: postgres-user
+ - name: POSTGRES_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: postgres-secret
+ key: postgres-password
+ - name: POSTGRES_DB
+ valueFrom:
+ configMapKeyRef:
+ name: postgres-config
+ key: postgres-db
- name: POSTGRES_HOST
value: "postgresql-service:5432"
- name: POSTGRES_SERVICE
diff --git a/src/main/resources/backup/cron.yaml b/src/main/resources/backup/cron.yaml
index 2026cf5..3c54570 100644
--- a/src/main/resources/backup/cron.yaml
+++ b/src/main/resources/backup/cron.yaml
@@ -1,4 +1,4 @@
-apiVersion: batch/v1beta1
+apiVersion: batch/v1
kind: CronJob
metadata:
name: cloud-backup
diff --git a/src/main/resources/nextcloud/certificate.yaml b/src/main/resources/nextcloud/certificate.yaml
index 054965b..6912f95 100644
--- a/src/main/resources/nextcloud/certificate.yaml
+++ b/src/main/resources/nextcloud/certificate.yaml
@@ -1,4 +1,4 @@
-apiVersion: cert-manager.io/v1alpha2
+apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: cloud-cert
diff --git a/src/main/resources/nextcloud/deployment.yaml b/src/main/resources/nextcloud/deployment.yaml
index f87b70a..b825eef 100644
--- a/src/main/resources/nextcloud/deployment.yaml
+++ b/src/main/resources/nextcloud/deployment.yaml
@@ -22,6 +22,14 @@ spec:
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
+ livenessProbe:
+ exec:
+ command:
+ - /bin/sh
+ - -c
+ - PGPASSWORD=$POSTGRES_PASSWORD psql -h postgresql-service -U $POSTGRES_USER $POSTGRES_DB
+ initialDelaySeconds: 1
+ periodSeconds: 5
env:
- name: NEXTCLOUD_ADMIN_USER
valueFrom:
diff --git a/src/test/cljc/dda/c4k_nextcloud/backup_test.cljc b/src/test/cljc/dda/c4k_nextcloud/backup_test.cljc
index 4aee6b2..227c4d6 100644
--- a/src/test/cljc/dda/c4k_nextcloud/backup_test.cljc
+++ b/src/test/cljc/dda/c4k_nextcloud/backup_test.cljc
@@ -10,7 +10,7 @@
:kind "Secret"
:metadata {:name "backup-secret"}
:type "Opaque"
- :stringData
+ :data
{:aws-access-key-id "YXdzLWlk", :aws-secret-access-key "YXdzLXNlY3JldA==", :restic-password "cmVzdGljLXB3"}}
(cut/generate-secret {:aws-access-key-id "aws-id" :aws-secret-access-key "aws-secret" :restic-password "restic-pw"}))))
@@ -25,7 +25,7 @@
(cut/generate-config {:restic-repository "s3:restic-repository"}))))
(deftest should-generate-cron
- (is (= {:apiVersion "batch/v1beta1"
+ (is (= {:apiVersion "batch/v1"
:kind "CronJob"
:metadata {:name "cloud-backup", :labels {:app.kubernetes.part-of "cloud"}}
:spec
@@ -38,7 +38,7 @@
{:spec
{:containers
[{:name "backup-app"
- :image "domaindrivenarchitecture/meissa-cloud-backup"
+ :image "domaindrivenarchitecture/c4k-cloud-backup"
:imagePullPolicy "IfNotPresent"
:command ["/entrypoint.sh"]
:env
diff --git a/src/test/cljc/dda/c4k_nextcloud/nextcloud_test.cljc b/src/test/cljc/dda/c4k_nextcloud/nextcloud_test.cljc
index 55ebae8..5494fa0 100644
--- a/src/test/cljc/dda/c4k_nextcloud/nextcloud_test.cljc
+++ b/src/test/cljc/dda/c4k_nextcloud/nextcloud_test.cljc
@@ -9,14 +9,14 @@
:kind "Secret"
:metadata {:name "cloud-secret"}
:type "Opaque"
- :stringData
+ :data
{:nextcloud-admin-user "Y2xvdWRhZG1pbg=="
:nextcloud-admin-password "Y2xvdWRwYXNzd29yZA=="}}
(cut/generate-secret {:nextcloud-admin-user "cloudadmin"
:nextcloud-admin-password "cloudpassword"}))))
(deftest should-generate-certificate
- (is (= {:apiVersion "cert-manager.io/v1alpha2"
+ (is (= {:apiVersion "cert-manager.io/v1"
:kind "Certificate"
:metadata {:name "cloud-cert", :namespace "default"}
:spec
@@ -58,71 +58,46 @@
(deftest should-generate-persistent-volume
(is (= {:kind "PersistentVolume"
:apiVersion "v1"
- :metadata {:name "cloud-pv-volume", :labels {:type "local" :app "cloud"}}
- :spec
- {:storageClassName "manual"
- :accessModes ["ReadWriteOnce"]
- :capacity {:storage "200Gi"}
- :hostPath {:path "xx"}}}
+ :metadata {:name "cloud-pv-volume"
+ :labels {:type "local", :app.kubernetes.io/application "cloud"}}
+ :spec {:storageClassName "manual"
+ :accessModes ["ReadWriteOnce"]
+ :capacity {:storage "200Gi"}
+ :hostPath {:path "xx"}}}
(cut/generate-persistent-volume {:nextcloud-data-volume-path "xx"}))))
(deftest should-generate-deployment
(is (= {:apiVersion "apps/v1"
:kind "Deployment"
- :metadata {:name "cloud"}
+ :metadata {:name "cloud-deployment"}
:spec
- {:selector {:matchLabels {:app "cloud"}}
+ {:selector {:matchLabels #:app.kubernetes.io{:name "cloud-pod", :application "cloud"}}
:strategy {:type "Recreate"}
:template
- {:metadata {:labels {:app "cloud"}}
+ {:metadata {:labels {:app.kubernetes.io/name "cloud-pod", :app.kubernetes.io/application "cloud", :redeploy "v3"}}
:spec
{:containers
- [{:image "domaindrivenarchitecture/meissa-cloud-app"
+ [{:image "domaindrivenarchitecture/c4k-cloud"
:name "cloud-app"
:imagePullPolicy "IfNotPresent"
:ports [{:containerPort 80}]
+ :livenessProbe
+ {:exec
+ {:command
+ ["/bin/sh"
+ "-c"
+ "PGPASSWORD=$POSTGRES_PASSWORD psql -h postgresql-service -U $POSTGRES_USER $POSTGRES_DB"]}
+ :initialDelaySeconds 1
+ :periodSeconds 5}
:env
- [{:name "NEXTCLOUD_ADMIN_USER_FILE"
- :value
- "/var/run/secrets/cloud-secrets/nextcloud-admin-user"}
- {:name "NEXTCLOUD_ADMIN_PASSWORD_FILE"
- :value
- "/var/run/secrets/cloud-secrets/nextcloud-admin-password"}
+ [{:name "NEXTCLOUD_ADMIN_USER", :valueFrom {:secretKeyRef {:name "cloud-secret", :key "nextcloud-admin-user"}}}
+ {:name "NEXTCLOUD_ADMIN_PASSWORD"
+ :valueFrom {:secretKeyRef {:name "cloud-secret", :key "nextcloud-admin-password"}}}
{:name "NEXTCLOUD_TRUSTED_DOMAINS", :value "xx"}
- {:name "POSTGRES_USER_FILE"
- :value
- "/var/run/secrets/postgres-secret/postgres-user"}
- {:name "POSTGRES_PASSWORD_FILE"
- :value
- "/var/run/secrets/postgres-secret/postgres-password"}
- {:name "POSTGRES_DB_FILE"
- :value
- "/var/run/configs/postgres-config/postgres-db"}
- {:name "POSTGRES_HOST"
- :value "postgresql-service:5432"}]
- :volumeMounts
- [{:name "cloud-data-volume"
- :mountPath "/var/www/html"}
- {:name "cloud-secret-volume"
- :mountPath "/var/run/secrets/cloud-secrets"
- :readOnly true}
- {:name "postgres-secret-volume"
- :mountPath "/var/run/secrets/postgres-secret"
- :readOnly true}
- {:name "postgres-config-volume"
- :mountPath "/var/run/configs/postgres-config"
- :readOnly true}]}]
- :volumes
- [{:name "cloud-data-volume"
- :persistentVolumeClaim {:claimName "cloud-pvc"}}
- {:name "cloud-secret-volume"
- :secret {:secretName "cloud-secret"}}
- {:name "postgres-secret-volume"
- :secret {:secretName "postgres-secret"}}
- {:name "postgres-config-volume"
- :configMap
- {:name "postgres-config"
- :items [{:key "postgres-db", :path "postgres-db"}]}}
- {:name "backup-secret-volume"
- :secret {:secretName "backup-secret"}}]}}}}
+ {:name "POSTGRES_USER", :valueFrom {:secretKeyRef {:name "postgres-secret", :key "postgres-user"}}}
+ {:name "POSTGRES_PASSWORD", :valueFrom {:secretKeyRef {:name "postgres-secret", :key "postgres-password"}}}
+ {:name "POSTGRES_DB", :valueFrom {:configMapKeyRef {:name "postgres-config", :key "postgres-db"}}}
+ {:name "POSTGRES_HOST", :value "postgresql-service:5432"}]
+ :volumeMounts [{:name "cloud-data-volume", :mountPath "/var/www/html"}]}]
+ :volumes [{:name "cloud-data-volume", :persistentVolumeClaim {:claimName "cloud-pvc"}}]}}}}
(cut/generate-deployment {:fqdn "xx"}))))