For production Crossplane, reference provider packages by digest, set revisionActivationPolicy to Manual, and keep the package pull policy at its default unless you have a reason. Crossplane's own documentation says digests give deterministic, repeatable installations, and Manual activation stops a newly installed revision from going live by itself.
Providers are dependencies you run in the cluster
Crossplane extends Kubernetes so you can manage cloud resources with manifests. It does that through provider packages, which are OCI images installed from a registry. A provider pod runs in your cluster, usually with cloud credentials. That makes the package reference in a Provider manifest a dependency decision, like picking a base image.
Install is simple: a Provider object has a package field with the registry location and a tag, for example version 2.0.0 of an S3 provider. You can also pass packages at install time with the Crossplane Helm chart.
Tag versus digest
The docs state that Crossplane supports tags and digests the way Kubernetes does with container images, and show a digest form of the package reference, noting that digests give deterministic, repeatable installations.
A tag can be re-pushed. A digest identifies one image. If you use tags, someone with push access to that registry path can change what your next install fetches.
Activation policy and upgrades
Upgrading means editing the package field. Crossplane then installs the new image and creates a new ProviderRevision, and only one revision is active at a time. The old revision can be kept, because the docs say Crossplane stores deprecated provider CRDs without removing them until you decide.
The revisionActivationPolicy field has two options. Automatic, the default, activates the last installed provider. Manual does not automatically activate it. Set Manual if you want a person to approve the switch after checking the new revision is healthy.
The revisionHistoryLimit field sets how many inactive revisions to keep, with a default of one. Keep at least one so you can roll back, and raise it if your release process needs more.
Pull policy
The packagePullPolicy field works like Kubernetes image pull policy:
| Value | Behavior |
|---|---|
| IfNotPresent | Default. Download only if not in the local cache |
| Always | Check for new packages every minute and download any matching one not cached |
| Never | Install only from the local cache |
Always combined with a mutable tag is the riskiest pairing, because a re-pushed tag is picked up within about a minute. Always combined with a digest is harmless, since the digest does not move.
Private registries and mirrors
Like imagePullSecrets, Crossplane uses packagePullSecrets for private registries. Mirroring approved provider packages into your own registry, and pointing the package field there, protects you from public registry changes and outages. Keep the digest the same after mirroring so you can show the content is identical.
A checklist
- Every Provider and Configuration package uses a digest.
- Manual activation is set on production.
- A pull request template for package changes links to the release notes and the new digest.
- A test cluster gets the new revision first.
- Provider credentials follow least privilege, scoped to what the provider needs.
- The registry path has restricted push access.
Where a scanner fits
Provider images contain code and dependencies like any other container image. Safeguard's container scanning and SBOM generation can inventory them, and policy gates can hold a pull request that moves a package to a vulnerable digest. Free scan: gold.safeguard.sh/scan.
Try it yourself
Click through it at your own pace, or open it full screen.
Scan the sample image and notice that findings attach to a specific image, which is why a digest matters.
Quick check
Is Manual activation the default?
No. The Crossplane documentation says Automatic is the default, which activates the last installed provider.
How many old revisions does Crossplane keep?
By default one inactive revision. You can change it with revisionHistoryLimit, and zero disables storing revisions.
Sources
Last reviewed: 19 October 2026.