Skip to content

Quick Start

Goal: go from zero to a browser-accessible GitLab Community Edition with managed PostgreSQL and Redis in roughly 15 minutes.

This is the golden path — one GitlabInstance, managed backends, one admin login. For the full configuration surface, see the Guides section.

Prerequisites

You need a cluster with the following already installed. Fix any missing items first — the operator assumes these exist.

Requirement Why Check
Kubernetes 1.25+ CRD + status subresource support kubectl version
Flux CD 2.3.x (source-controller + helm-controller) The operator emits HelmRelease resources; Flux applies them flux check
Percona PG Operator (pgv2.percona.com) Required for postgres.managed: true kubectl get crd perconapgclusters.pgv2.percona.com
OT-Container-Kit redis-operator (redis.redis.opstreelabs.in) Required for redis.managed: true kubectl get crd redis.redis.opstreelabs.in
Ingress controller (NGINX, Traefik, etc.) External access to the GitLab URL kubectl get ingressclass
Default StorageClass PVCs for managed databases kubectl get sc
A DNS name that resolves to your ingress So you can reach GitLab in a browser dig git.example.com

The Installation page covers installing the operator itself and the backend operators.

Step 1 — Apply the default GitlabVersionMap

The operator always looks up the cluster-scoped GitlabVersionMap named default to resolve spec.version to a Helm chart version. Apply it once per cluster:

kubectl apply -f https://raw.githubusercontent.com/bnerd/bnerd-gitlab-operator/main/examples/versionmap-default.yaml
# or from a local clone:
kubectl apply -f examples/versionmap-default.yaml

Verify:

kubectl get glvm default
# NAME      LATEST    AGE
# default   19.1.1    5s

Step 2 — Create a namespace and apply a GitlabInstance

Replace git.example.com with your real DNS name. This example uses managed Postgres and Redis so the operator provisions those clusters for you.

# gitlab-ce-demo.yaml
apiVersion: k8s.bnerd.com/v1alpha1
kind: GitlabInstance
metadata:
  name: gitlab-demo
  namespace: gitlab-demo
spec:
  version: "18"           # resolves to latest 18.x via GitlabVersionMap
  edition: ce

  domains:
    gitlab: git.example.com
    registry: registry.example.com

  postgres:
    managed: true
    topology: standalone   # use "ha" for production (3-node Percona cluster)

  redis:
    managed: true
    topology: standalone

  objectStorage:
    credentialsSecret: gitlab-demo-s3   # see Step 3

Object storage is required for GitLab 19+

GitLab 19 (chart 10) removed bundled MinIO. If you are deploying version 19 or later, an S3 credentials secret is mandatory. For testing on version 18 or earlier you may omit objectStorage and rely on in-chart storage — though this is not recommended for production.

Create the namespace and apply:

kubectl create namespace gitlab-demo
kubectl apply -f gitlab-ce-demo.yaml

Step 3 — Provide an S3 credentials Secret (required for v19+)

If you are deploying GitLab 18 for the quick start you can skip this step. For version 19+, create the Secret before applying the CR:

apiVersion: v1
kind: Secret
metadata:
  name: gitlab-demo-s3
  namespace: gitlab-demo
stringData:
  accessKey: YOUR_ACCESS_KEY
  secretKey: YOUR_SECRET_KEY
  endpoint: https://s3.example.com
  region: default
  bucket.registry: gitlab-demo-registry
  bucket.lfs: gitlab-demo-lfs
  bucket.artifacts: gitlab-demo-artifacts
  bucket.uploads: gitlab-demo-uploads
  bucket.packages: gitlab-demo-packages
  bucket.mr-diffs: gitlab-demo-mr-diffs
  bucket.terraform: gitlab-demo-terraform
  bucket.ci-secure-files: gitlab-demo-ci-secure-files
  bucket.dependency-proxy: gitlab-demo-dependency-proxy
  bucket.backups: gitlab-demo-backups
  bucket.pages: gitlab-demo-pages

See Object Storage for the full key reference.

Step 4 — Watch the instance come up

kubectl get gli -n gitlab-demo -w
# NAME          PHASE          HOST                       VERSION   AGE
# gitlab-demo   Provisioning                                        30s
# gitlab-demo   Deploying      https://git.example.com   18.11.6   4m
# gitlab-demo   Ready          https://git.example.com   18.11.6   8m

The phase sequence is PendingProvisioning (managed backends starting) → Deploying (HelmRelease emitted, Flux installing) → Ready.

The first run takes 5–10 minutes because the managed PostgreSQL cluster must initialise. If it stays in Provisioning beyond 15 minutes, see Troubleshooting.

Step 5 — Verify the deployment

# Status and conditions
kubectl describe gli gitlab-demo -n gitlab-demo

# Flux HelmRelease (the actual chart install)
kubectl get helmrelease -n gitlab-demo

# GitLab pods
kubectl get pods -n gitlab-demo

# Managed Postgres cluster
kubectl get perconapgcluster -n gitlab-demo

# Managed Redis
kubectl get redis -n gitlab-demo 2>/dev/null || kubectl get redisreplication -n gitlab-demo

Step 6 — Log in as root

The initial root password is stored in a Secret generated by the upstream GitLab chart:

kubectl get secret gitlab-demo-gitlab-initial-root-password \
  -n gitlab-demo \
  -o jsonpath='{.data.password}' | base64 -d; echo

Open https://git.example.com in your browser and log in with username root and the password above. Change it immediately after first login.

Change the initial root password

The auto-generated root password is stored in a Kubernetes Secret. Copy it, log in, and set a strong password in GitLab's user settings before giving anyone else access.

What's next

  • Production topology (HA backends)?Managed Backends shows HA Postgres and Redis Sentinel configuration.
  • Enterprise Edition?Editions & Licensing covers the licenseSecret shape and what EE unlocks.
  • Upgrading?Version Management explains the required upgrade stop sequence (do not skip stops).
  • Object storage?Object Storage describes the full bucket-class mapping.
  • Custom node scheduling? → set spec.placement.nodeSelector and tolerations on the GitlabInstance.