Deploy Nextcloud on Kubernetes

Nextcloud on K8s
Nextcloud on K8s

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:

    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
    
  2. 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   
    
  3. 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
    
  4. 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    
    
  5. 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
    ...
    
  6. 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

Comments