Skip to content

CRD Overview

Custom Resource Definitions

The Nextcloud Operator provides the following CRDs:

  • Nextcloud (nc) — Tenant-facing logical resource (namespaced)
  • NextcloudInstance (nci) — Physical Nextcloud instance resource (namespaced)
  • NextcloudPool (ncp) — Pre-provisioned instance pool management (cluster-scoped)
  • NextcloudProfile (ncprofile) — Reusable configuration profiles (cluster-scoped)
  • NextcloudVersionMap (ncvm) — Version-to-chart mapping and default images (cluster-scoped)
  • SignalingServer (ss) — HPB signaling server backend registration (cluster-scoped)
  • RecordingServer (rs) — Talk recording server backend registration (cluster-scoped)
  • NextcloudCommand (nccmd) — Ad-hoc occ command runner (namespaced). See the Commands guide.

API Version: k8s.bnerd.com/v1alpha1

For the full interactive API specification, see the OpenAPI / Swagger page.

API Resources

NextcloudInstance Resource

Minimal Example

apiVersion: k8s.bnerd.com/v1alpha1
kind: NextcloudInstance
metadata:
  name: my-nextcloud
  namespace: default
spec:
  profile: production
  ingress:
    host: cloud.example.com

Complete Example

apiVersion: k8s.bnerd.com/v1alpha1
kind: NextcloudInstance
metadata:
  name: production-nextcloud
  namespace: nextcloud
  labels:
    environment: production
spec:
  profile: production
  version: "29"
  replicas: 3

  ingress:
    enabled: true
    host: cloud.company.com
    className: nginx
    annotations:
      cert-manager.io/cluster-issuer: letsencrypt-prod
    tls:
      enabled: true

  database:
    type: postgresql
    managed: true
    postgres:
      replicas: 3
      storage:
        size: 50Gi
      backup:
        enabled: true
        s3:
          bucket: pg-backups
          endpoint: s3.example.com
          credentialsSecret: backup-s3-creds

  redis:
    enabled: true
    credentialsSecret: nextcloud-redis-creds

  s3:
    enabled: true
    credentialsSecret: nextcloud-s3-creds

  backups:
    data:
      enabled: true
      bucket: nextcloud-backups
      endpoint: s3.example.com
      region: eu-central-1
      credentialsSecret: nextcloud-backup-creds
      schedule: "0 3 * * *"
      deleteOnCleanup: false

  admin:
    credentialsSecret: nextcloud-admin-creds

  mail:
    enabled: true
    credentialsSecret: nextcloud-mail-creds

  resources:
    requests:
      cpu: 1000m
      memory: 2Gi
    limits:
      cpu: 4000m
      memory: 8Gi

  persistence:
    enabled: true
    size: 100Gi
    storageClass: fast-ssd

NextcloudProfile Resource

apiVersion: k8s.bnerd.com/v1alpha1
kind: NextcloudProfile
metadata:
  name: high-performance
spec:
  description: High-performance profile for production workloads
  defaults:
    version: "stable"        # Pins NC version for instances using this profile
    replicaCount: 3
    resources:
      requests:
        cpu: 2000m
        memory: 4Gi
      limits:
        cpu: 8000m
        memory: 16Gi
    persistence:
      enabled: true
      size: 200Gi
      storageClass: fast-ssd
    internalDatabase:
      enabled: false
  helm:
    version: "5.0.0"          # Helm chart version (escape hatch)

spec.defaults accepts both raw Helm chart values and these instance spec-level fields, which the operator pulls into the instance spec once, at instance creation (see Profiles → When Profiles Apply — a later profile edit does not retroactively apply): version, image, database, redis, s3, admin, mail, ingress, oidc, apps, backups, maintenance, persistence, cronjob, livenessProbe, readinessProbe, startupProbe, resources, replicas, php, extraVolumes, extraVolumeMounts, hooks, placement, upgradePolicy. Instance values win on conflict (deep-merge, except hooks which replaces wholesale). See the Profiles guide for a worked example.

API Endpoints

Nextcloud Endpoints

GET    /apis/k8s.bnerd.com/v1alpha1/namespaces/{namespace}/nextclouds
GET    /apis/k8s.bnerd.com/v1alpha1/namespaces/{namespace}/nextclouds/{name}
POST   /apis/k8s.bnerd.com/v1alpha1/namespaces/{namespace}/nextclouds
PUT    /apis/k8s.bnerd.com/v1alpha1/namespaces/{namespace}/nextclouds/{name}
DELETE /apis/k8s.bnerd.com/v1alpha1/namespaces/{namespace}/nextclouds/{name}

NextcloudInstance Endpoints

GET    /apis/k8s.bnerd.com/v1alpha1/namespaces/{namespace}/nextcloudinstances
GET    /apis/k8s.bnerd.com/v1alpha1/namespaces/{namespace}/nextcloudinstances/{name}
POST   /apis/k8s.bnerd.com/v1alpha1/namespaces/{namespace}/nextcloudinstances
PUT    /apis/k8s.bnerd.com/v1alpha1/namespaces/{namespace}/nextcloudinstances/{name}
DELETE /apis/k8s.bnerd.com/v1alpha1/namespaces/{namespace}/nextcloudinstances/{name}

NextcloudProfile Endpoints (Cluster-Scoped)

GET    /apis/k8s.bnerd.com/v1alpha1/nextcloudprofiles
GET    /apis/k8s.bnerd.com/v1alpha1/nextcloudprofiles/{name}
POST   /apis/k8s.bnerd.com/v1alpha1/nextcloudprofiles
PUT    /apis/k8s.bnerd.com/v1alpha1/nextcloudprofiles/{name}
DELETE /apis/k8s.bnerd.com/v1alpha1/nextcloudprofiles/{name}

Nextcloud safe-fallback contract: the operator validates every reference on the Nextcloud CR (spec.profile, spec.poolSelector) before doing any work. If a reference can't be honoured (typo'd profile, empty pool), it blocks with an InstanceAssigned=False condition + Warning event and retries every 60 s — never silently spawning a misconfigured instance. See Pool design — Modes, validation, and the safe-fallback contract.

NextcloudPool Endpoints (Cluster-Scoped)

GET    /apis/k8s.bnerd.com/v1alpha1/nextcloudpools
GET    /apis/k8s.bnerd.com/v1alpha1/nextcloudpools/{name}
POST   /apis/k8s.bnerd.com/v1alpha1/nextcloudpools
PUT    /apis/k8s.bnerd.com/v1alpha1/nextcloudpools/{name}
DELETE /apis/k8s.bnerd.com/v1alpha1/nextcloudpools/{name}

Notable lifecycle/status fields:

Field Type Description
spec.lifecycle.recreateOnProfileChange boolean (default false) When true, deletes unassigned pool instances when the referenced profile changes — either profileRef.name swap or content edit (detected via SHA256 digest by the reconcile timer). Assigned instances are sticky and never recreated. See Pool design — Profile changes and instance recreation.
status.observedProfile.{name,digest,observedAt} object Last observed profile snapshot used for content-change detection. Always recorded for observability.

SignalingServer Endpoints (Cluster-Scoped)

GET    /apis/k8s.bnerd.com/v1alpha1/signalingservers
GET    /apis/k8s.bnerd.com/v1alpha1/signalingservers/{name}
POST   /apis/k8s.bnerd.com/v1alpha1/signalingservers
PUT    /apis/k8s.bnerd.com/v1alpha1/signalingservers/{name}
DELETE /apis/k8s.bnerd.com/v1alpha1/signalingservers/{name}

RecordingServer Endpoints (Cluster-Scoped)

GET    /apis/k8s.bnerd.com/v1alpha1/recordingservers
GET    /apis/k8s.bnerd.com/v1alpha1/recordingservers/{name}
POST   /apis/k8s.bnerd.com/v1alpha1/recordingservers
PUT    /apis/k8s.bnerd.com/v1alpha1/recordingservers/{name}
DELETE /apis/k8s.bnerd.com/v1alpha1/recordingservers/{name}

NextcloudCommand Endpoints

GET    /apis/k8s.bnerd.com/v1alpha1/namespaces/{namespace}/nextcloudcommands
GET    /apis/k8s.bnerd.com/v1alpha1/namespaces/{namespace}/nextcloudcommands/{name}
POST   /apis/k8s.bnerd.com/v1alpha1/namespaces/{namespace}/nextcloudcommands
DELETE /apis/k8s.bnerd.com/v1alpha1/namespaces/{namespace}/nextcloudcommands/{name}

NextcloudCommand.spec is immutable — PUT/PATCH to spec is rejected by the operator. Re-run by creating a new resource.

spec.lifecycle is OnDemand (default) or OnReady. OnReady waits for the target instance to be Ready (and to have a Running+Ready pod) before running. spec.beforeScript is an optional bash setup script executed via /bin/bash -c before commands; non-zero exit fails the run and skips commands.

Operator-managed lifecycle hooks are declared on NextcloudInstance.spec.hooks (or upstream Nextcloud / Profile / Pool) and materialized as NCCs at three triggers:

  • onFirstReady — once per instance, on the first-ever Ready.
  • onAssignmentReady — once per assignment event (pool instance bound to a Nextcloud).
  • onEveryReady — every Ready edge (fresh NCC per edge; bounded by NCC TTL).

A hook NCC ending in Failed surfaces as a LifecycleHookFailed=True condition on the NCI; the NCI's own phase stays Ready. See the Commands guide for details.

Using the API

With kubectl

# Create a Nextcloud instance
kubectl apply -f nextcloudinstance.yaml

# List instances
kubectl get nci -n nextcloud

# Get instance details
kubectl describe nci my-nextcloud -n nextcloud

# Delete instance
kubectl delete nci my-nextcloud -n nextcloud

With Python (Kubernetes Client)

from kubernetes import client, config

config.load_kube_config()
api = client.CustomObjectsApi()

# List Nextcloud instances
nextclouds = api.list_namespaced_custom_object(
    group="k8s.bnerd.com",
    version="v1alpha1",
    namespace="default",
    plural="nextclouds"
)

# Create instance
body = {
    "apiVersion": "k8s.bnerd.com/v1alpha1",
    "kind": "Nextcloud",
    "metadata": {"name": "my-nextcloud"},
    "spec": {
        "profile": "production",
        "poolSelector": {"matchLabels": {"pool": "default"}}
    }
}

api.create_namespaced_custom_object(
    group="k8s.bnerd.com",
    version="v1alpha1",
    namespace="default",
    plural="nextclouds",
    body=body
)

Field Reference

NextcloudInstance Spec Fields

Field Type Default Description
profile string - Profile to use (production, testing, development, or custom)
version string 29 Nextcloud version (Docker tag)
image object - Custom container image (overrides version map and profile defaults)
image.repository string - Container image repository
image.tag string - Container image tag
image.pullPolicy string - Pull policy (Always, IfNotPresent, Never)
image.pullSecrets array - Image pull secrets for private registries
replicas integer 1 Number of pod replicas
ingress object - Ingress configuration
database object - Database configuration
redis object - Redis configuration
s3 object - S3 object storage configuration
admin object - Admin credentials
mail object - Mail/SMTP configuration
oidc object - OIDC/SSO configuration
resources object - Resource requests/limits
persistence object - Persistent storage configuration
cronjob object - Cron job configuration
livenessProbe object - Liveness probe overrides
readinessProbe object - Readiness probe overrides
startupProbe object - Startup probe overrides
license_key string - Nextcloud Enterprise license key
apps object - Declarative Nextcloud app management
backups object - Automated backup configuration: backups.data (S3 backup of Nextcloud files) and backups.config (encrypted configuration bundle)
upgradePolicy object - Declarative automatic-upgrade policy — see Upgrade Automation below
php object - PHP / FPM / Apache MPM / preview tuning. Sane defaults shipped in every built-in profile prevent image-upload from blocking the instance. See the PHP & Preview Tuning guide.
extraVolumes array - Extra volumes appended to the Nextcloud pod (chart nextcloud.extraVolumes).
extraVolumeMounts array - Extra volume mounts on the Nextcloud container (chart nextcloud.extraVolumeMounts).
helm object - Helm chart/values overrides
placement object - Pod scheduling constraints for the Nextcloud app and cron pod (nodeSelector, tolerations, affinity, topologySpreadConstraints). See Workload Placement.

Ingress Configuration

Field Type Default Description
enabled boolean true Enable ingress. Set to false to disable external access.
host string - Hostname for the ingress (e.g., nextcloud.example.com). Required if enabled=true.
className string nginx IngressClass to use (e.g., nginx, traefik)
annotations object - Additional annotations for the ingress
tls.enabled boolean true Enable TLS/HTTPS
tls.secretName string - Name of TLS secret (defaults to <instance-name>-tls)
tls.certManager boolean true Manage the TLS certificate via cert-manager. When true, the operator injects the cert-manager.io/cluster-issuer: letsencrypt-prod annotation (unless a cert-manager.io/cluster-issuer annotation is set explicitly). Set to false to skip annotation injection and bring your own TLS secret via tls.secretName.
trustedProxies array of strings ["10.0.0.0/8"] IP/CIDR ranges of trusted reverse proxies. Auto-sets trusted_proxies in Nextcloud PHP config.
forwardedForHeaders array of strings ["HTTP_X_FORWARDED_FOR"] HTTP headers carrying the real client IP. Auto-sets forwarded_for_headers in Nextcloud PHP config.

When ingress is enabled, the operator automatically configures overwriteprotocol, overwritehost, trusted_proxies, and forwarded_for_headers in Nextcloud's PHP config. This can be overridden by providing a custom bnerd.config.php via spec.helm.values.nextcloud.configs.

To use a manually provisioned TLS certificate instead of Let's Encrypt/cert-manager:

spec:
  ingress:
    host: cloud.example.com
    tls:
      certManager: false
      secretName: my-manual-tls   # pre-existing kubernetes.io/tls secret in the instance namespace

tls.certManager can be set on NextcloudInstance and Nextcloud specs, in a NextcloudPool template (template.spec.ingress.tls.certManager — pair it with a secretName, e.g. a wildcard-cert secret, since pool instances have random names and would otherwise each expect a manually created <instance-name>-tls secret), and in NextcloudProfile defaults (defaults.ingress.tls.certManager). As of 0.20.0, an ingress block on the instance deep-merges with the profile's ingress default field by field (instance wins conflicts, profile fills gaps) rather than replacing it wholesale — see Profiles → How Defaults Merge for the full merge semantics and an important connection-shaped-key caveat.

Database Configuration

Field Type Default Description
type string postgresql Database type (postgresql or mysql)
managed boolean false Create managed PostgreSQL cluster via Percona PG Operator
deleteOnCleanup boolean false Delete the managed PerconaPGCluster when the instance is deleted. Ignored for unmanaged DBs. Note: when the instance owns its namespace, namespace deletion removes the DB regardless — see Deletion & Cleanup
credentialsSecret string - Secret name with credentials (overrides inline values)
host string - Database host (ignored if credentialsSecret set)
port integer 5432 Database port
name string nextcloud Database name
user string nextcloud Database user
password string - Database password
postgres object - PostgreSQL cluster config (only when managed: true)

Data Backup Configuration (spec.backups.data)

Field Type Default Description
enabled boolean false Enable automated S3 data backup
bucket string - S3 bucket name for backup storage
endpoint string - S3-compatible endpoint URL
region string - S3 region
credentialsSecret string - Secret with backup credentials (keys: accessKey, secretKey)
schedule string "0 3 * * *" Cron schedule for backup jobs
deleteOnCleanup boolean false Delete backup data when instance is deleted

Configuration Backup Bundle (spec.backups.config)

Encrypted bundle of config/, the server-side encryption keys, the declarative state, the operator-owned Secrets, custom_apps/ and themes/, uploaded daily to /<namespace>/<instance>/backups/config/<timestamp>.tar.enc in the same bucket as the database backups. See Backup & Restore.

Field Type Default Description
enabled boolean true (operator default) Runs whenever a backup bucket and an encryption key both resolve. No CRD default.
retention integer 14 (operator default) Bundles kept in the bucket; older ones pruned after a successful upload.
schedule string per-instance jittered hour Hour-of-day hint for the daily run.

Database Backup Configuration (spec.database.postgres.backup)

Scheduled pgBackRest backups of the managed PostgreSQL. Enabled by default. See Managed PostgreSQL → Backups.

Field Type Default Description
enabled boolean true (operator default) Set false to opt out. Wins over any operator-central default bucket.
schedule.full / schedule.incremental string jittered per instance Weekly full + 6-hourly incremental; an explicit value is honoured verbatim.
retention.full / retention.differential integer 2 / - Retention for the volume-backed repo1.
volumeSize string "10Gi" enabled / "1Gi" disabled Size of the repo1 volume. Never shrunk on a live cluster.
s3.bucket / s3.endpoint / s3.region string operator-central default Off-cluster repository. Resolved from the instance spec, then the operator's backup.dbDefaultS3.* values, then nothing.
s3.credentialsSecret string - An existing pgBackRest s3.conf Secret in this namespace; used as-is, never overwritten.
s3.credentialsFrom.secretRef.name string operator-central A Secret in this instance's own namespace with plain access keys, rendered into <instance>-pgbackrest-s3. No namespace subfield — see Backup & Restore → Secret-reference confinement.
s3.pathPrefix string "/{namespace}/{instance}/backups/db" Per-instance object prefix. Mandatory in substance: Percona renders the same repo path for every cluster.
s3.mode string alongside alongside adds the S3 target as repo2 and keeps repo1; replace is the pre-0.22.0 in-place behaviour.
s3.retention.full / .differential integer 4 / - Retention for the S3 repository, independent of repo1.
s3.encryption.cipherType string aes-256-cbc Repository encryption algorithm.
s3.encryption.keyFrom.secretRef.{name,key} string operator-central Secret in this instance's own namespace holding the passphrase (key defaults to cipher-pass). By reference only — no inline passphrase field, and no namespace subfield.
s3.usePathStyle boolean false Path-style S3 addressing.

Secret References

All credential sections support credentialsSecret. See Secret Management for details.

Section Secret Keys
database.credentialsSecret host, port, name, user, password
redis.credentialsSecret host, port, password
s3.credentialsSecret bucket, endpoint, region, accessKey, secretKey
admin.credentialsSecret username, password, email
mail.credentialsSecret fromAddress, domain, smtpHost, smtpPort, smtpSecure, smtpAuthType, smtpName, smtpPassword

App Management (spec.apps)

Declarative Nextcloud app management. See below for supported apps.

Well-Known Apps

App key Configuration Description
richdocuments enabled, wopiUrl, wopiAllowlist Nextcloud Office / Collabora
spreed enabled, stunServers, turnServers, signalingServers, recording Nextcloud Talk
calendar enabled Nextcloud Calendar
contacts enabled Nextcloud Contacts
deck enabled Nextcloud Deck (Kanban)
tasks enabled Nextcloud Tasks
notes enabled Nextcloud Notes
mail enabled Nextcloud Mail client
collectives enabled Nextcloud Collectives (team wikis)
whiteboard enabled Nextcloud Whiteboard
forms enabled Nextcloud Forms
admin_audit enabled Admin Audit Log
groupfolders enabled Group Folders
photos enabled Nextcloud Photos
previewgenerator enabled Preview Generator

Custom Apps

apps:
  custom:
    - appId: files_retention
      enabled: true
    - appId: announcementcenter
      enabled: false

Note

Setting enabled: false disables an app. Removing an app entry entirely does not uninstall it — this prevents accidental data loss.

Status

Version Resolution

status:
  versionResolution:
    requestedVersion: "32.0.6"
    resolvedVersion: "32.0.6"
    chartVersion: "8.9.1"
    resolvedBy: crd

Upgrade Path Validation

Every reconcile that changes the resolved Nextcloud version is checked against status.versionResolution.resolvedVersion before the HelmRelease is updated. Downgrades and major-version skips (more than one major ahead, e.g. 30 → 32 in one step) are unsafe; what happens depends on resolvedBy. An explicit choice (resolvedBy: crd, configmap, or spec.helm.version) fails the reconcile with a permanent error. Resolution drift (resolvedBy: alias or prefix — e.g. a NextcloudVersionMap rollback) instead holds the instance on its current chart version and logs a warning, rather than failing it. Same-major patch/minor changes are unaffected either way. Annotation k8s.bnerd.com/allow-unsafe-version-change: "true" bypasses both checks, for documented restore/rollback procedures only. See the Upgrades guide for full details and the rollback runbook.

Upgrade Automation (spec.upgradePolicy)

spec:
  upgradePolicy:
    mode: auto              # manual (default) | auto
    patchUpgrades: true       # mode: auto only — auto-apply same-minor patch drift
    minorUpgrades: false      # mode: auto only — auto-apply same-major minor drift

mode: manual (default) never auto-applies; mode: auto applies a resolved drift only if its class is opted into (patchUpgrades/minorUpgrades, independently) — inside spec.maintenance.windowStart. No majorUpgrades field exists — a major hop is never automated by any flag combination, always requires an explicit spec.version edit, and is still fully subject to Upgrade Path Validation above.

spec.maintenance.autoUpdate: true is a deprecated alias for upgradePolicy: {mode: auto, patchUpgrades: true, minorUpgrades: false}, applied automatically when spec.upgradePolicy is unset. If both are set, upgradePolicy wins outright and a reason: UpgradePolicyAliasIgnored warning event fires. Not removed before 0.21.0. As of 0.20.0 the alias only auto-applies patch drift (previously any same-major drift) — see the Upgrades guide's upgrade notes for this and a second, opposite-direction widening in the same release (drift detection now also catches resolvedVersion-only bumps that were previously invisible to autoUpdate).

NextcloudProfile.spec.defaults.upgradePolicy sets a fleet-wide default, cascading to assigned instances with the same deep-merge semantics as every other profile default — instance values win on conflict, profile values fill gaps. See Profiles → How Defaults Merge.

status.conditions[type=UpdateAvailable] — True/False (never left absent once status.versionResolution exists), computed regardless of upgradePolicy.mode and regardless of whether a maintenance window is configured at all (visibility is never window-gated). reason is NewerVersionResolved or UpToDate; the message names the resolved target.

Annotation k8s.bnerd.com/upgrade-now — applies the currently-resolved update immediately, bypassing both the window and upgradePolicy.mode. Still subject to Upgrade Path Validation above. No-ops with a reason: NoUpdateAvailable event when nothing is pending; refuses an unparseable resolved target. See Operations → On-Demand Upgrade for the full runbook.

Upgrade Orchestration (status.upgrade) — 0.23.0

Every version change — a spec.version edit, a version-map alias moving, an upgradePolicy auto-update, or upgrade-now — now runs as an orchestrated flow rather than "patch the HelmRelease and hope". The operator turns Nextcloud's maintenance mode ON before the roll and lifts it only after it has verified that the instance's declared apps are enabled again; status.upgrade records the phase (MaintenanceOn → Rolling → Converging → Completed | AppsPending), the pending apps, and each step's exit code.

An app the upgrade disabled and that cannot be re-enabled yet (typically because the app store has not published a release for the new major) leaves the instance in AppsPending, which is retried indefinitely on the instance timer and heals itself when the release appears. Maintenance mode is lifted anyway — unless a critical app is pending: {user_oidc} when spec.oidc.enabled, empty otherwise, because an instance whose only login path is dead is better presented as "in maintenance" than as "up" and unusable.

Conditions: UpgradeInProgress, UpgradeStuck, and AppsHealthy with reason: PostUpgradeAppsDisabled. Metric: nextcloud_operator_upgrade_apps_pending{namespace,instance}. Escape hatch: k8s.bnerd.com/upgrade-apps-accept. Full detail in Upgrades → Post-upgrade app convergence, with the field-by-field status.upgrade reference in the OpenAPI schema.

Supported Versions

The following Nextcloud versions are shipped in the default NextcloudVersionMap CRD. Use spec.version with any of these values, or set spec.helm.version to override. To add custom versions or override image defaults, edit the NextcloudVersionMap/default resource.

Nextcloud Version Helm Chart Version
33.0.3 9.0.6
33.0.2 9.0.5
33.0.0 9.0.4
32.0.9 8.9.1
32.0.8 8.9.1
32.0.6 8.9.1
32.0.5 8.9.0
32.0.3 8.8.1
32.0.2 8.6.0
32.0.1 8.5.2
32.0.0 8.5.0
31.0.9 8.0.3
31.0.8 8.0.1
31.0.7 7.0.1
30.0.10 6.6.10
30.0.6 6.6.9
30.0.5 6.6.3
30.0.4 6.6.2
30.0.3 6.3.1
30.0.2 6.3.0
30.0.1 6.2.1
30.0.0 6.1.0
29.0.6 5.5.6
29.0.5 5.5.3
29.0.4 5.5.2
29.0.3 5.2.2
29.0.2 5.0.1
29.0.1 5.0.0
29.0.0 4.6.9
28.0.4 4.6.6
28.0.3 4.6.4
28.0.2 4.6.3
28.0.1 4.5.12
28.0.0 4.5.9

Aliases: latest and stable both resolve to 33.0.3.

Prefix resolution: Setting spec.version: "33" resolves to the latest known 33.x.y patch (currently 33.0.3).

Phase Values

  • Pending: kopf has not picked up the CR yet
  • Creating: Operator is provisioning DB / secrets / S3 / HelmRelease, including waiting on managed dependencies (PerconaPGCluster spin-up). Normal database initialization stays in this phase — inspect status.database for the cause.
  • Deploying: HelmRelease applied; waiting for Flux to roll out the chart, for the workload (Deployment, Endpoints, Ingress) to become ready, and for Nextcloud to confirm it is installed (occ status → installed:true)
  • Ready: HelmRelease Ready=True and Deployment has all ready replicas and Service has ready endpoints and (if an Ingress exists) the Ingress has a load-balancer address and Nextcloud reports installed:true. Only a Ready instance is pool-assignable.
  • Updating: Reserved for future use
  • Failed: An error blocks progress. The operator keeps retrying transient failures (database provisioning timeout, HelmRelease reconcile error) — Failed is informational so monitoring can alert. Configuration errors propagate as kopf PermanentError and require manual fix.

phase: Ready is set exclusively by the 30-second status timer after the layered readiness gate passes. on_create, on_update, and force_reconcile all leave the instance in Deploying. Inspect status.workload for per-component check results and status.conditions[type=Ready] for the machine-readable reason (WaitingForHelmRelease, WaitingForPods, WaitingForEndpoints, WaitingForIngress, or AllResourcesReady).

status.database is always populated and mirrors the DatabaseReady condition with drill-down fields (managed, type, clusterName, ready, reason, message, observedAt).

Install state. status.installed (boolean) is the cached result of the operator's occ status check, latched into the readiness gate so that Ready means installed, not merely "pods running". status.everInstalled records whether the instance ever installed — it is a safety latch that prevents the operator from auto-installing over an instance that previously worked. status.installCheckedAt is the last check time and status.installHealAttempts counts the bounded fail-closed self-heal attempts. The Installed condition carries the machine-readable reason (WaitingForInstall, WedgedWithData, RegressedAfterInstall, HealAttemptsExhausted, HealInstallTriggered, Installed). See Troubleshooting → Instance stuck in Deploying with the Installed condition False for the operator's data-safety behaviour and the manual recovery path.

RBAC

To interact with these resources, you need appropriate RBAC permissions:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: nextcloud-manager
rules:
  - apiGroups: ["k8s.bnerd.com"]
    resources: ["nextclouds", "nextcloudinstances", "nextcloudpools",
                "nextcloudprofiles", "signalingservers", "recordingservers"]
    verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]