Files
Homelabv4/apps/gitlab/values.yaml
T
Scooby HuskyandClaude Sonnet 5 bce3861083 GitLab cross-site replication Phase 2b: enable Gitaly + workhorse TLS
Per the approved plan (Istio federation scoped separately, current
NodePort/PeerAuth/cert-manager pattern continues for these 2 remaining
links). Real Let's Encrypt certs (not self-signed) via the same DNS-01
ClusterIssuer used everywhere else - both sites already trust Let's
Encrypt's public CA, no custom CA distribution needed.

- global.gitaly.tls.enabled: adds tls_listen_addr (8076) alongside the
  existing plaintext listener (8075, stays for in-cluster traffic
  that doesn't need it). Requires
  global.praefect.virtualStorages[0].tlsSecretName (chart's own NOTES.txt
  validation rejects the render without it, confirmed live).
- global.workhorse.tls.enabled + global.workhorse.host: Gitaly's [gitlab]
  url (internal-API callback for gitlab-shell hooks) switches from an
  unpublishable *.svc.cluster.local name to a real floating hostname
  (gitlab-internal-api.ha.huskypup.net) that Let's Encrypt CAN certify -
  confirmed live this replaces the plaintext [[listeners]] block with
  [listeners.tls] on the SAME port (8181), not a second port like Gitaly.
- praefect-ha-configmap.yaml (the manually-patched live config) updated
  to tls:// + floating hostnames for all 3 home nodes, so home's own
  Praefect uses the identical addresses it'll hand the VPS as peer
  addresses once Phase 2b's 4th node lands.
- New CoreDNS rewrite for gitlab-internal-api.ha.huskypup.net (same
  local-rewrite pattern as pg-*/gitaly-* already have).

Sequencing note: applying live - Certificates must issue before the
TLS-enabling values land, or Gitaly/webservice pods fail to start
(missing secret for their init container's cert copy).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-22 14:24:13 -05:00

407 lines
14 KiB
YAML

# values/gitlab.values.yaml
# GitLab with Authentik OIDC SSO Integration
global:
hosts:
domain: kube.huskypup.net
gitlab:
name: gitlab.kube.huskypup.net
registry:
name: registry.gitlab.kube.huskypup.net
tls:
secretName: gitlab-tls
minio:
name: minio.gitlab.kube.huskypup.net
tls:
secretName: gitlab-tls
kas:
name: kas.kube.huskypup.net
tls:
secretName: gitlab-tls
# Ingress disabled - Istio VirtualServices handle routing
ingress:
enabled: false
configureCertmanager: false # Use cluster-wide cert-manager, not GitLab's
# Edition: Community Edition
edition: ce
# Time zone
time_zone: UTC
# Email configuration (configure as needed)
email:
from: 'gitlab@kube.huskypup.net'
display_name: GitLab
reply_to: 'noreply@kube.huskypup.net'
# External PostgreSQL configuration
# NOTE: PgBouncer service currently has no endpoints (replicas=0),
# so GitLab is pointed directly at the CNPG primary service.
psql:
host: pg-gitlab-rw.gitlab.svc.cluster.local
port: 5432
database: gitlabhq_production
username: app
password:
secret: pg-gitlab-app
key: password
# Gitaly configuration - using Praefect for HA
gitaly:
enabled: true # Enabled to deploy Gitaly pods
internal:
names: [] # No internal Gitaly, using Praefect
external: [] # Praefect configured below
# GitLab cross-site replication (see
# /home/scooby/.claude/plans/jiggly-snacking-iverson.md) - Gitaly's
# gRPC has no TLS by default. The VPS's 4th node has to be reached
# over the same public UniFi WAN forward already used for Postgres
# (confirmed live the direct-Netbird-IP path doesn't accept inbound
# connections to home, same as the existing etcd quorum) - without
# this, that WAN hop would carry the gitaly_token,
# gitlab_shell_secret, and raw repository contents in plaintext.
# Chart-native support (tls_listen_addr alongside the existing
# plaintext listener, both stay active) - cert is a real Let's
# Encrypt cert via the same DNS-01 ClusterIssuer already used
# everywhere else (gitaly-tls-certificate.yaml), not a self-signed
# one, so no custom CA needs distributing to either site.
tls:
enabled: true
# Gitaly's [gitlab] url (the internal-API callback every Gitaly node
# uses for gitlab-shell hooks) - a real, TLS-supported override,
# confirmed live via gitlab/charts/gitlab/templates/_workhorse.tpl.
# Uses the SAME floating-hostname + CoreDNS-local-rewrite pattern
# already proven for Postgres and Gitaly's own node addresses: home's
# 3 Gitaly nodes resolve this locally (no WAN round-trip), the VPS's
# 4th node resolves it via the UniFi WAN forward - one consistent
# https:// URL for every node regardless of site, rather than trying
# to TLS-certify an unpublishable *.svc.cluster.local name (which
# Let's Encrypt fundamentally can't issue for).
workhorse:
host: gitlab-internal-api.ha.huskypup.net
tls:
enabled: true
# Praefect configuration
praefect:
enabled: true
# Use CNPG database secret
dbSecret:
secret: pg-praefect-app
key: password
virtualStorages:
- name: default
gitalyReplicas: 3 # Production HA
maxUnavailable: 1
# Required once global.gitaly.tls.enabled: true - the chart's own
# NOTES.txt validation rejects the render without it ("not
# specified ('default')... not supported", confirmed live).
# Matches gitlab.gitaly.tls.secret's default name/keys
# (gitaly-tls-certificate.yaml issues into this exact secret).
tlsSecretName: gitlab-gitaly-tls
# Praefect PostgreSQL configuration
psql:
host: pg-praefect-rw.gitlab.svc.cluster.local
port: 5432
dbName: praefect_production
user: app
# External Redis configuration - using standalone Redis for writes
# (replicated Redis service causes READONLY errors from replicas)
redis:
host: redis-gitlab-standalone.gitlab.svc.cluster.local
port: 6379
auth:
enabled: true
secret: redis-gitlab-secret
key: password
# Application Configuration
appConfig:
# OmniAuth SSO Configuration
#
# CORRECTED 2026-08-21 (second time - see git history for the wrong
# 2026-08-20 fix that removed this list entirely). This IS the real,
# actually-processed OIDC config mechanism for the CNG webservice
# image (chart's gitlab.appConfig.omniauth.configuration template,
# infra/_omniauth.tpl) - GITLAB_OMNIBUS_CONFIG below is an
# omnibus-image-only convention this image never processes, so it
# was always a documentation-only no-op despite looking functional.
# gitlab-oidc-secret's `provider` key now holds a full YAML-encoded
# provider block (apps/gitlab/manifests/external-secret-oidc.yaml),
# loaded via Ruby's YAML.load_file at container start - not raw
# client_id/secret strings, which is why plain GITLAB_OIDC_CLIENT_ID/
# SECRET keys alone (yesterday's assumption) were never enough.
omniauth:
enabled: true
allowSingleSignOn: ['openid_connect']
blockAutoCreatedUsers: false
autoLinkUser: ['openid_connect']
syncProfileFromProvider: ['openid_connect']
syncProfileAttributes: ['email', 'name']
providers:
- secret: gitlab-oidc-secret
key: provider
# Settings for Let's Encrypt ACME Issuer - disabled, using cluster-wide cert-manager
certmanager-issuer:
email: admin@kube.huskypup.net
# Authentik OIDC Configuration via Rails omnibus config
# Note: Credentials are loaded from gitlab-oidc-secret via environment variables
# SAML Configuration via Rails omnibus config
# Note: SAML provider configuration is loaded from gitlab-saml-secret
# PostgreSQL (external via CloudNativePG)
postgresql:
install: false
# Redis (external)
redis:
install: false
# PgBouncer connection pooler
# NOTE: PgBouncer is deployed via CNPG Pooler CRD (see pgbouncer-pooler.yaml)
# This setting disables GitLab's bundled PgBouncer chart
pgbouncer:
enabled: false # Using external CNPG Pooler instead
# MinIO for object storage
minio:
persistence:
storageClass: rook-ceph-block
size: 100Gi # Production storage
resources:
requests:
cpu: 100m
memory: 512Mi
limits:
memory: 2Gi
# Container Registry - enabled with S3 storage
registry:
enabled: true
hpa:
minReplicas: 1
maxReplicas: 1
resources:
requests:
cpu: 25m
memory: 128Mi
limits:
memory: 1Gi
# GitLab components
gitlab:
# GitLab Webservice - Main application
webservice:
minReplicas: 2
maxReplicas: 3
workerProcesses: 3
# Note: hostAliases for OIDC SSL validation are applied via helmfile postsync hook
# (GitLab chart doesn't support hostAliases in values.yaml)
extraEnvFrom:
GITLAB_OIDC_CLIENT_ID:
secretKeyRef:
name: gitlab-oidc-secret
key: GITLAB_OIDC_CLIENT_ID
GITLAB_OIDC_CLIENT_SECRET:
secretKeyRef:
name: gitlab-oidc-secret
key: GITLAB_OIDC_CLIENT_SECRET
GITLAB_SAML_IDP_FINGERPRINT:
secretKeyRef:
name: gitlab-saml-secret
key: GITLAB_SAML_IDP_FINGERPRINT
GITLAB_SAML_IDP_SSO_URL:
secretKeyRef:
name: gitlab-saml-secret
key: GITLAB_SAML_IDP_SSO_URL
extraEnv:
GITLAB_OMNIBUS_CONFIG: |
# Authentik OIDC Configuration
gitlab_rails['omniauth_enabled'] = true
gitlab_rails['omniauth_allow_single_sign_on'] = ['openid_connect', 'saml']
gitlab_rails['omniauth_block_auto_created_users'] = false
gitlab_rails['omniauth_auto_link_user'] = ['openid_connect', 'saml']
gitlab_rails['omniauth_auto_sign_in_with_provider'] = nil
gitlab_rails['omniauth_sync_profile_from_provider'] = ['openid_connect', 'saml']
gitlab_rails['omniauth_sync_profile_attributes'] = ['email', 'name']
gitlab_rails['omniauth_providers'] = [
{
'name' => 'openid_connect',
'label' => 'Authentik',
'args' => {
'name' => 'openid_connect',
'scope' => ['openid', 'profile', 'email'],
'response_type' => 'code',
'issuer' => 'https://auth.kube.huskypup.net/application/o/gitlab/',
'discovery' => true,
'client_auth_method' => 'query',
'uid_field' => 'sub',
'send_scope_to_token_endpoint' => true,
'pkce' => true,
'client_options' => {
'identifier' => ENV['GITLAB_OIDC_CLIENT_ID'],
'secret' => ENV['GITLAB_OIDC_CLIENT_SECRET'],
'redirect_uri' => 'https://gitlab.kube.huskypup.net/users/auth/openid_connect/callback'
}
}
},
{
'name' => 'saml',
'label' => 'Authentik SAML',
'args' => {
'assertion_consumer_service_url' => 'https://gitlab.kube.huskypup.net/users/auth/saml/callback',
'idp_cert_fingerprint' => ENV['GITLAB_SAML_IDP_FINGERPRINT'],
'idp_sso_target_url' => ENV['GITLAB_SAML_IDP_SSO_URL'],
'issuer' => 'https://gitlab.kube.huskypup.net',
'name_identifier_format' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
'attribute_statements' => {
'email' => ['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'],
'name' => ['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name'],
'first_name' => ['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname'],
'last_name' => ['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname']
}
}
}
]
# Homelab resource allocation
resources:
requests:
cpu: 300m
memory: 2Gi
limits:
memory: 4Gi
# GitLab KAS (Kubernetes Agent Server) - enabled for Kubernetes cluster integration
kas:
enabled: true
minReplicas: 1
maxReplicas: 1
resources:
requests:
cpu: 25m
memory: 256Mi
limits:
cpu: 500m
memory: 1Gi
# Gitaly Cluster (Praefect) - High Availability Git storage
gitaly:
# Note: enabled is in global.gitaly
persistence:
storageClass: rook-ceph-block
size: 200Gi # Production storage
# Production resources
resources:
requests:
cpu: 100m
memory: 512Mi
limits:
cpu: "1"
memory: 2Gi
# GitLab Runner - enabled for CI/CD
gitlab-runner:
install: false # Will be installed separately
# Praefect - Gitaly Cluster routing and transaction manager
praefect:
enabled: true
minReplicas: 1
maxReplicas: 1
# Note: Praefect PostgreSQL config is in global.praefect.psql
# Use CNPG-generated database secret
dbSecret:
secret: pg-praefect-app
key: password
# Resources
resources:
requests:
cpu: 25m
memory: 256Mi
limits:
cpu: 250m
memory: 512Mi
# (dead config removed 2026-08-22: this virtualStorages block never
# actually did anything - confirmed live the chart's Praefect
# ConfigMap template iterates global.praefect.virtualStorages, not
# this one, so gitalyReplicas: 3 up there always won regardless of
# what this said. See global.praefect.virtualStorages above for the
# real config.)
#
# GitLab cross-site replication (see
# /home/scooby/.claude/plans/jiggly-snacking-iverson.md): tried a
# values-only CONFIG_TEMPLATE_DIRECTORY redirect (extraEnv +
# extraVolumes/extraVolumeMounts) to add a VPS-hosted Gitaly node the
# chart has no mechanism to register - confirmed live this doesn't
# work: extraVolumeMounts and extraEnv both render correctly, but
# extraVolumes is a dead values key for THIS subchart specifically -
# charts/gitlab/charts/praefect/templates/statefulset.yaml's own
# volumes: list never calls the gitlab.extraVolumes helper at all
# (only volumeMounts does), so the mount has nothing to mount and the
# pod would fail to schedule. No values-only fix exists.
#
# Real fix: argocd-apps/apps/gitlab.yaml's ignoreDifferences now
# covers ConfigMap gitlab-praefect's `data` field, so Helm creates
# the object (with its own 3-node content) but ArgoCD stops
# reconciling its content afterward. The actual multi-node content
# lives in apps/gitlab/manifests/praefect-ha-configmap.yaml as a
# git-tracked reference/documentation copy (deployed under its own
# name, praefect-ha-config, harmless and otherwise unused) - the
# live gitlab-praefect ConfigMap gets kubectl-patched with that same
# content directly, same "documented but manually-applied"
# convention as every other cross-cluster secret in this plan.
# GitLab Exporter for Prometheus metrics
gitlab-exporter:
enabled: true
metrics:
enabled: true
# Sidekiq background jobs
sidekiq:
minReplicas: 1
maxReplicas: 1
# Note: hostAliases applied via helmfile postsync hook
# Homelab resources
resources:
requests:
cpu: 25m
memory: 512Mi
limits:
cpu: 250m
memory: 2Gi
# Disable components we already have in the cluster
certmanager:
install: false # Using cluster-wide cert-manager
installCRDs: false
prometheus:
install: false # Using existing Prometheus
nginx-ingress:
enabled: false # Istio handles ingress
# Disable GitLab Runner (configure separately if needed)
gitlab-runner:
install: false