GitLab container registry on self-managed

Teams running self-managed GitLab for CI/CD need to decide where container images are stored, how the registry's metadata is kept, and how old images are removed without downtime. This page covers those decisions for the GitLab container registry on infrastructure you control.

On this page

What the GitLab container registry on self-managed does for your build pipelines

Your CI jobs will build and push container images many times a day, and the platform team has to decide where those images live, how long they are kept and how old tags are removed. The GitLab container registry is the component that answers those questions for a self-managed instance. It is an image registry built into GitLab, so each project's images are stored, listed and pulled through the same URL structure, authentication and project permissions that govern the source code and pipelines. A CI job pushes an image with its job token, a deployment pulls it with a deploy token, and both actions are visible in the same project context. That integration is the main reason teams use it rather than a separate registry, but it also means registry storage grows inside the same infrastructure that hosts repositories and runners, and it needs its own capacity and retention plan.

Plan the registry deliberately when any of these conditions applies: many projects build images on every merge request, images are large because of language toolchains or model artifacts, production deployments depend on specific tags remaining available, or auditors expect to see which image version reached production. Defaults are rarely enough in those cases. Before go-live, confirm with the GitLab documentation for the exact version you run which storage backends the registry supports, how it is configured in gitlab.rb, what metadata database requirements apply and how garbage collection behaves while the registry serves requests. Ask your team to confirm each of these against that documentation. Those details were not part of the research supplied for this page, so treat any default you find in an older guide as a hypothesis to check.

The practical work is to tie three decisions together: where image bytes are stored, how cleanup policies remove tags that nobody needs, and how much capacity is reserved for growth. Storage choice affects backup scope and restore time, because image data lives outside the database. Cleanup policies decide what is removed automatically, and a policy that is too aggressive can delete an image a rollback still needs. Capacity planning depends on build frequency, image size and retention windows, so ask your engineers to measure current push volume for a representative month before sizing. Ask any implementation partner for a written scope that names the storage backend, the backup approach for registry data, the cleanup rules per project group and the monitoring you will use to catch runaway growth.

Storage and deployment options for the registry and when each fits

This table compares the choices that shape a self-managed container registry: where image layers live, how metadata is handled, and where the registry runs relative to GitLab. Read each row as a trade-off between backup scope, recovery effort and who owns the storage cost, then confirm the exact settings against the registry documentation for your GitLab version.

DecisionOptionOperational trade-offWhen it fits
Layer storageLocal filesystem on the GitLab hostSimplest to set up, but backups grow with image data and the host becomes the capacity limit.Small instances with modest image volume and a single-node setup
Layer storageObject storage (S3-compatible or cloud provider)Capacity scales outside the GitLab host, but backups must cover both the bucket and the metadata database.Growing image volumes, or teams that already run object storage with versioning and lifecycle controls
Metadata handlingBundled registry metadata in the Linux packageLower operating overhead, with the database backed up through the standard GitLab backup task.Teams that want fewer moving parts and accept the bundled database model
Metadata handlingExternal or managed PostgreSQL for the registry metadataMore control over availability and recovery, but a second database to back up, patch and monitor.Organizations with an existing PostgreSQL platform and tested recovery procedures
Garbage collectionOnline garbage collection enabledReclaims unreferenced layers while the registry runs, so teams must confirm behavior and monitoring for their version.Environments with frequent pushes that need storage reclaimed without downtime
Garbage collectionOffline garbage collection in a maintenance windowSimpler to reason about, but requires planned downtime and a clear window for each run.Smaller registries or teams with fixed maintenance windows
Registry placementRegistry on the same host or Linux package as GitLabFewer components to deploy, but registry load, storage I/O and upgrades share a failure domain with GitLab.Single-node installations with light image traffic
Registry placementRegistry as a separate service behind its own endpointIsolates load and upgrades, with more DNS, TLS and certificate work to maintain.Teams with heavy CI pull traffic or strict separation of duties between platform and build operations
Cost ownershipSelf-managed storage and database capacityYour team pays for storage, backup copies and staff time, and costs recur as image history grows.Organizations that already budget for infrastructure they control

What drives image storage capacity in a self-managed registry

Registry storage grows with how often teams push images, how large those images are, and how long the platform keeps what it has already stored. The cards below separate the inputs you can measure in your own pipelines from the retention and backup decisions you make on purpose.

Build frequency and project count

Every pipeline that builds and pushes an image adds layers and a manifest to the registry, so storage grows with the number of projects that publish images and how often they run. A project that rebuilds on every merge request creates far more tags than one that publishes only on release. Before sizing, count pushes per day across all projects, grouped by project and pipeline type, and note which pipelines push on every commit. Those counts set the growth rate that retention policy then has to keep under control.

Image size and layer reuse

The registry stores image layers, and layers shared between images are stored once. Large base images, unpinned dependency installs and build steps that change early in the Dockerfile reduce reuse, so each new tag carries more unique data. Measure the compressed size of recent images per project and check how many layers each new build actually adds compared with the previous build. Teams that restructure Dockerfiles to keep stable layers first usually see less unique data per push, which you can confirm in your own registry.

Tag retention policy

Cleanup policies decide how many tags survive per project and for how long. Without a policy, every tag ever pushed stays referenced, and garbage collection can only reclaim blobs that no manifest points to. Set the policy per project using name patterns and keep counts that match how your teams deploy, then confirm which tags must never be removed, such as release tags. Ask the platform team to show a dry run on a real project before enabling the policy broadly, because a pattern that is too broad removes tags that deployments still reference.

Environments and branches that publish

Images tagged per branch, per environment, or per commit multiply the tag count even when the underlying code changes little. A team that promotes one image through development, staging and production by retagging adds few new blobs, while a team that rebuilds for each environment adds a full image set each time. Inventory the pipelines that push to the registry and record which branches and environments each one covers. This shows where a single change fans out into several stored images and where promotion by digest would avoid duplicate builds.

Backup retention for the image store

Backups of the registry's storage backend and its metadata database hold older blobs and tag references that the live registry may already have cleaned up. Each retained backup adds its own footprint on top of live storage, so the number of backups you keep multiplies the cost of every cleanup decision. Confirm with your backup procedure whether registry data is captured by your standard GitLab backup, by storage-level snapshots, or by both, and write down how many restore points you need for compliance and recovery. Those answers determine how much storage sits outside the live registry.

Garbage collection and reclaim timing

Storage shrinks only after cleanup removes tags and garbage collection removes unreferenced blobs. If garbage collection runs rarely or during peak hours, reclaimable space builds up between runs, so peak usage can exceed what steady-state growth suggests. Record how long a garbage collection run takes on a copy of your data, how often pipelines push during that window, and how much space it frees each time. Plan capacity for the peak between runs, not only for the average day, and confirm the online collection behavior for your GitLab version before you rely on it.

How to set up the registry on a self-managed instance, step by step

This sequence takes a self-managed GitLab instance from an unconfigured registry to a tested one, with each stage confirmed before the next starts. The result is a registry that accepts pushes from a runner, applies cleanup rules and reclaims storage on a schedule your team controls.

  1. Confirm the install method and version

    The platform engineer on the GitLab team records how the instance was installed (Linux package, Helm chart, Operator, Docker or source), the exact GitLab version and the matching Runner version. Install methods differ in where registry settings live, so the team should confirm the registry configuration keys in the documentation for that exact version before editing anything. The step is done when the version, install method and the registry section of the configuration file have been written down and reviewed. Upgrade paths also matter here, because a registry change made during an upgrade can complicate the required upgrade stop plan.

  2. Choose and prepare the image storage backend

    The infrastructure team selects where image layers will live, such as local disk on the instance or an object storage service in infrastructure you control, and creates a bucket or directory with access limited to the registry service. Credentials should be scoped to that bucket or path, stored in the team's secrets process and rotated on a schedule. Confirm in the documentation which storage drivers and credential formats the installed version supports. The step is done when a test write and read from the storage location succeed using only the registry's credentials, and the access policy is saved for audit.

  3. Set the external URL and TLS for the registry

    The team sets the registry's external hostname and enables TLS with a certificate that clients inside the network trust, including any internal certificate authority the runners use. Hostname and certificate settings must match what the runners and developers will type into image references, so a mismatch shows up later as a failed login. The team confirms the exact setting names for the installed version and reconfigures the instance. The step is done when a Docker or equivalent client can complete a login to the registry hostname over HTTPS without disabling certificate checks.

  4. Test a push and pull from a runner

    A CI engineer creates a throwaway project with a minimal pipeline that builds a small image, pushes it to the project's registry path and pulls it in a second job. The runner's executor and its trust store must be able to reach the registry hostname, so this test exposes network and certificate gaps early. The step is done when both jobs pass in the pipeline log and the image is visible in the project's container registry view, with the digest matching the one pushed.

  5. Configure cleanup policies on a test project

    On the test project, the owner defines a cleanup policy that matches the team's retention rule, for example keeping recent tags and removing older ones by pattern. Cleanup policies are the first line of storage control, and they run asynchronously, so the owner should not expect space to return immediately. The team should check the documentation for the installed version to confirm which policy fields are available and how the policy is scheduled. The step is done when the policy shows the expected tags as kept and the expected tags as marked for removal in a dry review of the tag list.

  6. Run garbage collection in a non-production window

    The administrator schedules a maintenance window, puts the instance in the mode the documentation prescribes for registry garbage collection, and runs the collection command confirmed for the installed version. Garbage collection reclaims storage for manifests and layers that no tag references any longer, so the team should take a backup of the metadata and storage configuration first. The step is done when the command completes without errors, the storage usage on the backend is compared before and after, and the test project's pulls still succeed for the tags that were kept.

  7. Record the baseline and hand off to operations

    The team writes down the configuration values, storage capacity at the time of testing, the cleanup policy used and the garbage collection schedule, then adds registry checks to the monitoring and backup runbooks. Ask the vendor or your support channel to confirm any settings the team could not verify in the documentation. The step is done when another engineer can read the runbook and repeat the push, pull and cleanup test without help, and the baseline numbers are stored with the change record for future capacity planning.

How registry planning changes by deployment environment

On a single Linux package instance, the bundled services run on the same host or small set of hosts, and the registry follows that layout. Image layers are written to the local filesystem by default, or to object storage if you configure it. The registry's metadata lives in the PostgreSQL database that the Linux package bundles, so image records and cleanup state sit alongside the rest of GitLab's data.

  • Blob location: Layers default to local disk under the GitLab data path unless you point the registry at object storage in the registry settings.
  • Metadata: Tags, manifests and repository records are stored in the bundled PostgreSQL database, so a database restore is required for a consistent registry.
  • Backup scope: The GitLab backup task covers registry data when it is stored locally, but confirm whether your object storage bucket needs its own snapshot or versioning policy.
  • Garbage collection: Plan online garbage collection windows around disk growth, since blobs remain on disk until collection runs.
  • Secrets: Back up the secrets file (gitlab-secrets.json) with the database, because restored registry data depends on it.

Confirm the storage backend, the disk headroom for your expected image volume, and whether the backup job captures every location the registry writes to.

How online garbage collection and cleanup policies free image storage

Cleanup policies and garbage collection solve two different problems, and a registry needs both. A cleanup policy removes tags by rule, for example keeping the most recent tags matching a name pattern and expiring the rest after a set age. That removes references to images. It does not free disk space by itself, because the layers and manifests behind those tags stay on the storage backend until the registry reclaims them. Garbage collection is the step that finds blobs and manifests no longer referenced by any tag and deletes them from storage. Tag cleanup decides what is kept; garbage collection decides what bytes are actually released. Plan both as one process, and confirm in your GitLab version's container registry documentation whether garbage collection runs in an online mode that keeps the registry readable and writable, or whether it requires a read-only window or a stop of the registry service. That answer changes your maintenance schedule more than any other setting on this page.

The main operational risk is deleting data that running deployments still depend on. A tag can be removed by a policy while a Kubernetes deployment, a Helm release or a CI job still pulls that image by tag, and a pod restart or a rollback then fails. Many teams reduce this by pinning digests in deployment manifests and by excluding production tag patterns from expiry, but these are decisions for your own release process, not defaults you can assume. Before enabling a policy on a shared registry, apply it to a non-critical project with representative tags, confirm what it removes in the reported output, and check that its rules match how your pipelines name images. Keep retention long enough for your slowest rollback path, and record the policy settings as part of your change evidence.

Watch for a growing backlog of untagged manifests. Images pushed by digest, superseded builds and images whose tags were removed all leave manifests that no longer appear in the tag list but still occupy metadata and storage until they are cleaned up. If the backlog grows faster than garbage collection runs, storage use rises even though cleanup policies appear to be working. Review untagged counts and storage growth on a regular schedule, and ask your GitLab support or implementation team to confirm how untagged manifests are handled in your version before you set retention targets. Capacity planning should use the observed rate of image pushes and the retention period you choose, so measure those on your own pipelines before you size the storage backend.

What teams ask before running the GitLab registry themselves

What does running a self-managed GitLab registry cost, and what drives it?

The cost comes from four places: the subscription (if any), infrastructure, your staff time and any outside services. GitLab's pricing page lists Free at 0 US dollars and Premium at 29 US dollars per user per month billed annually, with the top tier custom priced, so subscription cost depends on the tier you choose. Infrastructure cost rises with image volume, retention rules and redundancy. Staff time recurs through upgrades, cleanup, capacity growth and restore tests. Ask any partner for a quote built from a written scope that separates one-time build work from recurring operations.

How long does a registry rollout take, and what sets the timeline?

The timeline depends on whether you are adding the registry to an existing GitLab instance or building the instance and registry together. The main drivers are the storage backend you choose, DNS and TLS readiness, the size of the image estate that must be checked, how backup tooling is integrated, and approval cycles for change windows. Offline or air-gapped networks add packaging and mirroring steps. Ask for a timeline that lists each dependency and who owns it, and confirm the install method and reference architecture first, since those decisions shape the rest of the plan.

What must our own team provide before the registry can go live?

Your team typically provides the infrastructure and the access that the registry depends on:

  • Storage for image layers, sized for your retention policy and growth
  • DNS records and TLS certificates for the registry hostname
  • Network paths from CI runners and build hosts to the registry
  • A PostgreSQL and Redis plan, whether bundled or external
  • Backup tooling and object storage for backups and restore tests
  • A named owner for upgrades, cleanup policies and incident response

Confirm each item in the official GitLab documentation for your chosen install method before work starts.

Can our team run the GitLab registry without outside help?

A team can run it alone if it already operates Linux servers, PostgreSQL, object storage and TLS well, and if it has time to read the install and upgrade documentation closely. The Linux package bundles PostgreSQL and Redis, which lowers the number of moving parts for a single instance, while Helm and the Operator suit teams already running Kubernetes. Stateful components inside Kubernetes are not supported by GitLab's reference architectures, so that choice needs care. Outside help is most useful for the first build, the first upgrade across a required stop, and a tested restore.

How does the registry relate to the Premium and Ultimate tiers?

Tier choice changes which GitLab features your teams can use, and it should be checked against the registry features you plan to depend on. GitLab's pricing page lists advanced CI/CD and priority support for Premium, and application security testing, software supply chain security, vulnerability management and compliance features for the custom-priced top tier. The pricing page is the authority on which tiers include which capabilities, so confirm registry-related features there and in your license before you design around them. Do not assume a feature is included in a tier because a neighboring feature is.

How do upgrades across required upgrade stops affect the registry?

The registry ships as part of the GitLab instance, so it moves through the same upgrade path. Since GitLab 17.5, required upgrade stops fall at versions x.2, x.5, x.8 and x.11, for example 18.2, 18.5, 18.8, 18.11, 19.2, 19.5, 19.8 and 19.11, and you cannot skip them. GitLab ships minor releases on the third Thursday of each month and patch releases twice a month. Bug fixes are backported only to the current stable release, while security fixes also reach the previous two monthly releases. Plan a backup before every stop, check the upgrade path page for your starting version, and test the registry after each step.

What does a backup or restore need to cover for the registry?

A restore is only useful if the registry's image data and the GitLab metadata it depends on come back together. GitLab's backup and restore documentation describes the core backup task, and the registry's storage backend has its own durability and snapshot behavior that you must plan separately. Confirm how your storage backend is backed up, how the metadata database is captured, and how secrets are preserved. Then run a restore into a separate environment and check that pulls and pushes work. For air-gapped sites, check the offline environments guidance before choosing how backups leave the network.

Security and operations to plan for the image registry

Image registries hold build output that production systems pull and trust, so access, transport, tag integrity, recovery and visibility need decisions before the first push. The cards below cover one control each, with the check to run in your own environment.

Push and pull access by group and project

Registry access follows the GitLab permissions of the project that owns each image path, so a developer who can push to one project should not automatically reach images in another. Map which groups may push, which may only pull and which service accounts or deploy tokens are allowed to read images for production clusters. Then test the mapping with a user from each role, including a pull attempt against an image in a project that user cannot see. Confirm the rules in the authentication and authorization documentation for your edition and identity setup.

Credentials used by runners

A runner that builds and pushes images holds credentials that can write to the registry, so a compromised job can publish a malicious image under a legitimate name. Plan separate runners or runner tags for build jobs that push and for jobs that only test, and use short-lived job tokens instead of long-lived personal access tokens wherever the pipeline allows it. Keep runner configuration, including any registry credentials in the runner config file, off shared hosts and out of job logs. Check that a job on an unprotected branch cannot reach the push credentials.

TLS and certificate trust on the registry endpoint

Clients such as Docker, containerd, Kubernetes nodes and CI executors each validate the registry certificate against their own trust store, and a missing internal CA on one node type causes failures that look like authentication errors. Decide whether the registry uses a publicly trusted certificate or an internal CA, and list every consumer that must trust it, including build hosts, cluster nodes and any air-gapped mirrors. Rotate certificates before expiry on a schedule that covers all consumers. Verify with a pull from a clean node that has only the documented trust store installed.

Tag immutability and image provenance

A mutable tag such as latest or a release tag that is overwritten can change what production runs without any change record. Decide which tag patterns are protected from overwrite and deletion, and make production deployments reference immutable digests rather than tags where your deployment tooling supports it. Record which pipeline and commit produced each image so that a digest can be traced back to source. Confirm which tag protection and immutability features your GitLab edition provides, and test an overwrite attempt on a protected tag before relying on it.

Backup and restore with the metadata store

Image data lives in the storage backend while the mapping of repositories, tags and manifests lives in the metadata database, so restoring one without the other leaves images that cannot be found or tags that point at missing blobs. Plan backups that capture both at a consistent point, and confirm whether your GitLab backup procedure covers registry storage or needs a separate step for your storage backend. Restore into a test instance on a regular schedule and pull a sample of images by digest to prove the result. Record the restore steps alongside the backup procedure.

Monitoring and logging of registry activity

Without registry logs, a team cannot tell who pushed an image, who pulled a sensitive image or whether a cleanup job removed something a deployment still needs. Decide which events to keep, such as pushes, pulls, deletions and failed authentication, and where they are sent, including the retention period your audit process requires. Set alerts for spikes in failed logins, unexpected deletions and garbage collection failures. Check that registry logs reach your central log platform and that a test push appears there with the user and project attached.

What to confirm in your environment before you commit to a registry design

This page can describe how the GitLab container registry works, but it cannot tell you which registry version, storage backend or metadata database your instance will run. Those depend on your GitLab version, your install method and your infrastructure, so confirm them before you commit to a design. Start with the registry version that ships with your target GitLab release, and check which storage backends that version supports for your object storage. Then confirm whether your chosen install method bundles the registry or expects you to run it separately. The GitLab installation methods page is the starting point for that check, and the Linux package, Helm chart, Operator and Docker methods can differ in how they handle the registry. Next, confirm the metadata database and garbage collection behavior. The registry depends on a database for image metadata, and you need to know whether your version expects that database to be in place, how it is provisioned on your side, and whether its sizing fits your planned image count. Ask GitLab or check the release documentation for the online garbage collection behavior of your exact version, including whether it runs without taking the registry offline. Your infrastructure team should confirm where the registry data sits, how the metadata database is backed up, and whether the registry is covered by your GitLab backup procedure or needs its own backup and restore steps. A restore plan that omits image storage will fail in a way that only shows up after an incident. Finally, confirm the network path and image growth. Map the network path between your runners and the registry, including DNS, TLS certificates, proxies and any firewall rules that apply when runners sit in a separate network or cloud account. Then measure expected image growth from your own pipelines: how many images each pipeline pushes per day, how large they are, and how long you need to keep tags. DeployOpen confirms the version, install method, architecture and scoping assumptions during the scoping phase, and documents them in the written scope. Your GitLab vendor relationship and your infrastructure team confirm the storage backend support, database requirements and backup coverage for your target release.

How DeployOpen scopes and delivers the GitLab registry

DeployOpen plans, implements, hardens, documents and supports self-hosted open-source platforms inside your own infrastructure, including the registry's storage, database and cleanup behavior. For GitLab container registry on self-managed, the work starts with a written scope that ties image storage, retention and capacity to the GitLab instance it serves.

How we scope

  • Confirm the GitLab edition, install method and registry storage backend your environment will run
  • Map which projects publish images, how often, and which retention rules teams need
  • Agree the written scope, deliverables and timeline before any build work starts

How we build

  • Configure the registry storage backend, metadata database and online garbage collection for your setup
  • Set cleanup policies and test them against a copy of representative image data
  • Validate backup, restore and upgrade steps for the registry alongside the GitLab instance

How we hand over

  • Deliver configuration, runbooks and capacity notes written for your platform team
  • Document storage growth assumptions and the checks your team should repeat over time
  • Walk your engineers through cleanup, restore and upgrade procedures before handover

How we support

  • Offer ongoing support, upgrades and continuous testing as a retainer if you want it
  • Review registry storage growth and cleanup results when GitLab releases change behavior
  • Plan each upgrade around the required upgrade stops that apply to your instance

Sources and further reading

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.