Skip to content

Version Management

The operator uses a NextcloudVersionMap CRD to map Nextcloud versions to compatible Helm chart versions and optional container image defaults.

How Version Resolution Works

When you set spec.version on a Nextcloud or NextcloudInstance resource, the operator resolves it through the following priority chain:

  1. spec.helm.version (escape hatch) -- bypasses all mapping, uses the exact chart version specified
  2. ConfigMap override (deprecated) -- nextcloud-operator-version-map ConfigMap in the operator namespace
  3. NextcloudVersionMap CRD -- the default instance contains all known-good mappings
  4. Alias resolution -- latest, stable resolve to a specific NC version
  5. Prefix resolution -- "33" resolves to the latest known 33.x.y patch

If the instance does not set spec.version itself, the operator falls back to its profile's defaults.version (when one is defined) before defaulting to the stable alias. So the effective version source order is: instance spec.version → profile defaults.versionstable alias. See Profile-Level Version Pinning below.

Default Version Map

The operator ships a NextcloudVersionMap/default resource containing all tested version mappings. It is installed automatically via Helm or make deploy.

apiVersion: k8s.bnerd.com/v1alpha1
kind: NextcloudVersionMap
metadata:
  name: default
spec:
  aliases:
    latest: "33.0.3"
    stable: "33.0.3"
  versions:
    "33.0.3":
      chartVersion: "9.0.6"
    "32.0.9":
      chartVersion: "8.9.1"
    # ... more versions

Customizing the Version Map

To add new versions, override chart versions, or set custom images, edit the default NextcloudVersionMap:

kubectl edit nextcloudversionmap default

Adding a New Version

spec:
  versions:
    "33.0.4":
      chartVersion: "9.1.0"

Using Custom Images

Each version entry can include an image block to set the default container image:

spec:
  versions:
    "33.0.2":
      chartVersion: "9.0.5"
      image:
        repository: my-registry.example.com/nextcloud
        tag: "33.0.2-apache"
        pullPolicy: IfNotPresent
        pullSecrets:
          - name: my-registry-credentials

Per-Instance Image Overrides

You can override the container image at the instance level using spec.image:

apiVersion: k8s.bnerd.com/v1alpha1
kind: Nextcloud
metadata:
  name: my-instance
spec:
  version: "33.0.2"
  image:
    repository: my-registry.example.com/nextcloud-custom
    tag: "33.0.2-enterprise"
    pullSecrets:
      - name: my-registry-credentials

Image Resolution Priority

Images are resolved from multiple sources. The highest-priority source wins:

Priority Source Description
1 (highest) spec.helm.values.image Escape hatch -- raw Helm values
2 spec.image Per-instance override
3 Profile defaults.image Profile-level default
4 Version map entry image Per-version default from CRD
5 (lowest) Helm chart default Upstream nextcloud image

Pull secrets from multiple levels are merged (not overridden), so version map and instance secrets are combined.

Private Registry Setup

To use a private registry:

  1. Create an image pull secret in the instance namespace:

    kubectl create secret docker-registry my-registry-credentials \
      --docker-server=my-registry.example.com \
      --docker-username=user \
      --docker-password=pass \
      -n my-namespace
    
  2. Reference it in the version map or instance spec:

    spec:
      image:
        repository: my-registry.example.com/nextcloud
        pullSecrets:
          - name: my-registry-credentials
    

Profile-Level Image Defaults

Profiles can set image defaults for all instances using the profile:

apiVersion: k8s.bnerd.com/v1alpha1
kind: NextcloudProfile
metadata:
  name: enterprise
spec:
  description: Enterprise profile with custom registry
  defaults:
    image:
      repository: my-registry.example.com/nextcloud-enterprise
      pullPolicy: Always
      pullSecrets:
        - name: enterprise-registry
    replicaCount: 2
    resources:
      requests:
        cpu: 1000m
        memory: 1Gi

Profile-Level Version Pinning

Profiles can pin the Nextcloud version for every instance using the profile via spec.defaults.version. Useful for multi-tenant clusters that want to roll the whole fleet to a known-good version without touching every NCI:

apiVersion: k8s.bnerd.com/v1alpha1
kind: NextcloudProfile
metadata:
  name: nextcloud-31-pinned
spec:
  description: Pin all instances to the latest Nextcloud 31.x
  defaults:
    version: "31"            # Resolved via NextcloudVersionMap → latest 31.x
    replicaCount: 2

Instances reference it without their own spec.version:

apiVersion: k8s.bnerd.com/v1alpha1
kind: NextcloudInstance
metadata:
  name: tenant-a
spec:
  profile: nextcloud-31-pinned

defaults.version accepts the same forms as spec.version -- exact ("31.0.8"), prefix ("31"), and aliases ("latest", "stable"). An explicit spec.version on the instance always overrides the profile-pinned value. See examples/profile-pinned-version.yaml for a complete example.

Propagating VersionMap Changes to Running Instances

Edits to the NextcloudVersionMap/default CRD do not automatically reconcile already-running NextcloudInstances. Version resolution is only re-run when the instance's spec changes, when the k8s.bnerd.com/reconcile annotation is bumped, or when the operator restarts. An instance pinned to spec.version: latest keeps its old chart version when the latest alias is repointed — by design, to prevent surprise upgrades.

Three ways to apply a VersionMap change:

  1. Manual trigger (per instance):
    kubectl annotate nextcloudinstance my-nc \
      k8s.bnerd.com/reconcile=$(date +%s) -n my-ns --overwrite
    
  2. Auto-update in the maintenance window: set spec.maintenance.autoUpdate: true together with spec.maintenance.windowStart. The 15-minute maintenance timer will notice drift inside the window and trigger an upgrade automatically. Post-upgrade tasks run on the next tick. Example:
    spec:
      version: latest
      maintenance:
        autoUpdate: true
        windowStart: 2   # 02:00-06:00 UTC
    
  3. Operator restart: kopf replays create/update events for every resource at startup, which re-runs version resolution. Acceptable for planned cutovers, blunt for everyday use.

Migrating from ConfigMap Overrides

If you previously used the nextcloud-operator-version-map ConfigMap:

  1. The ConfigMap still works (for backwards compatibility) but is deprecated
  2. ConfigMap entries override CRD entries with the same version key
  3. To migrate, add your ConfigMap entries to the NextcloudVersionMap/default CRD
  4. Delete the ConfigMap once migrated

The operator logs a warning when ConfigMap overrides are detected.