Container Registry, Package Registry, Generic Packages, Dependency Proxy, and Artifact Promotion: Configuration, Design Choices, and Tradeoffs
Choose deliberately among job tokens, deploy tokens, tags, digests, same-bytes promotion, built-in registries, external repository managers, protection, and retention controls.
Learning objectives
- Choose job tokens or deploy tokens based on lifetime, execution context, and least privilege.
- Choose tags for readability while retaining digest/checksum as the machine-verifiable identity.
- Design same-bytes promotion instead of per-environment rebuilding.
- Compare built-in GitLab registries with an external repository manager without collapsing trust boundaries.
- Apply protection, duplicate, and cleanup policies without confusing governance with content identity.
1. Design problem: distribution policy is part of delivery architecture
Once multiple teams consume artifacts, registry choices affect blast radius, rollback speed, auditability, storage cost, and developer experience. The right question is not “which registry feature is richest?” It is “which identity, authentication, lifecycle, and evidence model keeps the verified bytes reproducible across teams?”
Before comparing designs, preserve the producer identity:
CI_PIPELINE_SOURCE, exact CI_COMMIT_SHA,
pipeline/job IDs, and the published package checksum or image
digest. Design decisions are valid only if they keep that evidence
chain intact.
2. Job token versus deploy token
| Choice | Strength | Risk / cost | Good fit |
|---|---|---|---|
CI_JOB_TOKEN |
Ephemeral, automatically issued, tied to running job and triggering user permissions. | Cross-project use needs allowlist and user permission; runner security matters. | CI-to-GitLab package/container automation. |
| Deploy token | Purpose-built registry/package scopes; useful outside CI. | Longer-lived secret requires rotation/storage; protected packages can restrict deploy-token publishing. | External deployment system or read-only consumer. |
| PAT/project access token | Broad API flexibility. | Often wider than distribution needs and longer lived. | Only when narrower mechanisms cannot perform an authorized requirement. |
For CI, start with the job token. For a non-CI consumer, a narrowly scoped deploy token may be appropriate. Never choose a credential merely because it “makes 403 go away.”
3. Tag versus digest/version
| Reference | Human readability | Mutability | Rollback/provenance value |
|---|---|---|---|
Container tag v1.4.0 |
High | Can move unless policy prevents overwrite | Record resolved digest alongside it. |
Container @sha256:… |
Lower | Content-addressed | Strong machine identity for deploy/rollback. |
| Generic package version | High | Named version; duplicate assets may be configurable/allowed | Pair with file checksum and duplicate policy. |
| Package checksum | Low | Content identity of file | Strong verification of exact bytes. |
4. Rebuild per environment versus promote the same bytes
Rebuilding in test, staging, and production produces three artifact identities even if the source SHA is the same. Toolchain timing, dependency resolution, base image drift, timestamps, or nondeterministic compilation can change the bytes. Promotion should preserve the object identity and only change eligibility or a human-facing pointer.
flowchart LR
A[Build once from source SHA] --> B[Digest/checksum]
B --> C[Test consumes exact identity]
C --> D[Approval / policy]
D --> E[Staging points to same identity]
E --> F[Approval / policy]
F --> G[Production points to same identity]
G --> H[Independent health check]
5. GitLab registry versus external repository manager
| Dimension | GitLab built-in registry | External repository manager |
|---|---|---|
| Pipeline integration | Native project metadata, job-token flow, release/deployment proximity. | Usually requires external auth/config and separate audit correlation. |
| Formats/features | Strong built-in coverage; Generic Packages for arbitrary files. | May offer broader federation, replication, promotion, scanning, or enterprise policy depending on product. |
| Identity | GitLab project/package/image coordinates. | External repository path/digest/version. |
| Evidence | Producer pipeline and commit can be close to package metadata. | Must explicitly record GitLab pipeline → external object relationship. |
| Operations | Fewer systems for smaller teams. | Separate service lifecycle, HA, backup, credentials, cost. |
6. Protection and immutability are different controls
Protected packages and protected container tags restrict who can push/delete matching identities. Current protected container tags are Free and can define up to five rules per project; protected tags are excluded from cleanup policies. Container tag immutability goes further: once a matching tag exists, it cannot be updated or deleted. Current GitLab documents container tag immutability as Ultimate, so the mandatory course path never depends on it.
Generic Packages have their own duplicate behavior: duplicate files are allowed by default and can be restricted at group settings. Therefore, your immutable contract should still include exact version + checksum even when governance rules exist.
7. Retention: storage control must preserve rollback evidence
Container cleanup policies select tags by name/age while always
preserving latest and excluding protected/immutable
tags. Deleting tags does not necessarily reclaim underlying layers
immediately; registry garbage collection/online GC behavior is a
separate storage layer. Package cleanup likewise has package/asset
rules. Start with narrow policies and inspect what will remain
before relying on cleanup for cost control.
| Retention question | Evidence-first answer |
|---|---|
| Can we delete this tag? | Is it a rollback/provenance target? Is it protected/immutable? Which digest does it reference? |
| Can we delete this package version? | Who consumes the exact version? Is request forwarding enabled? Is the version referenced by releases/deployments? |
| Did cleanup save storage? | Inspect registry/package usage after policy execution; tag deletion alone is not storage proof. |
8. Worked scenario: choose a design
A team builds a CLI once, tests it in CI, deploys it to staging and production, and also publishes a container wrapper. Production must be reproducible; a legacy external host needs read-only download access.
| Decision | Choice | Why | Observable evidence |
|---|---|---|---|
| CI publisher | CI_JOB_TOKEN |
Ephemeral and native to producer pipeline. | Producer pipeline/job IDs + successful package/container publication. |
| Legacy consumer | Read-only deploy token | Non-CI system needs durable read identity only. | Token class/scope documented; download audit; checksum match. |
| Package identity | Version + SHA-256 | Readable version plus byte identity. | Package coordinate + stored/local checksum. |
| Container identity | Tag + manifest digest | Readable label plus content-addressed deploy reference. | Registry digest + deployment reference. |
| Promotion | Same bytes | Avoids rebuild drift. | Stage/prod manifests reference same checksum/digest. |
| Retention | Protect release identities; clean ephemeral tags narrowly | Preserves rollback while controlling cost. | Policy config + post-cleanup object inventory. |
9. Tier/offering assumptions
- Generic Packages, Package Registry, Container Registry, Dependency Proxy, protected packages, and protected container tags are available across Free/Premium/Ultimate in current docs.
- Container tag immutability is currently documented as Ultimate.
- Self-Managed registry capabilities can depend on using the newer container registry/metadata database.
- Cross-project job-token access remains authorization-sensitive even when the feature itself is Free.
Knowledge check
Why is a deploy token not automatically “more secure” than a job token?
Security depends on scope, lifetime, storage, and use. A job token is ephemeral and often preferable inside CI; a deploy token is useful for external systems but becomes a managed long-lived secret.
If a protected tag cannot be overwritten by a Developer, is its digest unnecessary?
No. Protection controls who can mutate the tag. The digest/checksum is still the evidence of exact bytes and supports independent verification.
What is the main reproducibility problem with rebuilding in each environment?
Each rebuild can produce different bytes, so the tested artifact is no longer necessarily the deployed artifact.
When should an external repository manager be considered?
When required distribution, federation, policy, replication, format, or operational features justify a second system—and only if the GitLab pipeline-to-external-object identity is explicitly recorded.
Why start cleanup rules narrowly?
Retention mistakes are destructive. Narrow selectors make impact observable and protect rollback/provenance targets while policy is validated.
Version and compatibility note
GitLab and GitLab Runner evolve continuously. Treat version-sensitive YAML, runner/executor behavior, APIs, security features, policy controls, tiers, and deprecations as assumptions to verify against the current official GitLab documentation before production use. Preserve the exact project/ref/SHA, compiled configuration, pipeline/job IDs, runner/tool versions, and external target evidence used for any reproducible lab or incident record.
Official references and version notes
Documentation verification date: 2026-09-12. Generic Packages, Package Registry, Container Registry, Dependency Proxy, protected packages, and protected container tags are documented for Free/Premium/Ultimate unless noted otherwise. Current immutable container-tag rules are Ultimate-only. Dependency Proxy is group-level and supports Docker Hub images. The design lesson treats GitLab feature availability as a runtime assumption to record, because Self-Managed registry backend/version configuration can affect which protection and cleanup capabilities are actually usable.
- Package registry — official reference.
- Generic packages — official reference.
- Supported package functionality — official reference.
- Protected packages — official reference.
- Reduce package registry storage — official reference.
- Container registry — official reference.
- Container registry authentication — official reference.
- Protected container tags — official reference.
- Immutable container tags — official reference.
- Reduce container registry storage — official reference.
- Dependency Proxy — official reference.
- CI job token — official reference.
Current assumptions used in this chapter: Version-sensitive YAML, Runner/executor behavior, APIs, security features, policy controls, tiers, and deprecations must be verified against the exact GitLab, GitLab Runner, tool, and external-system versions used in production. Preserve the exact project/ref/SHA, compiled configuration, pipeline/job IDs, runner/tool versions, and external target evidence used for reproducible work.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.