Harbor Storage Control with Retention Policies and Immutable Tags
A minimal Harbor lifecycle uses per-project retention policies, immutable tag rules for releases, scheduled garbage collection, and scoped robot accounts to bound storage growth while protecting release artifacts.
29 Jul 2026, 14:00 UTC

Harbor registries grow uncontrollably when every CI build pushes a new tag and nothing is pruned. The practical fix is a minimal lifecycle: retention policies to bound storage, immutable tag rules to protect releases, and garbage collection to reclaim blobs. Combined with scoped robot accounts and digest pinning, this is the smallest design that controls growth without risking running workloads.
Requirements
Project-level policy isolation is required. Retention and immutability rules apply per project, so dev and prod can have different lifecycles.
Dry-run support is required before any deletion. Harbor retention jobs can simulate deletions; review is mandatory.
Separate garbage collection is required. Retention removes tags and manifests. Blob reclamation only happens after a GC job runs.
Pattern matching is required. Rules must distinguish ephemeral tags like dev-* from stable releases like v*.
Smallest Suitable Design
A baseline project uses four controls.
Per-project retention policy
Create a retention rule per project, scheduled weekly. Example intent: keep the last 10 tags matching dev-* by push time, keep all tags matching v* or release-*, and drop tags older than 30 days that do not match a keep pattern. The rule is evaluated as scheduled jobs per project.
Run the rule first in dry-run mode from Project Settings > Retention Policies. Review the simulated deletion set before enabling the schedule.
Immutable tag rule on releases
Add a project-level immutable rule for the release pattern, e.g., v* and release-*. Once a tag matches, Harbor prevents overwrite and deletion of that tag. This closes the gap where retention or a CI push could silently replace a referenced artifact.
Scheduled garbage collection
Schedule GC weekly off-peak. Retention only removes manifests; GC removes unreferenced blobs. Monitor job completion and storage metrics after GC.
Scoped robot accounts
Create robot accounts per pipeline with push permission limited to the target project and repository. Use pull-only credentials for clusters. Robot credentials are created in Harbor UI under Administration > Robot Accounts.
Example push from CI runner:
docker login harbor.example.com -u robot$project-pipeline -p $ROBOT_TOKEN
docker tag app:latest harbor.example.com/project/app:dev-$(git rev-parse --short HEAD)
docker push harbor.example.com/project/app:dev-$(git rev-parse --short HEAD)
Risk: broad robot scope allows deletion. Keep scope to push only.
Trust and Data Boundaries
Harbor sits between CI producers and cluster consumers.
CI boundary: robot accounts provide push. RBAC per project isolates teams. Do not reuse admin credentials in pipelines.
Runtime boundary: clusters pull with pull-only credentials. Prefer digest pinning in manifests, e.g., harbor.example.com/project/app@sha256:..., to ensure a running workload is not affected if a tag is later removed or moved.
Integrity boundary: Harbor stores content but does not verify signatures. Verify Cosign or Notation signatures at admission in the orchestrator, not inside Harbor.
Operational Checks
Create a test project, push several tagged images, configure the retention rule, and run dry-run. Confirm the simulated deletion set matches expectations before enabling the schedule.
After a real retention run, execute garbage collection and verify reclaimed space via Harbor UI storage metrics or the underlying storage backend.
Attempt to push over an immutable tag from a CI runner and confirm Harbor rejects the push. Attempt deletion via UI/API and confirm rejection.
Pull a retained image by digest from a client to confirm manifests referenced by running workloads remain intact.
Failure Modes
Overly broad retention rules can delete tags still referenced by deployments. Mitigate with digest pinning and dry-run review. Retention does not protect untagged images referenced only by digest unless rules are written carefully.
GC racing concurrent pushes on older Harbor versions can cause transient errors. Schedule GC off-peak and monitor job logs.
Immutable rules block legitimate hotfix repushes to a release tag. Change requires admin removal of the immutability rule first, which is an intentional friction.
Retention deletes tags and manifests, not blobs immediately. Storage growth appears unchanged until GC runs.
When to Change the Design
Add proxy-cache projects when pull-through caching of upstream registries is needed. This adds upstream availability dependency and cache staleness.
Add replication jobs for multi-site DR. Replication changes trust boundaries and requires credential management for remote sites.
Enable Trivy scanning with pull-blocking severity thresholds when compliance requires vulnerability gating. This moves policy from lifecycle to admission.
Limitations: exact retention rule syntax, GC behavior, and job scheduler details vary across Harbor 2.x releases. Confirm against the version you run. Immutable tags prevent overwrite but do not guarantee content integrity across registries; use digests for that.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.