# services/gitea/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: gitea namespace: gitea labels: app: gitea atlas.bstein.dev/workload-profile: heavy spec: replicas: 1 selector: matchLabels: app: gitea strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 maxSurge: 0 template: metadata: labels: app: gitea atlas.bstein.dev/workload-profile: heavy annotations: vault.hashicorp.com/agent-inject: "true" vault.hashicorp.com/agent-init-first: "true" vault.hashicorp.com/role: "gitea" vault.hashicorp.com/agent-inject-secret-gitea-db-secret__password: "kv/data/atlas/gitea/gitea-db-secret" vault.hashicorp.com/agent-inject-template-gitea-db-secret__password: | {{ with secret "kv/data/atlas/gitea/gitea-db-secret" }} {{ .Data.data.password }} {{ end }} vault.hashicorp.com/agent-inject-secret-gitea-secret__SECRET_KEY: "kv/data/atlas/gitea/gitea-secret" vault.hashicorp.com/agent-inject-template-gitea-secret__SECRET_KEY: | {{ with secret "kv/data/atlas/gitea/gitea-secret" }} {{ .Data.data.SECRET_KEY }} {{ end }} vault.hashicorp.com/agent-inject-secret-gitea-secret__INTERNAL_TOKEN: "kv/data/atlas/gitea/gitea-secret" vault.hashicorp.com/agent-inject-template-gitea-secret__INTERNAL_TOKEN: | {{ with secret "kv/data/atlas/gitea/gitea-secret" }} {{ .Data.data.INTERNAL_TOKEN }} {{ end }} vault.hashicorp.com/agent-inject-secret-gitea-oidc__client_id: "kv/data/atlas/gitea/gitea-oidc" vault.hashicorp.com/agent-inject-template-gitea-oidc__client_id: | {{ with secret "kv/data/atlas/gitea/gitea-oidc" }} {{ .Data.data.client_id }} {{ end }} vault.hashicorp.com/agent-inject-secret-gitea-oidc__client_secret: "kv/data/atlas/gitea/gitea-oidc" vault.hashicorp.com/agent-inject-template-gitea-oidc__client_secret: | {{ with secret "kv/data/atlas/gitea/gitea-oidc" }} {{ .Data.data.client_secret }} {{ end }} vault.hashicorp.com/agent-inject-secret-gitea-oidc__openid_auto_discovery_url: "kv/data/atlas/gitea/gitea-oidc" vault.hashicorp.com/agent-inject-template-gitea-oidc__openid_auto_discovery_url: | {{ with secret "kv/data/atlas/gitea/gitea-oidc" }} {{ .Data.data.openid_auto_discovery_url }} {{ end }} vault.hashicorp.com/agent-inject-secret-gitea-veles__client_id: "kv/data/atlas/gitea/gitea-veles-oidc" vault.hashicorp.com/agent-inject-template-gitea-veles__client_id: | {{ with secret "kv/data/atlas/gitea/gitea-veles-oidc" }} {{ .Data.data.client_id }} {{ end }} vault.hashicorp.com/agent-inject-secret-gitea-veles__client_secret: "kv/data/atlas/gitea/gitea-veles-oidc" vault.hashicorp.com/agent-inject-template-gitea-veles__client_secret: | {{ with secret "kv/data/atlas/gitea/gitea-veles-oidc" }} {{ .Data.data.client_secret }} {{ end }} vault.hashicorp.com/agent-inject-secret-gitea-veles__discovery_url: "kv/data/atlas/gitea/gitea-veles-oidc" vault.hashicorp.com/agent-inject-template-gitea-veles__discovery_url: | {{ with secret "kv/data/atlas/gitea/gitea-veles-oidc" }} {{ .Data.data.openid_auto_discovery_url }} {{ end }} vault.hashicorp.com/agent-inject-secret-gitea-veles__claim_name: "kv/data/atlas/gitea/gitea-veles-oidc" vault.hashicorp.com/agent-inject-template-gitea-veles__claim_name: | {{ with secret "kv/data/atlas/gitea/gitea-veles-oidc" }} {{ .Data.data.required_claim_name }} {{ end }} vault.hashicorp.com/agent-inject-secret-gitea-veles__claim_value: "kv/data/atlas/gitea/gitea-veles-oidc" vault.hashicorp.com/agent-inject-template-gitea-veles__claim_value: | {{ with secret "kv/data/atlas/gitea/gitea-veles-oidc" }} {{ .Data.data.required_claim_value }} {{ end }} vault.hashicorp.com/agent-inject-secret-gitea-veles__team_map: "kv/data/atlas/gitea/gitea-veles-oidc" vault.hashicorp.com/agent-inject-template-gitea-veles__team_map: | {{ with secret "kv/data/atlas/gitea/gitea-veles-oidc" }} {{ .Data.data.group_team_map }} {{ end }} spec: serviceAccountName: gitea-vault initContainers: - name: configure-oidc image: gitea/gitea:1.23 securityContext: runAsUser: 1000 runAsGroup: 1000 command: - /bin/sh - -c - | set -eu APPINI=/data/gitea/conf/app.ini BIN=/usr/local/bin/gitea read_secret() { path="$1" if [ ! -r "$path" ]; then echo "Missing readable Vault secret file: $path" >&2 return 1 fi tr -d '\r\n' <"$path" } CLIENT_ID="$(read_secret /vault/secrets/gitea-oidc__client_id || true)" CLIENT_SECRET="$(read_secret /vault/secrets/gitea-oidc__client_secret || true)" DISCOVERY_URL="$(read_secret /vault/secrets/gitea-oidc__openid_auto_discovery_url || true)" VELES_CLIENT_ID="$(read_secret /vault/secrets/gitea-veles__client_id || true)" VELES_CLIENT_SECRET="$(read_secret /vault/secrets/gitea-veles__client_secret || true)" VELES_DISCOVERY_URL="$(read_secret /vault/secrets/gitea-veles__discovery_url || true)" VELES_REQUIRED_CLAIM_NAME="$(read_secret /vault/secrets/gitea-veles__claim_name || true)" VELES_REQUIRED_CLAIM_VALUE="$(read_secret /vault/secrets/gitea-veles__claim_value || true)" VELES_GROUP_TEAM_MAP="$(read_secret /vault/secrets/gitea-veles__team_map || true)" if [ ! -r "$APPINI" ]; then echo "Gitea app.ini is not readable yet; skipping OIDC source maintenance" >&2 exit 0 fi if ! list="$($BIN -c "$APPINI" admin auth list)"; then echo "Gitea auth source list failed; skipping OIDC source maintenance" >&2 exit 0 fi ensure_oidc_source() { source_name="$1" source_scopes="$2" source_client_id="$3" source_client_secret="$4" source_discovery_url="$5" source_required_claim_name="$6" source_required_claim_value="$7" shift 7 id=$(echo "$list" | awk -v name="$source_name" '$2==name{print $1}') if [ -n "$id" ]; then echo "Updating auth source ${source_name} id=${id}" if ! $BIN -c "$APPINI" admin auth update-oauth \ --id "$id" \ --name "$source_name" \ --provider openidConnect \ --key "$source_client_id" \ --secret "$source_client_secret" \ --auto-discover-url "$source_discovery_url" \ --scopes "$source_scopes" \ --required-claim-name "$source_required_claim_name" \ --required-claim-value "$source_required_claim_value" \ --group-claim-name groups \ --admin-group admin \ --skip-local-2fa "$@"; then echo "OIDC update failed for ${source_name}; continuing without blocking startup" >&2 fi else echo "Creating auth source ${source_name}" if ! $BIN -c "$APPINI" admin auth add-oauth \ --name "$source_name" \ --provider openidConnect \ --key "$source_client_id" \ --secret "$source_client_secret" \ --auto-discover-url "$source_discovery_url" \ --scopes "$source_scopes" \ --required-claim-name "$source_required_claim_name" \ --required-claim-value "$source_required_claim_value" \ --group-claim-name groups \ --admin-group admin \ --skip-local-2fa "$@"; then echo "OIDC create failed for ${source_name}; continuing without blocking startup" >&2 fi fi } if [ -n "$CLIENT_ID" ] && [ -n "$CLIENT_SECRET" ] && [ -n "$DISCOVERY_URL" ]; then ensure_oidc_source keycloak "openid profile email groups" "$CLIENT_ID" "$CLIENT_SECRET" "$DISCOVERY_URL" "" "" else echo "Skipping keycloak auth source maintenance because atlas OIDC secret data is incomplete" >&2 fi if [ -n "$VELES_CLIENT_ID" ] && [ -n "$VELES_CLIENT_SECRET" ] && [ -n "$VELES_DISCOVERY_URL" ] && [ -n "$VELES_REQUIRED_CLAIM_NAME" ] && [ -n "$VELES_REQUIRED_CLAIM_VALUE" ]; then if [ -n "$VELES_GROUP_TEAM_MAP" ]; then ensure_oidc_source veles "openid profile email groups" "$VELES_CLIENT_ID" "$VELES_CLIENT_SECRET" "$VELES_DISCOVERY_URL" "$VELES_REQUIRED_CLAIM_NAME" "$VELES_REQUIRED_CLAIM_VALUE" \ --restricted-group "$VELES_REQUIRED_CLAIM_VALUE" \ --group-team-map "$VELES_GROUP_TEAM_MAP" else ensure_oidc_source veles "openid profile email groups" "$VELES_CLIENT_ID" "$VELES_CLIENT_SECRET" "$VELES_DISCOVERY_URL" "$VELES_REQUIRED_CLAIM_NAME" "$VELES_REQUIRED_CLAIM_VALUE" \ --restricted-group "$VELES_REQUIRED_CLAIM_VALUE" fi else echo "Skipping veles auth source maintenance because Veles OIDC secret data is incomplete" >&2 fi volumeMounts: - name: gitea-data mountPath: /data nodeSelector: node-role.kubernetes.io/worker: "true" affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: hardware operator: In values: ["rpi5"] preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 preference: matchExpressions: - key: hardware operator: In values: ["rpi5"] - weight: 100 preference: matchExpressions: - key: kubernetes.io/hostname operator: In values: ["titan-20","titan-21"] containers: - name: gitea image: gitea/gitea:1.23 command: ["/bin/sh", "-c"] args: - | set -euo pipefail export GITEA__security__SECRET_KEY="$(tr -d '\r\n'