Deploy Nextcloud on Kubernetes



This content originally appeared on DEV Community and was authored by Harry Tang

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

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.

  1. Prepare the ENVs

I set up the environment variables for Nextcloud’s user credentials, SMTP mail server, and MinIO credentials:

```bash
export NEXTCLOUD_ADMIN_USER=harry
export NEXTCLOUD_ADMIN_PASSWORD=$(openssl rand -base64 32)
export SMTP_HOST=smtp.eu.mailgun.org
export SMTP_USER=nextcloud@notify.harrytang.com
export SMTP_PASSWORD=YOUR_SMTP_PASSWORD
export MINIO_ACCESS_KEY=YOUR_MINIO_ACCESS_KEY
export MINIO_SECRET_KEY=YOUR_MINIO_SECRET_KEY
```
  1. 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   
  1. Create the Certificate

    I use a wildcard certificate to access Nextcloud both from home and remotely via the domains homecloud.harrytang.com and nextcloud.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
    
  2. 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    
    
  3. 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
    ...
    
  4. 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.

References


This content originally appeared on DEV Community and was authored by Harry Tang