Merge branch 'master' of gitlab.com:domaindrivenarchitecture/c4k-nextcloud
This commit is contained in:
commit
f943994afa
15 changed files with 169 additions and 99 deletions
|
@ -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
|
||||
|
|
43
README.md
43
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
|
||||
[<img src="https://domaindrivenarchitecture.org/img/delta-chat.svg" width=20 alt="DeltaChat"> chat over e-mail](mailto:buero@meissa-gmbh.de?subject=community-chat) | [<img src="https://meissa-gmbh.de/img/community/Mastodon_Logotype.svg" width=20 alt="team@social.meissa-gmbh.de"> team@social.meissa-gmbh.de](https://social.meissa-gmbh.de/@team) | [Website & Blog](https://domaindrivenarchitecture.org)
|
||||
|
||||
# restore manuell triggern
|
||||
## 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)
|
|
@ -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"}
|
||||
```
|
||||
|
|
BIN
doc/tryItOut.png
Normal file
BIN
doc/tryItOut.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 63 KiB |
|
@ -1,4 +1,4 @@
|
|||
FROM nextcloud:19
|
||||
FROM nextcloud:22
|
||||
|
||||
# Prepare Entrypoint Script
|
||||
ADD resources /tmp
|
||||
|
|
|
@ -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/
|
||||
|
|
18
public/index.html
Normal file
18
public/index.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>c4k-nextcloud</title>
|
||||
<link href="https://domaindrivenarchitecture.org/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
|
||||
<link href="https://domaindrivenarchitecture.org/css/fonts/fontawesome/fontawesome.css" rel="stylesheet"
|
||||
type="text/css" />
|
||||
<link href="https://domaindrivenarchitecture.org/css/custom.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="c4k-content"></div>
|
||||
<script src="js/main.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -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 {}
|
||||
|
|
|
@ -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!))))
|
||||
)
|
||||
(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"))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: batch/v1beta1
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: cloud-backup
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: cert-manager.io/v1alpha2
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: cloud-cert
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"}))))
|
||||
|
|
Loading…
Reference in a new issue