# services/nextcloud/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nextcloud namespace: nextcloud labels: app: nextcloud spec: replicas: 1 selector: matchLabels: app: nextcloud template: metadata: labels: app: nextcloud annotations: vault.hashicorp.com/agent-inject: "true" vault.hashicorp.com/agent-init-first: "true" vault.hashicorp.com/role: "nextcloud" vault.hashicorp.com/agent-inject-secret-nextcloud-env.sh: "kv/data/atlas/nextcloud/nextcloud-db" vault.hashicorp.com/agent-inject-template-nextcloud-env.sh: | {{ with secret "kv/data/atlas/nextcloud/nextcloud-db" }} export POSTGRES_DB="{{ .Data.data.database }}" export POSTGRES_USER="{{ index .Data.data "db-username" }}" export POSTGRES_PASSWORD="{{ index .Data.data "db-password" }}" {{ end }} {{ with secret "kv/data/atlas/nextcloud/nextcloud-admin" }} export NEXTCLOUD_ADMIN_USER="{{ index .Data.data "admin-user" }}" export NEXTCLOUD_ADMIN_PASSWORD="{{ index .Data.data "admin-password" }}" {{ end }} export ADMIN_USER="${NEXTCLOUD_ADMIN_USER}" export ADMIN_PASS="${NEXTCLOUD_ADMIN_PASSWORD}" {{ with secret "kv/data/atlas/nextcloud/nextcloud-oidc" }} export OIDC_CLIENT_ID="{{ index .Data.data "client-id" }}" export OIDC_CLIENT_SECRET="{{ index .Data.data "client-secret" }}" {{ end }} {{ with secret "kv/data/atlas/shared/postmark-relay" }} export SMTP_NAME="{{ index .Data.data "relay-username" }}" export SMTP_PASSWORD="{{ index .Data.data "relay-password" }}" {{ end }} {{ with secret "kv/data/atlas/shared/keycloak-admin" }} export KC_ADMIN_USER="{{ .Data.data.username }}" export KC_ADMIN_PASS="{{ .Data.data.password }}" {{ end }} spec: nodeSelector: hardware: rpi5 securityContext: fsGroup: 33 runAsUser: 33 runAsGroup: 33 serviceAccountName: nextcloud-vault initContainers: - name: seed-nextcloud-web image: nextcloud:29-apache command: ["/bin/sh", "-c"] args: - | if [ ! -f /var/www/html/version.php ]; then echo "Seeding Nextcloud webroot..." tar -C /usr/src/nextcloud -cf - \ --exclude=./config \ --exclude=./data \ --exclude=./custom_apps \ . | tar -C /var/www/html -xf - chown -R 33:33 /var/www/html || true fi securityContext: runAsUser: 0 runAsGroup: 0 volumeMounts: - name: nextcloud-web mountPath: /var/www/html - name: fix-perms image: alpine:3.20 command: ["/bin/sh", "-c"] args: - | if [ ! -s /var/www/html/config/config.php ]; then rm -f /var/www/html/config/config.php || true fi mkdir -p /var/www/html/config /var/www/html/data /var/www/html/custom_apps || true if [ ! -s /var/www/html/config/config.php ]; then rm -f /var/www/html/data/.ocdata || true fi if [ -s /var/www/html/config/config.php ] && [ ! -f /var/www/html/data/.ocdata ]; then touch /var/www/html/data/.ocdata fi chown -R 33:33 /var/www/html/config /var/www/html/data /var/www/html/custom_apps || true securityContext: runAsUser: 0 runAsGroup: 0 volumeMounts: - name: nextcloud-config-pvc mountPath: /var/www/html/config - name: nextcloud-custom-apps mountPath: /var/www/html/custom_apps - name: nextcloud-user-data mountPath: /var/www/html/data - name: nextcloud-config-extra mountPath: /var/www/html/config/extra.config.php subPath: extra.config.php - name: install-nextcloud image: nextcloud:29-apache securityContext: runAsUser: 0 runAsGroup: 0 command: ["/bin/sh", "-c"] args: - | . /vault/secrets/nextcloud-env.sh installed="$(su -s /bin/sh www-data -c "php /var/www/html/occ status" 2>/dev/null | awk '/installed:/{print $3}' || true)" if [ ! -s /var/www/html/config/config.php ]; then su -s /bin/sh www-data -c "php /var/www/html/occ maintenance:install --database pgsql --database-host \"${POSTGRES_HOST}\" --database-name \"${POSTGRES_DB}\" --database-user \"${POSTGRES_USER}\" --database-pass \"${POSTGRES_PASSWORD}\" --admin-user \"${NEXTCLOUD_ADMIN_USER}\" --admin-pass \"${NEXTCLOUD_ADMIN_PASSWORD}\" --data-dir /var/www/html/data" chown 33:33 /var/www/html/config/config.php || true chown -R 33:33 /var/www/html/data || true fi installed="$(su -s /bin/sh www-data -c "php /var/www/html/occ status" 2>/dev/null | awk '/installed:/{print $3}' || true)" if [ "${installed}" = "true" ]; then configure_oidc() { su -s /bin/sh www-data -c "php /var/www/html/occ config:system:set oidc_login_provider_url --value='https://sso.bstein.dev/realms/atlas'" su -s /bin/sh www-data -c "php /var/www/html/occ config:system:set oidc_login_client_id --value='${OIDC_CLIENT_ID}'" su -s /bin/sh www-data -c "php /var/www/html/occ config:system:set oidc_login_client_secret --value='${OIDC_CLIENT_SECRET}'" su -s /bin/sh www-data -c "php /var/www/html/occ config:system:set oidc_login_auto_redirect --type=boolean --value=true" su -s /bin/sh www-data -c "php /var/www/html/occ config:system:set oidc_login_hide_password_form --type=boolean --value=true" su -s /bin/sh www-data -c "php /var/www/html/occ config:system:set oidc_login_disable_registration --type=boolean --value=false" } configure_office() { su -s /bin/sh www-data -c "php /var/www/html/occ config:app:set richdocuments wopi_url --value='https://office.bstein.dev'" su -s /bin/sh www-data -c "php /var/www/html/occ config:app:set richdocuments public_wopi_url --value='https://office.bstein.dev'" } ensure_mime_defaults() { cfg_dir="/var/www/html/resources/config" mkdir -p "${cfg_dir}" if [ ! -s "${cfg_dir}/mimetypemapping.dist.json" ]; then curl -fsSL https://raw.githubusercontent.com/nextcloud/server/v29.0.16/resources/config/mimetypemapping.dist.json -o "${cfg_dir}/mimetypemapping.dist.json" || true fi if [ ! -s "${cfg_dir}/mimetypealiases.dist.json" ]; then curl -fsSL https://raw.githubusercontent.com/nextcloud/server/v29.0.16/resources/config/mimetypealiases.dist.json -o "${cfg_dir}/mimetypealiases.dist.json" || true fi chown -R 33:33 "${cfg_dir}" || true } install_app() { app="$1" url="$2" target="/var/www/html/custom_apps/${app}" rm -rf "${target}" mkdir -p /tmp/nextcloud-apps curl -fsSL "${url}" -o "/tmp/nextcloud-apps/${app}.tar.gz" tar -xzf "/tmp/nextcloud-apps/${app}.tar.gz" -C /var/www/html/custom_apps rm -f "/tmp/nextcloud-apps/${app}.tar.gz" chown -R 33:33 "${target}" su -s /bin/sh www-data -c "php /var/www/html/occ app:enable --force ${app}" || true } reset_external_config() { su -s /bin/sh www-data -c "php /var/www/html/occ app:remove external" || true su -s /bin/sh www-data -c "php /var/www/html/occ config:app:delete external jwt_token_privkey_es256" || true su -s /bin/sh www-data -c "php /var/www/html/occ config:app:delete external jwt_token_pubkey_es256" || true su -s /bin/sh www-data -c "php /var/www/html/occ config:app:delete external jwt_token_privkey_ed25519" || true su -s /bin/sh www-data -c "php /var/www/html/occ config:app:delete external jwt_token_pubkey_ed25519" || true } ensure_app() { app="$1" target="/var/www/html/custom_apps/${app}" rm -rf "${target}" su -s /bin/sh www-data -c "php /var/www/html/occ app:remove ${app}" || true su -s /bin/sh www-data -c "php /var/www/html/occ app:install --force ${app}" || true su -s /bin/sh www-data -c "php /var/www/html/occ app:enable --force ${app}" || true } ensure_mime_defaults reset_external_config install_app external https://github.com/nextcloud-releases/external/releases/download/v5.4.1/external-v5.4.1.tar.gz install_app mail https://github.com/nextcloud-releases/mail/releases/download/v3.7.24/mail-stable3.7.tar.gz install_app oidc_login https://github.com/pulsejet/nextcloud-oidc-login/releases/download/v3.2.2/oidc_login.tar.gz ensure_app richdocuments configure_office configure_oidc fi env: - name: POSTGRES_HOST value: postgres-service.postgres.svc.cluster.local volumeMounts: - name: nextcloud-web mountPath: /var/www/html - name: nextcloud-config-pvc mountPath: /var/www/html/config - name: nextcloud-custom-apps mountPath: /var/www/html/custom_apps - name: nextcloud-user-data mountPath: /var/www/html/data - name: nextcloud-config-extra mountPath: /var/www/html/config/extra.config.php subPath: extra.config.php containers: - name: nextcloud image: nextcloud:29-apache imagePullPolicy: IfNotPresent command: ["/bin/sh", "-c"] args: - >- . /vault/secrets/nextcloud-env.sh && exec /entrypoint.sh apache2-foreground env: # DB (external secret required: nextcloud-db with keys username,password,database) - name: POSTGRES_HOST value: postgres-service.postgres.svc.cluster.local # Admin bootstrap (external secret: nextcloud-admin with keys admin-user, admin-password) - name: NEXTCLOUD_TRUSTED_DOMAINS value: cloud.bstein.dev - name: OVERWRITEHOST value: cloud.bstein.dev - name: OVERWRITEPROTOCOL value: https - name: OVERWRITECLIURL value: https://cloud.bstein.dev # SMTP (external secret: nextcloud-smtp with keys username, password) - name: SMTP_HOST value: smtp.postmarkapp.com - name: SMTP_PORT value: "587" - name: SMTP_SECURE value: tls - name: MAIL_FROM_ADDRESS value: no-reply-nextcloud - name: MAIL_DOMAIN value: bstein.dev # OIDC (external secret: nextcloud-oidc with keys client-id, client-secret) - name: NEXTCLOUD_UPDATE value: "1" - name: APP_INSTALL value: "mail,oidc_login,external" ports: - containerPort: 80 name: http volumeMounts: - name: nextcloud-web mountPath: /var/www/html - name: nextcloud-config-pvc mountPath: /var/www/html/config - name: nextcloud-custom-apps mountPath: /var/www/html/custom_apps - name: nextcloud-user-data mountPath: /var/www/html/data - name: nextcloud-config-extra mountPath: /var/www/html/config/extra.config.php subPath: extra.config.php resources: requests: cpu: 250m memory: 1Gi limits: cpu: 1 memory: 3Gi volumes: - name: nextcloud-web persistentVolumeClaim: claimName: nextcloud-web-v2 - name: nextcloud-config-pvc persistentVolumeClaim: claimName: nextcloud-config-v2 - name: nextcloud-custom-apps persistentVolumeClaim: claimName: nextcloud-custom-apps-v2 - name: nextcloud-user-data persistentVolumeClaim: claimName: nextcloud-user-data-v2 - name: nextcloud-config-extra configMap: name: nextcloud-config defaultMode: 0444