Deploy Nextcloud on Kubernetes

Introduction
Nextcloud is an open-source data storage solution that you can self-host at home. This article shows how I deployed Nextcloud on my home Kubernetes cluster.
Prerequisites
- A Kubernetes cluster.
- MariaDB (see Deploy MariaDB Galera with MaxScale on Kubernetes).
- MinIO (see Deploy MinIO in Kubernetes with Tenant Separation).
- FluxCD.
- Sealed Secrets.
- SMTP provider.
- Cert Manager.
- CloudFlare Tunnel.
Step-by-step Guide
I used FluxCD to manage my YAML files in Git, following the GitOps approach. However, you can also use standard Helm commands for the HelmRelease
.
-
Prepare the ENVs
I set up the environment variables for Nextcloud's user credentials, SMTP mail server, and MinIO credentials:
export NEXTCLOUD_ADMIN_USER=harry export NEXTCLOUD_ADMIN_PASSWORD=$(openssl rand -base64 32) export SMTP_HOST=smtp.eu.mailgun.org export [email protected] export SMTP_PASSWORD=YOUR_SMTP_PASSWORD export MINIO_ACCESS_KEY=YOUR_MINIO_ACCESS_KEY export MINIO_SECRET_KEY=YOUR_MINIO_SECRET_KEY
-
Create Sealed Secrets
kubectl -n nextcloud create secret generic nextcloud-secrets --dry-run=client --from-literal=nextcloud-password=$NEXTCLOUD_ADMIN_PASSWORD \ --from-literal=nextcloud-username=$NEXTCLOUD_ADMIN_USER \ --from-literal=smtp-host=$SMTP_HOST \ --from-literal=smtp-username=$SMTP_USER \ --from-literal=smtp-password=$SMTP_PASSWORD \ --from-literal=minio-access-key=$MINIO_ACCESS_KEY \ --from-literal=minio-secret-key=$MINIO_SECRET_KEY \ -o yaml | kubeseal --format=yaml > sealed-secret.yaml
-
Create the Certificate
I use a wildcard certificate to access Nextcloud both from home and remotely via the domains
homecloud.harrytang.com
andnextcloud.harrytang.com
, respectively.apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: harrytang-com namespace: nextcloud spec: secretName: harrytang-com-tls dnsNames: - 'harrytang.com' - '*.harrytang.com' issuerRef: name: letsencrypt kind: ClusterIssuer
-
Deploy Ingress
I use Nginx Ingress to expose Nextcloud within my home network (by adding an A record to my domain):
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: nextcloud namespace: nextcloud annotations: nginx.ingress.kubernetes.io/proxy-body-size: 100G nginx.ingress.kubernetes.io/proxy-read-timeout: '86400' nginx.ingress.kubernetes.io/proxy-send-timeout: '86400' nginx.ingress.kubernetes.io/proxy-connect-timeout: '86400' spec: tls: - hosts: - homecloud.harrytang.com secretName: harrytang-com-tls rules: - host: homecloud.harrytang.com http: paths: - path: / pathType: Prefix backend: service: name: nextcloud port: number: 8080
-
Config CloudFlare Tunnel
Configure Cloudflare Tunnel to acess your Nextcloud remotely and securely:
... ingress: # https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/configure-tunnels/origin-configuration/#tls-settings - hostname: nextcloud.harrytang.com service: http://nextcloud.nextcloud:8080 ...
-
Deploy Nextcloud
Finally, after setting everything up, I deployed Nextcloud:
--- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: nextcloud namespace: nextcloud spec: interval: 24h url: https://nextcloud.github.io/helm/ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: nextcloud namespace: nextcloud spec: interval: 24h chart: spec: chart: nextcloud version: '~6.6.4' sourceRef: kind: HelmRepository name: nextcloud namespace: nextcloud interval: 24h values: replicaCount: 1 livenessProbe: initialDelaySeconds: 180 readinessProbe: initialDelaySeconds: 180 nextcloud: update: true host: nextcloud.harrytang.com trustedDomains: - nextcloud.harrytang.com - homecloud.harrytang.com existingSecret: enabled: true secretName: nextcloud-secrets mail: enabled: true fromAddress: noreply domain: harrytang.com objectStore: s3: enabled: true bucket: nextcloud usePathStyle: true host: minio.nextcloud.svc.cluster.local existingSecret: nextcloud-secrets secretKeys: accessKey: minio-access-key secretKey: minio-secret-key ssl: false port: 80 configs: proxy.config.php: |- <?php $CONFIG = array ( 'trusted_proxies' => array( 0 => '127.0.0.1', 1 => '10.0.0.0/8', ), 'forwarded_for_headers' => array('HTTP_X_FORWARDED_FOR'), ); zz.config.php: |- <?php $CONFIG = array ( 'trusted_domains' => array( 0 => 'localhost', 1 => 'nextcloud.harrytang.com', 2 => 'homecloud.harrytang.com', ), ); phpConfigs: zz-custom.ini: |- memory_limit=1024M upload_max_filesize=100G post_max_size=100G max_execution_time=86400 max_input_time=86400 extraVolumes: - name: private-ca configMap: name: private-ca items: - key: private-ca.pem path: private-ca.crt extraVolumeMounts: - name: private-ca mountPath: /usr/local/share/ca-certificates readOnly: true lifecycle: postStartCommand: - update-ca-certificates persistence: enabled: true accessMode: ReadWriteMany phpClientHttpsFix: enabled: true cronjob: enabled: false internalDatabase: enabled: false externalDatabase: enabled: true type: mysql host: maxscale-galera.nextcloud.svc.cluster.local database: nextcloud existingSecret: enabled: true secretName: mariadb usernameKey: mariadb-username passwordKey: mariadb-password
Conclusion
Running Nextcloud on your home lab Kubernetes cluster provides a secure and private way to store your data. You can store unlimited photos and videos for yourself and your family while accessing them from anywhere.