Skip to content

GitLab

GitLab EE runs in the bootstrap namespace, deployed via the official Helm chart with custom images for the webservice and sidekiq components.

Custom Images

Two components run custom EE images built from internal Dockerfiles:

  • registry.mdapi.ch/mdapi/gitlab-webservice-ee
  • registry.mdapi.ch/mdapi/gitlab-sidekiq-ee

Both use pullPolicy: Always — restarting the pods picks up the new image without a Helm upgrade. Images are mirrored to zot.mdapi.ch (an OCI-compatible registry) before each upgrade to ensure availability if the internal registry is temporarily unreachable during the upgrade process.

Upgrade Flow

GitLab must be upgraded one minor version at a time (e.g. 18.10 → 18.11, never 18.10 → 18.12). A Windmill flow (f/gitlab/upgrade_flow) automates the process:

flowchart LR
    trigger["Trigger upgrade flow\nwindmill.mdapi.ch"]
    check["Check current vs\ntarget version"]
    build["Bump Dockerfile\ntag + trigger\nCI build"]
    mirror["Mirror image\nto zot.mdapi.ch\n(skopeo)"]
    helm["helm upgrade\ngitlab gitlab/gitlab\n--version <new>"]
    verify["Verify pods\nready"]

    trigger --> check --> build --> mirror --> helm --> verify

CI Pipeline — CVE Scanning

Every custom Docker image CI pipeline includes a security scan stage using Grype and Syft:

flowchart LR
    build["build\ndocker buildx"] --> scan["scan\nSyft SBOM\nGrype CVE check"] --> notify["notify\nPushover alert\n(HIGH/CRITICAL only)"]
    build --> push["push :latest\nto registry"]
  • Syft generates an SPDX JSON SBOM, stored as a 7-day CI artifact
  • Grype checks against the SBOM for HIGH and CRITICAL CVEs
  • Builds are non-blocking (allow_failure: true) — a CVE never stops a deployment
  • Alert threshold: any HIGH or CRITICAL finding triggers a Pushover notification at priority 1

This runs on 9 custom images: GitLab webservice/sidekiq, Keycloak, Chrony, Certspotter, Autoconfig, OpenNIC tier-2, Mirror, Threadfin, Joplin MCP, ZNC.

Runner Architecture

Runner ID Type API visibility Usage
156, 159 Group Non-admin API visible ~7 jobs/30d
172 Instance (Helm) Invisible to non-admin /api/v4/runners ~571 jobs/30d

Instance runners (type instance) are not returned by the standard runner list API unless the caller has admin privileges. Use the Rancher API pod health check or mint a temporary admin PAT to verify instance runner health.

Zot OCI Registry

Zot runs in the zot namespace as an OCI-native registry mirror at zot.mdapi.ch. It holds mirrored copies of the custom GitLab images and serves as a fallback during upgrades.

# Mirror an image to Zot before upgrade
skopeo copy \
  docker://registry.mdapi.ch/mdapi/gitlab-webservice-ee:latest \
  docker://zot.mdapi.ch/mdapi/gitlab-webservice-ee:latest \
  --creds zot:$PASSWORD   # --creds always needed even after skopeo login