GitLab Deployment and Runner Classes

GitLab CE 18.11.1 on a single VM at 30.30.30.5 behind HAProxy — internal LAN endpoint for automation, public route for browsers, eleven ct-* role groups, five planned runner classes, and the FG-1 readiness gate.

GitLab is the lab’s operational source for platform and application delivery. It hosts the platform GitOps repository that hub and spoke Argo CD pull from; it hosts application source for division teams; it triggers Jenkins via webhook; and (planned) it hosts protected runner classes for in-GitLab CI.

GitHub remains the planning surface for the opp-full-plat workspace — issues, milestones, ADRs, reports, handoffs. GitLab and GitHub together split the “what we plan vs what we execute” axis cleanly.

This page covers the GitLab VM deployment and the runner-class model. Sister pages cover the federated monorepo architecture (page 2), the protected runner model (page 3), and tokens/bots (page 4).

Architecture

Two distinct entry points by purpose:

  • Operators in browsershttps://gitlab.apps.sub.comptech-lab.com via HAProxy + LE wildcard.
  • Automation (Argo CD, Jenkins, future runners, platform API work) → the internal LAN endpoint directly on the lab /24, port 80, no TLS termination by HAProxy.

This split is non-negotiable per the operator guide.

What it is

PropertyValue
VMgitlab at 30.30.30.5
Internal LAN endpointhttp://30.30.30.5 (port 80, no TLS)
Human browser routehttps://gitlab.apps.sub.comptech-lab.com (TLS at HAProxy edge)
GitLab version18.11.1
EditionGitLab CE (non-Enterprise)
Current operational platform repocomptech-platform/openshift-ops/openshift-platform-gitops (project ID 12)
Local clone for the platform GitOps repo/home/ze/claude-agent/clones/platform-gitops (worktree-of-main convention)
Bootstrap admin userzahid
Operator PAT custodygitlab-md-pat file in the local-only secrets directory (Git-ignored)

Why a single VM CE

Per the operator guide:

  • CE is acceptable for the lab’s current scope — branch protection, merge requests, and approval rules at the CE feature level are enough.
  • Single VM matches the bootstrap pattern for all supporting services (Nexus, Jenkins, SigNoz, Trivy, DefectDojo, etc.).
  • Internal LAN endpoint as the automation surface keeps platform tools off the public path. Argo CD, Jenkins, GitLab Runner (future), and platform tooling use it; only humans use the public route.

CE has limitations vs Premium/Ultimate — most relevantly, certain advanced merge-rule features. When the lab hits one, the compensating control is CODEOWNERS, protected branches, validation pipelines, and documented MR evidence rather than upgrading the GitLab edition.

Endpoints, one more time

The two-endpoint distinction is the most-misused piece of the GitLab design. Repeating for clarity:

UseEndpoint
git clone for automation (Argo CD, Jenkins, runners)LAN endpoint, http://, port 80
git clone from a human operator workstationLAN endpoint OR public route — both work
Browser, MR review, issue trackingPublic route, https://gitlab.apps.*
API calls from automationLAN endpoint
API calls from an operator’s CLIEither; prefer LAN endpoint for consistency

Configuring Argo CD or Jenkins to use the public route is a drift indicator — it breaks the assumption that automation lives on the LAN, complicates TLS trust setup, and pulls automation behind the HAProxy SNI plane unnecessarily.

Current group structure

The federated group skeleton already exists (per the operator guide):

comptech-platform/
  openshift-ops/
    openshift-platform-gitops   (project ID 12, migrated from gitops/platform-gitops)
  infra-ops/
  platform-services/
  tenant-registry/

divisions/
  sandbox/
    openliberty-readiness-probe
    demo-smoke

Eleven ct-* role groups are already provisioned with bootstrap membership:

ct-gitlab-admins
ct-openshift-platform-maintainers
ct-openshift-platform-reviewers
ct-infra-platform-maintainers
ct-infra-platform-reviewers
ct-cicd-platform-maintainers
ct-security-reviewers
ct-auditors
ct-sandbox-app-maintainers
ct-sandbox-developers
ct-sandbox-release-approvers

The full ownership matrix lives in the federated monorepo page.

Runner classes (planned)

Per the operator guide, five runner classes are intended, each with a specific privilege bound:

ClassPurposeWhat it must NOT have
Validation runnerRender templates, lint, policy checkslive apply credentials
Build runnerBuild/test/scan app imagesplatform infra credentials
Security runnerTrivy/SBOM/SCA checksbroad deploy credentials
Ops runnerTerraform/OpenTofu, Ansible, platform API workshared with app builds; protected, restricted to platform repos
Deploy runnerVM runtime deploymentunrestricted target list; scoped to approved VM targets

The existing gitlab-vm-docker runner is project-scoped, unprotected, and runs untagged jobs — it is explicitly not the future trusted platform runner. Protected runner classes must be created under the GitLab Runner Operating Model milestone before production-like work.

Runner rules (per operator guide):

  • Use the internal LAN endpoint.
  • Store runner tokens outside Git.
  • Use protected runners for protected branches.
  • Don’t share ops runners with untrusted app builds.
  • Don’t put platform kubeconfigs or admin tokens on build runners.
  • OpenShift deploys through Argo CD pull, not runner-side oc apply.

Detailed runner privileges live on the protected runner model page.

FG-1 readiness gate — in progress

FG-1 is the first federated GitOps readiness gate — the named, repeatable bar that GitLab must clear before more divisions onboard or production-like CI runs in-GitLab. It is tracked under issue #83, governed by ADR 0023, and the formal ownership matrix it locks in lives on the federated monorepo architecture page.

The gate’s acceptance criteria, in current state:

CriterionStatusNotes
GitLab CE 18.11.1 at 30.30.30.5, public route via HAProxy LE wildcard, internal LAN endpoint reachableDonepreflight 2026-05-09; smart-HTTP clone fails through public route by design — automation uses LAN
Two-tree group skeleton (comptech-platform/ + divisions/) provisionedDone11 ct-* role groups created with bootstrap membership
openshift-platform-gitops at project ID 12, main protected, force-push disabled, Maintainers-only push/mergeDoneconfirmed live
CODEOWNERS on openshift-platform-gitopsIn progressCE limitations on approval-rule enforcement to be documented as a compensating control
Validation-only pipeline on openshift-platform-gitops (Kustomize render, YAML parse, no plaintext Secrets, no unmanaged public images, no app-team cluster-admin)In progressruns on the (planned) validation runner class only
Five protected runner classes provisioned with dedicated registration tokensOpencovered on the protected runner model page; current gitlab-vm-docker runner is not a substitute
Negative access tests (sandbox apps cannot write to platform repos, platform GitOps cannot read secrets, etc.)Openrun after CODEOWNERS + runner classes land
Documented MR mechanics for platform-gitops changes (PAT custody, sync-wave 10 convention, operator-install pattern)Donetokens-and-bots page documents the PAT flow; sync-wave convention lives in the platform GitOps repo

The gate’s compensating control posture matters: GitLab CE doesn’t expose the full approval-rules surface (the preflight saw HTTP 404 on the project approval-rules API). The lab compensates with CODEOWNERS, protected branches, the validation pipeline, and the protected-runner trust boundaries, rather than upgrading the GitLab edition.

FG-1 closes when every criterion above is Done. Until then, app-team onboarding stays inside the sandbox division.

Repository ownership

The bootstrap-phase intent is captured fully on the federated monorepo page. The summary table:

GitLab pathWritersDefault readers
comptech-platform/openshift-ops/openshift-platform-gitopsOpenShift/platform team onlyplatform, security, auditors
comptech-platform/infra-ops/vm-platform-ops (planned)Infra/platform tools teamOpenShift read, security, auditors
divisions/<division>/<division>-apps-monorepoDivision app teamplatform/CI/security as needed
divisions/<division>/<division>-gitopsDivision app team (inside guardrails)OpenShift/platform retains maintainer for guardrails/emergency rollback

Application teams must not write to:

  • openshift-platform-gitops
  • openshift-cluster-build
  • vm-platform-ops
  • Platform runner or admin configuration repos

Branch protection baseline

Every operational repository runs with:

  • Default branch main.
  • Protected main.
  • Force push disabled.
  • Direct push to main disabled except named break-glass maintainers.
  • Merge requests required for normal changes.
  • Approval required (one for non-production repos, two for production-impacting).
  • CODEOWNERS approval required for protected paths.
  • Pipeline required before merge where validation jobs exist.
  • Stale approval dismissal for production-impacting repos where the edition supports it.
  • MR templates for platform, infra, runner, and release repos.

Daily operator checks

# GitLab health
curl -fsS "http://30.30.30.5/-/readiness"
curl -fsS "http://30.30.30.5/-/liveness"

# API check
GITLAB_PAT="$(cat <secrets-dir>/gitlab-md-pat)"
curl -fsS --header "PRIVATE-TOKEN: $GITLAB_PAT" \
  "http://30.30.30.5/api/v4/version"
unset GITLAB_PAT

# Platform repo reachability
git ls-remote \
  http://30.30.30.5/comptech-platform/openshift-ops/openshift-platform-gitops.git \
  main

OpenShift GitOps consumer

The v6 OpenShift model is ACM plus OpenShift GitOps Basic pull. GitLab’s role:

  1. hub-dc-v6 Argo CD pulls from openshift-platform-gitops via the internal LAN endpoint.
  2. spoke-dc-v6 Argo CD does the same.
  3. GitLab must therefore be reachable from hub Argo CD repo-server, spoke Argo CD repo-server, Jenkins, future GitLab runners, and platform operator workstations — all using the LAN endpoint.

A platform repo Argo CD health check:

K_HUB=/home/ze/.kube/configs/hub-dc-v6.kubeconfig
K_SPOKE=/home/ze/.kube/configs/spoke-dc-v6.kubeconfig

oc --kubeconfig "$K_HUB"   -n openshift-gitops get app hub-dc-v6-bootstrap         -o wide
oc --kubeconfig "$K_SPOKE" -n openshift-gitops get app spoke-dc-v6-cluster-config -o wide

Expected: Synced Healthy.

Drift indicators

Per the operator guide, watch for:

  • Users directly added to many projects (should be via role groups).
  • App-team group appearing on openshift-platform-gitops.
  • Public route appearing in Argo CD/Jenkins/runner config.
  • Unprotected runner executing protected-branch jobs.
  • Direct pushes to main.
  • Missing session report for a live GitLab mutation.
  • Platform GitOps containing VM service configuration or application source.
  • App GitOps repo containing platform cluster-scoped guardrails.

Roadmap

Immediate (FG-1 close-out):

  1. Land CODEOWNERS on openshift-platform-gitops and document the CE compensating-control posture.
  2. Finish the validation-only pipeline (Kustomize render, YAML parse, no plaintext Secrets, no unmanaged public images, no app-team cluster-admin) — runs on the validation runner class only.
  3. Define and provision the five protected GitLab Runner classes and tags (covered on the protected runner model page).
  4. Negative access tests for sandbox apps against platform repos.
  5. Close FG-1 (issue #83) — all criteria in the FG-1 readiness gate table at Done.

Next:

  1. Create vm-platform-ops once ownership and first service adoption are ready.
  2. Create sandbox division repos with negative access tests.
  3. Move from bootstrap admin/PAT usage to named users, deploy tokens, and Vault-backed or protected variable custody.

Longer:

  • Support future hub-dr, spoke-dr, dev, UAT, staging, production OCP clusters.
  • Onboard multiple BFSI divisions.
  • Adopt HAProxy, PowerDNS, GitLab, Jenkins, Nexus, Docker runtime, Vault, Trivy, SigNoz into Git-tracked VM/platform operations.
  • Add audit evidence retention for GitLab changes.
  • Add signed commits for production-impacting repos if feasible.
  • Add automated access drift checks against the matrix.

References

  • opp-full-plat/connection-details/gitlab-operator-guide.md — canonical operator runbook.
  • opp-full-plat/adr/0023-federated-gitlab-group-repo-ownership.md — ownership model.
  • opp-full-plat/adr/0015-federated-gitops-repo-architecture.md — parent architecture decision.
  • opp-full-plat/adr/0018-acm-openshift-gitops-pull-model-v6.md — Argo CD pull-model consumer.
  • opp-full-plat/adr/0019-nexus-only-image-supply-chain.md — mirror ownership the platform GitOps owns.

Last reviewed: 2026-05-12