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:
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 MinIOglobal.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 nameglobal.pages.objectStore— the Pages object store blockregistry.storage— the docker-registry S3 driver config (via an operator-owned Secret)
GitLab 19 / chart 10 mandate and auto-handling¶
External object storage is mandatory for production on GitLab 19+ (chart 10+)
GitLab 19 (chart 10) removed the bundled MinIO sub-chart. For production use, you must configure spec.objectStorage.credentialsSecret before upgrading to 19.x or deploying GitLab 19 fresh.
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.
Operator auto-handling for chart 10 (no-S3 case). When spec.objectStorage.credentialsSecret is not set on chart 10+, the operator automatically disables the default object-storage types (lfs, artifacts, uploads, packages) so the chart installs using local disk rather than failing. This is suitable for development or evaluation only — not for production workloads. Set spec.objectStorage.credentialsSecret for any instance that will hold real data.
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.credentialsSecretis 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. The backup credentials Secret uses s3cmd format (not the same multi-key shape as the main S3 Secret):
The Secret must contain the s3cmd config under key config:
apiVersion: v1
kind: Secret
metadata:
name: my-gitlab-backup-s3-config
namespace: my-gitlab
stringData:
config: |
[default]
host_base = rgw.bnerd.com
host_bucket = rgw.bnerd.com/%(bucket)s
access_key = <rgw-access-key>
secret_key = <rgw-secret-key>
bucket_location = default
use_https = True
The operator wires this Secret to gitlab.toolbox.backups.objectStorage.config in the emitted HelmRelease. On chart 10+, the Toolbox is only enabled when this field is set — if you omit backups.objectStorage.credentialsSecret, the Toolbox is disabled by the operator to avoid chart install failures.
The backups.objectStorage.credentialsSecret must be a separate s3cmd-format Secret — it cannot share the same multi-key shape as the main spec.objectStorage.credentialsSecret.