Skip to content

Object Storage

GitLab uses S3-compatible object storage for nearly all persistent data (git LFS, CI artifacts, uploads, packages, registry, etc.). The operator consumes an hq-provided Secret that contains both the S3 connection parameters and a per-bucket mapping.

The S3 credentials Secret

hq creates the RGW user and all required buckets, then writes a single Secret in the instance namespace. The operator reads this Secret and validates that all required bucket-class keys are present.

apiVersion: v1
kind: Secret
metadata:
  name: my-gitlab-s3-credentials
  namespace: my-gitlab
stringData:
  accessKey: <rgw-access-key>
  secretKey: <rgw-secret-key>
  endpoint: https://rgw.bnerd.com
  region: default
  # One key per GitLab storage class:
  bucket.registry:          my-gitlab-registry
  bucket.lfs:               my-gitlab-lfs
  bucket.artifacts:         my-gitlab-artifacts
  bucket.uploads:           my-gitlab-uploads
  bucket.packages:          my-gitlab-packages
  bucket.mr-diffs:          my-gitlab-mr-diffs
  bucket.terraform:         my-gitlab-terraform
  bucket.ci-secure-files:   my-gitlab-ci-secure-files
  bucket.dependency-proxy:  my-gitlab-dependency-proxy
  bucket.backups:           my-gitlab-backups
  bucket.pages:             my-gitlab-pages

Reference it from the GitlabInstance:

spec:
  objectStorage:
    credentialsSecret: my-gitlab-s3-credentials

Required bucket classes

The operator validates that the Secret contains all of the following bucket.<class> keys. If any key is missing, the instance enters phase: Failed with condition S3BucketsIncomplete.

Key GitLab storage class What is stored
bucket.registry registry Container image layers
bucket.lfs lfs Git LFS objects
bucket.artifacts artifacts CI/CD job artifacts
bucket.uploads uploads User-uploaded attachments
bucket.packages packages Package registry (npm, pip, etc.)
bucket.mr-diffs mr-diffs Merge request diff storage
bucket.terraform terraform Terraform state files
bucket.ci-secure-files ci-secure-files CI secure files
bucket.dependency-proxy dependency-proxy Dependency proxy cache
bucket.backups backups GitLab backup tarballs
bucket.pages pages GitLab Pages content

All keys required even if the feature is unused

hq must supply all eleven bucket.<class> keys. A key being present does not enable the feature — it just satisfies the operator's validation. If backups or Pages are not used, the corresponding bucket can be empty but the key must exist in the Secret.

How the operator wires S3 to the chart

The operator translates the Secret into Helm values for the upstream GitLab chart:

  • global.minio.enabled: false — disables bundled MinIO
  • global.appConfig.object_store — global S3 connection block referencing the credentials Secret
  • Per-bucket entries under global.appConfig.{lfs,artifacts,uploads,packages,...}
  • global.registry.bucket — the registry bucket name
  • global.pages.objectStore — the Pages object store block
  • registry.storage — the docker-registry S3 driver config (via an operator-owned Secret)

GitLab 19 mandate

External object storage is mandatory on GitLab 19+ (chart 10+)

GitLab 19 (chart 10) removed the bundled MinIO sub-chart. If you deploy GitLab 19 or later without spec.objectStorage.credentialsSecret set and validated, the chart install will fail.

Before upgrading from 18.x to 19.x, ensure your S3 credentials Secret exists and passes validation (all eleven bucket-class keys present). See Version Management for the upgrade sequence.

What the operator does NOT do

  • The operator never creates or modifies RGW users or buckets.
  • The operator never deletes the S3 Secret or any bucket data on instance deletion.
  • If spec.objectStorage.credentialsSecret is empty, S3 wiring is skipped entirely (valid for GitLab 18 and earlier in non-production setups that use the in-chart defaults).

Backup object storage

The backup schedule and destination are configured separately on the GitlabInstance:

spec:
  backups:
    schedule: "30 2 * * *"
    objectStorage:
      credentialsSecret: my-gitlab-s3-credentials  # same Secret as main S3

The backups.objectStorage.credentialsSecret may point at the same Secret as spec.objectStorage.credentialsSecret, or a different one (e.g. a dedicated backup user with narrower permissions).

Backup job wiring is a follow-up item

As of v0.1.0-beta, spec.backups.schedule is stored and validated but the backup job wiring to the chart is not yet complete. The field is accepted without error; the actual backup cron is a planned follow-up.