How Harbor Tag Immutability Rules Protect Release Images (and How to Use Them Correctly)
Harbor’s tag immutability rules lock release images so pushes with the same tag are rejected and the artifacts can’t be deleted. Learn how to configure, test, and avoid common pitfalls with a step‑by‑step example.
30 May 2026, 11:17 UTC

Why Tag Immutability Matters
In a busy CI/CD pipeline, it’s common to see an image tagged latest or a version like v1.0 overwritten by a new build. In Harbor, this can silently replace the old artifact, breaking reproducibility and making rollback impossible. Tag immutability rules give you a declarative way to lock a tag so that any subsequent push with the same tag is rejected, and the artifact cannot be deleted. The feature is especially useful for production releases, where you want the image to stay exactly as it was when first published.
How the Rule Engine Works
Tag immutability rules live at the project level. Each rule contains:
- Repository filter – a doublestar pattern (e.g.,
**) that matches one or more repositories. - Tag filter – a pattern that matches tags (e.g.,
v*orrelease-*). - Immutability flag – when set, the rule is active.
When a client pushes an image, Harbor evaluates the repository and tag against all active rules in the target project. If a match is found, Harbor refuses the push with a 409 Conflict, returning a JSON error such as:
{"message":"Tag 'v1.0' is immutable and cannot be overwritten."}
This check happens before the manifest is stored, so the old image remains untouched.
The same rule is applied at delete time. If an artifact is referenced by an immutable tag, Harbor will block the deletion request. Garbage collection (GC) respects immutability: immutable artifacts are never removed, even if they become untagged.
Practical Example: Locking Release Tags in a Production Project
- Identify the project – Suppose the production images live in the
prodproject. - Create the rule via the UI:
- Navigate to
Projects > prod > Settings > Tag Immutability. - Add a rule:
- Repository filter:
**(all repos) - Tag filter:
{v*,release-*} - Check
Enable immutability
- Repository filter:
- Save.
- Navigate to
- Push a release image (replace placeholders with your registry address and credentials):
docker tag myapp:1.0 registry.example.com/prod/myapp:v1.0 docker push registry.example.com/prod/myapp:v1.0The first push succeeds.
- Attempt a second push with the same tag:
docker tag myapp:1.0.1 registry.example.com/prod/myapp:v1.0 docker push registry.example.com/prod/myapp:v1.0Harbor responds with a 409 Conflict and the image is not stored.
- Try to delete the immutable artifact via the API:
curl -X DELETE \ -u admin:HarborPass \ https://registry.example.com/api/v2.0/projects/prod/repositories/myapp/artifacts/v1.0 -H "Content-Type: application/json" -d '{"force":true}'Harbor returns:
{"message":"Tag 'v1.0' is immutable and cannot be deleted."} - Run a retention policy dry‑run to confirm immutable artifacts are excluded:
curl -X POST \ -u admin:HarborPass \ https://registry.example.com/api/v2.0/projects/prod/retention_policies/dryrun \ -H "Content-Type: application/json" \ -d '{"dry_run":true,"policy":{"type":"artifact","action":"delete"}}'In the response, the
v1.0artifact will not appear in thecandidateslist.
Limitations and Common Pitfalls
- Scope of the rule – The rule only applies to the project where it is created. If you replicate artifacts to another Harbor instance, you must create a matching rule in the destination project; otherwise, the immutable tag can be overwritten there.
- Rule pattern syntax – Harbor uses doublestar patterns. A rule like
tag: "**"will make every tag immutable, which blocks GC and can cause storage bloat. Keep the tag filter specific (e.g.,v*). - Admin override – Project admins can edit or delete the rule. Immutability is an operational guardrail, not a security boundary. Combine it with RBAC and, if needed, content trust (Notary/Cosign) for stronger guarantees.
- Un-tagged manifests – Immutability protects only tagged artifacts. Un-tagged layers that become orphaned can still be removed by GC if they are not referenced by any immutable tag.
- Retention and GC interaction – Because immutable artifacts are excluded from deletion candidates, a broad rule can prevent the removal of old releases, leading to unbounded storage growth. Monitor disk usage and consider rotating immutable tags (e.g., keep only the last 10 releases).
- Version differences – The UI location and API endpoints for tag immutability rules can differ between Harbor 2.x releases. Verify against your version’s documentation before scripting.
Checking the Result
After setting a rule, you can verify its existence via the API:
curl -u admin:HarborPass \
https://registry.example.com/api/v2.0/projects/prod/tag_immutability
| jq ".rules[] | {repo_filter, tag_filter, enabled}"
The output should list the rule with enabled:true. A subsequent push that matches the rule will return a 409; a push that does not match will succeed.
Bottom Line
Tag immutability rules give you a simple, declarative way to protect production release images from accidental overwrite or deletion. Use a narrow tag filter (e.g., v*), keep the rule enabled only in the projects that host immutable artifacts, and remember that admins can still override it. Pair the rule with retention policies and, if your compliance needs are high, with signed images to achieve a robust release pipeline.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.