From 9291a88f04197e02690b123ecf843017d3b7b5cb Mon Sep 17 00:00:00 2001 From: WrenIX Date: Sat, 2 Dec 2023 13:34:12 +0100 Subject: [PATCH] fix(mycloud-nextcloud): init solves #1 --- base-values/mycloud-core.yaml | 2 +- base-values/mycloud-nextcloud.yaml | 17 ++ docs/modules/components/nav.adoc | 1 + .../components/pages/mycloud-nextcloud.adoc | 1 + .../grafana/authentik-application.yaml | 6 +- mycloud-nextcloud/.helmignore | 23 ++ mycloud-nextcloud/Chart.yaml | 9 + mycloud-nextcloud/README.adoc | 230 ++++++++++++++++++ .../templates/authentik-application.yaml | 68 ++++++ mycloud-nextcloud/templates/pv.yaml | 29 +++ mycloud-nextcloud/templates/release.yaml | 212 ++++++++++++++++ mycloud-nextcloud/templates/repo.yaml | 10 + mycloud-nextcloud/values.yaml | 116 +++++++++ 13 files changed, 720 insertions(+), 4 deletions(-) create mode 100644 base-values/mycloud-nextcloud.yaml create mode 120000 docs/modules/components/pages/mycloud-nextcloud.adoc create mode 100644 mycloud-nextcloud/.helmignore create mode 100644 mycloud-nextcloud/Chart.yaml create mode 100644 mycloud-nextcloud/README.adoc create mode 100644 mycloud-nextcloud/templates/authentik-application.yaml create mode 100644 mycloud-nextcloud/templates/pv.yaml create mode 100644 mycloud-nextcloud/templates/release.yaml create mode 100644 mycloud-nextcloud/templates/repo.yaml create mode 100644 mycloud-nextcloud/values.yaml diff --git a/base-values/mycloud-core.yaml b/base-values/mycloud-core.yaml index 7293f77..cc517ae 100644 --- a/base-values/mycloud-core.yaml +++ b/base-values/mycloud-core.yaml @@ -17,7 +17,7 @@ commons: host: username: password: - from: + from: "no-reply@example.org" use_tls: false use_ssl: false diff --git a/base-values/mycloud-nextcloud.yaml b/base-values/mycloud-nextcloud.yaml new file mode 100644 index 0000000..1e8baec --- /dev/null +++ b/base-values/mycloud-nextcloud.yaml @@ -0,0 +1,17 @@ +## +# commons are from mycloud-core +## + +components: + mycloud-services: + # patch mycloud-core to get another database + values: + databases: + nextcloud: + type: postgresql + + mycloud-nextcloud: + enabled: true + namespace: + # current namespace + name: diff --git a/docs/modules/components/nav.adoc b/docs/modules/components/nav.adoc index 8dbc6e5..6cecd64 100644 --- a/docs/modules/components/nav.adoc +++ b/docs/modules/components/nav.adoc @@ -6,4 +6,5 @@ ** xref:infra-monitoring.adoc[infra-monitoring] ** xref:infra-trivy.adoc[infra-trivy] ** xref:mycloud-authentik.adoc[mycloud-authentik] +** xref:mycloud-nextcloud.adoc[mycloud-nextcloud] ** xref:mycloud-services.adoc[mycloud-services] diff --git a/docs/modules/components/pages/mycloud-nextcloud.adoc b/docs/modules/components/pages/mycloud-nextcloud.adoc new file mode 120000 index 0000000..e91a003 --- /dev/null +++ b/docs/modules/components/pages/mycloud-nextcloud.adoc @@ -0,0 +1 @@ +../../../../mycloud-nextcloud/README.adoc \ No newline at end of file diff --git a/infra-monitoring/templates/grafana/authentik-application.yaml b/infra-monitoring/templates/grafana/authentik-application.yaml index d5008f0..8daf844 100644 --- a/infra-monitoring/templates/grafana/authentik-application.yaml +++ b/infra-monitoring/templates/grafana/authentik-application.yaml @@ -42,9 +42,9 @@ spec: clientSecret: {{ .Values.grafana.auth.authentik.clientSecret | default (derivePassword 1 "long" .Values.commons.masterPassword "grafana" "clientSecret") | quote }} # signingKey: scopes: - - openid - - email - - profile + - name: "authentik default OAuth Mapping: OpenID 'openid'" + - name: "authentik default OAuth Mapping: OpenID 'email'" + - name: "authentik default OAuth Mapping: OpenID 'profile'" groups: - slug: "app: infra" diff --git a/mycloud-nextcloud/.helmignore b/mycloud-nextcloud/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/mycloud-nextcloud/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/mycloud-nextcloud/Chart.yaml b/mycloud-nextcloud/Chart.yaml new file mode 100644 index 0000000..feaccb9 --- /dev/null +++ b/mycloud-nextcloud/Chart.yaml @@ -0,0 +1,9 @@ +apiVersion: v2 +name: mycloud-nextcloud +description: myCloud component to setup nextcloud +type: application +maintainers: + - name: WrenIX + url: https://wrenix.eu + +version: 0.1.0 diff --git a/mycloud-nextcloud/README.adoc b/mycloud-nextcloud/README.adoc new file mode 100644 index 0000000..a6a86c8 --- /dev/null +++ b/mycloud-nextcloud/README.adoc @@ -0,0 +1,230 @@ + + += mycloud-nextcloud + +image::https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square[Version: 0.1.0] +image::https://img.shields.io/badge/Version-application-informational?style=flat-square[Type: application] +== Maintainers + +.Maintainers +|=== +| Name | Email | Url + +| WrenIX +| +| +|=== + +== Values + +.Values +|=== +| Key | Type | Default | Description + +| adminPassword +| string +| `nil` +| generated by .Values.commons.masterPassword + +| auth.clientID +| string +| `nil` +| generated by .Values.commons.masterPassword + +| auth.clientSecret +| string +| `nil` +| generated by .Values.commons.masterPassword + +| commons.auth.host +| string +| `nil` +| default auth.(.Values.commons.ingress.domain) + +| commons.helm.release.install +| object +| `{}` +| + +| commons.helm.release.test +| object +| `{}` +| + +| commons.helm.release.upgrade +| object +| `{}` +| + +| commons.ingress.annotations."cert-manager.io/cluster-issuer" +| string +| `"letsencrypt-prod"` +| + +| commons.ingress.domain +| string +| `"wrenix.eu"` +| + +| commons.ingress.tls.enabled +| bool +| `true` +| tls on every ingress + +| commons.ingress.tls.override +| string +| `nil` +| use own definition of tls (e.g. for own or wildcard certificate) + +| commons.mail.from +| string +| `nil` +| + +| commons.mail.host +| string +| `nil` +| + +| commons.mail.password +| string +| `nil` +| + +| commons.mail.use_ssl +| bool +| `false` +| + +| commons.mail.use_tls +| bool +| `false` +| + +| commons.mail.username +| string +| `nil` +| + +| commons.masterPassword +| string +| `"CHANGEME"` +| + +| commons.persistence.hostPath.enabled +| bool +| `false` +| + +| commons.persistence.hostPath.prefix +| string +| `"/var/lib/mycloud"` +| + +| commons.persistence.storageClass +| string +| `nil` +| + +| commons.prometheus.monitor.labels +| object +| `{}` +| + +| commons.prometheus.rules.labels +| object +| `{}` +| + +| commons.theme.favicon +| string +| `"/static/dist/assets/icons/icon.png"` +| + +| commons.theme.logo +| string +| `"/static/dist/assets/icons/icon_left_brand.svg"` +| + +| commons.theme.title +| string +| `"myCloud"` +| + +| database.host +| string +| `"mycloud-services-postgresql"` +| default is from mysql-services + +| database.name +| string +| `"nextcloud"` +| + +| database.password +| string +| `nil` +| generated by .Values.commons.masterPassword (equal to mycloud-services) + +| database.username +| string +| `"nextcloud"` +| + +| ingress.annotations +| string +| `nil` +| + +| ingress.host +| string +| `nil` +| default: fs.(Values.commons.ingress.domain) + +| init.namespace +| string +| `"bases"` +| + +| init.version +| int +| `0` +| + +| mail.authtype +| string +| `"PLAIN"` +| + +| mail.from +| string +| `nil` +| generade by Values.commons.mail.from + +| mail.host +| string +| `nil` +| default Values.commons.mail.host + +| persistence.data.pvc +| string +| `"nextcloud-data"` +| + +| persistence.data.size +| string +| `"16Gi"` +| + +| persistence.main.pvc +| string +| `"nextcloud"` +| + +| persistence.main.size +| string +| `"8Gi"` +| +|=== + +Autogenerated from chart metadata using https://github.com/norwoodj/helm-docs[helm-docs] diff --git a/mycloud-nextcloud/templates/authentik-application.yaml b/mycloud-nextcloud/templates/authentik-application.yaml new file mode 100644 index 0000000..8388abc --- /dev/null +++ b/mycloud-nextcloud/templates/authentik-application.yaml @@ -0,0 +1,68 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2beta2 +kind: HelmRelease +metadata: + name: {{ .Release.Name }}-auth +spec: + chart: + spec: + sourceRef: + kind: GitRepository + name: "wrenix-helm-charts" + namespace: "flux-system" + chart: "./authentik-application" + reconcileStrategy: "Revision" + install: + {{- toYaml .Values.commons.helm.release.install | nindent 4 }} + test: + {{- toYaml .Values.commons.helm.release.test | nindent 4 }} + upgrade: + {{- toYaml .Values.commons.helm.release.upgrade | nindent 4 }} + driftDetection: + {{- toYaml .Values.commons.helm.release.driftDetection | nindent 4 }} + interval: 10m + values: + {{- $host := .Values.ingress.host | default (printf "fs.%s" .Values.commons.ingress.domain) }} + blueprint: + authentik: + domain: "https://{{ .Values.commons.auth.host | default (printf "auth.%s" .Values.commons.ingress.domain) }}" + provider: + type: "oidc" + name: "Nextcloud" + oidc: + clientType: "confidential" + redirectURL: "https://{{ $host }}/apps/user_oidc/code" + clientID: {{ .Values.auth.clientID | default (derivePassword 1 "long" .Values.commons.masterPassword "nextcloud" "auth.clientID") | quote }} + clientSecret: {{ .Values.auth.clientSecret | default (derivePassword 1 "long" .Values.commons.masterPassword "nextcloud" "auth.clientSecret") | quote }} + # signingKey: + scopes: + - name: "authentik default OAuth Mapping: OpenID 'openid'" + - name: "authentik default OAuth Mapping: OpenID 'email'" + - name: "OAuth Mapping: Nextcloud Profile" + scope_name: profile + expression: |- + groups = [group.name for group in user.ak_groups.all()] + if user.is_superuser and "admin" not in groups: + groups.append("admin") + + return { + "nickname": request.user.username, + "name": request.user.name, + "groups": groups, + "quota": user.group_attributes().get("nextcloud_quota", {{ with .Values.quota }}{{ . | quote }}{{ else }}None{{ end }}) + } + + groups: + - slug: "mycloud - users" + bindID: "cefc0c13-49fa-4374-a909-e201a88a473b" + + application: + policyEngineMode: "any" + openInNewTab: true + publisher: "WrenIX's myCloud" + slug: "mycloud-nextcloud" + group: "Office" + name: "Nextcloud" + launchURL: "https://{{ $host }}/" + icon: "https://{{ $host }}/core/img/favicon-touch.png" + description: "📱☁️💻 A safe home for all your data – community-driven, free & open source 👏" diff --git a/mycloud-nextcloud/templates/pv.yaml b/mycloud-nextcloud/templates/pv.yaml new file mode 100644 index 0000000..c40f12d --- /dev/null +++ b/mycloud-nextcloud/templates/pv.yaml @@ -0,0 +1,29 @@ +{{- if or + .Values.commons.persistence.hostPath.enabled +}} +{{- range $name, $config := .Values.persistence }} +{{- $pvcName := printf "%s-hr-%s" $.Release.Name $config.pvc }} +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: {{ $.Release.Namespace }}-{{ $pvcName }} +spec: + claimRef: + apiVersion: v1 + kind: PersistentVolumeClaim + namespace: {{ $.Release.Namespace }} + name: {{ $pvcName }} + storageClassName: {{ $.Values.commons.persistence.storageClass }} + accessModes: + - "ReadWriteOnce" + capacity: + storage: "{{ $config.size }}" + {{- with $.Values.commons.persistence.hostPath }} + {{- if .enabled }} + hostPath: + path: {{ printf "%s/nextcloud/%s" .prefix $name }} + {{- end }}{{/* end-if .enabled */}} + {{- end }}{{/* end-with .hostPath */}} +{{- end }}{{/* end-range */}} +{{- end }}{{/* end-if */}} diff --git a/mycloud-nextcloud/templates/release.yaml b/mycloud-nextcloud/templates/release.yaml new file mode 100644 index 0000000..434e401 --- /dev/null +++ b/mycloud-nextcloud/templates/release.yaml @@ -0,0 +1,212 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2beta2 +kind: HelmRelease +metadata: + name: "{{ .Release.Name }}-hr" +spec: + chart: + spec: + sourceRef: + kind: GitRepository + name: "nextcloud" + chart: "./charts/nextcloud" + # TODO delete later + # https://codeberg.org/wrenix/flux-charts/issues/6 + reconcileStrategy: "Revision" + install: + {{- toYaml .Values.commons.helm.release.install | nindent 4 }} + test: + {{- toYaml .Values.commons.helm.release.test | nindent 4 }} + upgrade: + {{- toYaml .Values.commons.helm.release.upgrade | nindent 4 }} + driftDetection: + {{- toYaml .Values.commons.helm.release.driftDetection | nindent 4 }} + interval: 10m + values: + {{- $host := .Values.ingress.host | default (printf "fs.%s" .Values.commons.ingress.domain) }} + nextcloud: + username: nextcloud-admin + password: {{ .Values.adminPassword | default (derivePassword 1 "long" .Values.commons.masterPassword "nextcloud" "admin_password") | quote }} + host: {{ $host }} + mail: + enabled: true + fromAddress: {{ .Values.mail.from | default (printf "[%s] %s <%s>" .Values.commons.theme.title "nextcloud" .Values.commons.mail.from) | quote }} + domain: {{ .Values.mail.host | default .Values.commons.mail.host | quote }} + smtp: + host: {{ .Values.mail.host | default .Values.commons.mail.host | quote }} + port: 587 + {{- if .Values.commons.mail.use_tls }} + secure: "tls" + {{- else if .Values.commons.mail.use_ssl }} + secure: "ssl" + {{- end }} + {{- if and .Values.commons.mail.username .Values.commons.mail.password}} + # there also "PLAIN" is supported + authtype: {{ .Values.mail.authtype }} + {{- end }} + name: {{ .Values.commons.mail.username | quote }} + password: {{ .Values.commons.mail.password | quote }} + + configs: + proxy.config.php: |- + true, + 'trusted_proxies' => array( + 0 => '127.0.0.1', + 1 => '10.0.0.0/8', + ), + 'forwarded_for_headers' => array('HTTP_X_FORWARDED_FOR'), + ); + custom-oidc.config.php: |- + false, + 'skeletondirectory' => '', + 'lost_password_link' => 'https://{{ .Values.commons.auth.host | default (printf "auth.%s" .Values.commons.ingress.domain) }}/if/flow/default-recovery-flow/', + ); + + {{- if or + .Values.commons.persistence.hostPath.enabled + }} + extraInitContainers: + - name: "take-ownership" + image: "alpine:3" + command: ["chown", "-R", "33:33", "/var/www/html/config" ] + volumeMounts: + - name: "nextcloud-main" + mountPath: /var/www/html/config + subPath: "config" + {{- end }} + + appManagement: + enabled: true + apps: + user_oidc: + enabled: true + config: + allow_multiple_user_backends: "0" + # collabora + #richdocuments: + # enabled: true + # config: {} + {{- toYaml .Values.apps | nindent 10 }} + + hooks: + before-starting: + # docu for theming: https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/theming.html#configure-theming-through-cli + # /var/www/html/occ theming:config logo "{{ .Values.commons.theme.logo }}"; + # + # TODO add group mapping after fix is there + # https://github.com/nextcloud/user_oidc/issues/744 + # https://codeberg.org/wrenix/flux-charts/issues/7 + shell: |- + #!/bin/sh + echo "setup theming": + /var/www/html/occ theming:config disable-user-theming yes; + /var/www/html/occ theming:config name "{{ .Values.commons.theme.title }}"; + + echo "setup oidc"; + /var/www/html/occ user_oidc:provider mycloud \ + --clientid {{ .Values.auth.clientID | default (derivePassword 1 "long" .Values.commons.masterPassword "nextcloud" "auth.clientID") | squote }} \ + --clientsecret {{ .Values.auth.clientSecret | default (derivePassword 1 "long" .Values.commons.masterPassword "nextcloud" "auth.clientSecret") | squote }} \ + --discoveryuri "https://{{ .Values.commons.auth.host | default (printf "auth.%s" .Values.commons.ingress.domain) }}/application/o/mycloud-nextcloud/.well-known/openid-configuration" \ + --scope "openid email profile" \ + --extra-claims=scope \ + --mapping-uid={{ .Values.auth.idMapping }} \ + --mapping-email=email \ + --mapping-display-name=name \ + --mapping-quota=quota \ + --check-bearer=true \ + --unique-uid=0; + + phpClientHttpsFix: + enabled: true + + image: + flavor: fpm + nginx: + enabled: true + + metrics: + enabled: true + serviceMonitor: + enabled: {{ (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1/ServiceMonitor") }} + additionalLabels: + {{- toYaml .Values.commons.prometheus.monitor.labels | nindent 10 }} + rules: + enabled: {{ (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1/PrometheusRule") }} + additionalLabels: + {{- toYaml .Values.commons.prometheus.rules.labels | nindent 10 }} + + ingress: + enabled: true + annotations: + {{- with .Values.commons.ingress.annotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingress.annotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.commons.ingress.tls.enabled }} + tls: + {{- with .Values.commons.ingress.tls.override }} + {{- toYaml . | nindent 8 }} + {{- else }} + - secretName: "mycloud-nextcloud-cert" + hosts: + - "{{ $host }}" + {{- end }} + {{- end }} + + cronjob: + enabled: true + + redis: + enabled: true + replica: + # just one replica + replicaCount: 1 + metrics: + enabled: true + serviceMonitor: + enabled: {{ (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1/ServiceMonitor") }} + additionalLabels: + {{- toYaml .Values.commons.prometheus.monitor.labels | nindent 12 }} + prometheusRule: + # empty rules + enabled: false + # {{ (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1/PrometheusRule") }} + additionalLabels: + {{- toYaml .Values.commons.prometheus.rules.labels | nindent 12 }} + rules: [] + + {{- $pvHelper := (or .Values.commons.persistence.hostPath.enabled) }} + {{- $storageClass := $pvHelper | ternary "manual" .Values.commons.persistence.storageClass }} + persistence: + enabled: true + {{- if $storageClass }} + storageClass: {{ $storageClass }} + {{- end}} + size: {{ .Values.persistence.main.size }} + nextcloudData: + enabled: true + {{- if $storageClass }} + storageClass: {{ $storageClass }} + {{- end}} + size: {{ .Values.persistence.data.size }} + + internalDatabase: + enabled: false + postgresql: + enabled: false + mariadb: + enabled: false + + externalDatabase: + enabled: true + type: postgresql + host: {{ .Values.database.host | quote }} + database: {{ .Values.database.name | quote }} + user: {{ .Values.database.username | quote }} + password: {{ .Values.database.password | default (derivePassword 1 "long" .Values.commons.masterPassword "nextcloud" "database_password") | quote }} diff --git a/mycloud-nextcloud/templates/repo.yaml b/mycloud-nextcloud/templates/repo.yaml new file mode 100644 index 0000000..8ac708d --- /dev/null +++ b/mycloud-nextcloud/templates/repo.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: GitRepository +metadata: + name: nextcloud +spec: + url: https://github.com/wrenix/nextcloud-helm.git + ref: + branch: main + interval: 10m diff --git a/mycloud-nextcloud/values.yaml b/mycloud-nextcloud/values.yaml new file mode 100644 index 0000000..9fefb31 --- /dev/null +++ b/mycloud-nextcloud/values.yaml @@ -0,0 +1,116 @@ +init: + version: 0 + namespace: "bases" + +commons: + masterPassword: "CHANGEME" + + auth: + # -- default auth.(.Values.commons.ingress.domain) + host: + + theme: + title: myCloud + logo: /static/dist/assets/icons/icon_left_brand.svg + favicon: /static/dist/assets/icons/icon.png + + mail: + host: + username: + password: + from: + use_tls: false + use_ssl: false + + persistence: + storageClass: + hostPath: + enabled: false + prefix: "/var/lib/mycloud" + + helm: + release: + install: {} + test: {} + upgrade: {} + driftDetection: {} + + ingress: + domain: "wrenix.eu" + annotations: + cert-manager.io/cluster-issuer: letsencrypt-prod + tls: + # -- tls on every ingress + enabled: true + # -- use own definition of tls (e.g. for own or wildcard certificate) + override: + + prometheus: + monitor: + labels: {} + rules: + labels: {} + +# -- generated by .Values.commons.masterPassword +adminPassword: + +auth: + # -- generated by .Values.commons.masterPassword + clientID: + # -- generated by .Values.commons.masterPassword + clientSecret: + # -- oidc field which us used as id in nextcloud for username (for security reason it is sub, but could be overwritten by username) + # https://goauthentik.io/integrations/services/nextcloud/#provider-and-application + idMapping: sub + +apps: + checksum: + enabled: true + contacts: + enabled: true + calendar: + enabled: true + notes: + enabled: true + deck: + enabled: true + # remove unneeded application + firstrunwizard: + enabled: false + dashboard: + enabled: false + memories: + enabled: false + +# -- default quota for an user +quota: + + +ingress: + # -- default: fs.(Values.commons.ingress.domain) + host: + annotations: + +database: + # -- default is from mysql-services + host: mycloud-services-postgresql + name: nextcloud + username: nextcloud + # -- generated by .Values.commons.masterPassword (equal to mycloud-services) + password: + +mail: + # -- generade by Values.commons.mail.from + from: + # -- default Values.commons.mail.host + host: + authtype: PLAIN + # other settings are taken from commons + +persistence: + main: + pvc: "nextcloud" + size: 8Gi + data: + pvc: "nextcloud-data" + size: 16Gi