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-hococccommand 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¶
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 yetCreating: Operator is provisioning DB / secrets / S3 / HelmRelease, including waiting on managed dependencies (PerconaPGCluster spin-up). Normal database initialization stays in this phase — inspectstatus.databasefor 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: HelmReleaseReady=Trueand Deployment has all ready replicas and Service has ready endpoints and (if an Ingress exists) the Ingress has a load-balancer address and Nextcloud reportsinstalled:true. Only aReadyinstance is pool-assignable.Updating: Reserved for future useFailed: An error blocks progress. The operator keeps retrying transient failures (database provisioning timeout, HelmRelease reconcile error) —Failedis informational so monitoring can alert. Configuration errors propagate as kopfPermanentErrorand 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"]