titan-iac/services/gitea/deployment.yaml
2026-06-20 14:43:24 -03:00

299 lines
13 KiB
YAML

# 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' </vault/secrets/gitea-secret__SECRET_KEY)"
export GITEA__security__INTERNAL_TOKEN="$(tr -d '\r\n' </vault/secrets/gitea-secret__INTERNAL_TOKEN)"
export DB_PASS="$(tr -d '\r\n' </vault/secrets/gitea-db-secret__password)"
exec /usr/bin/entrypoint /usr/bin/s6-svscan /etc/s6
ports:
- containerPort: 3000
name: http
- containerPort: 2242
name: ssh
env:
- name: USER_UID
value: "1000"
- name: USER_GID
value: "1000"
- name: DEFAULT_BRANCH
value: "master"
- name: ROOT_URL
value: "https://scm.bstein.dev"
- name: GITEA__service__ENABLE_OPENID_SIGNIN
value: "true"
- name: GITEA__oauth2_client__ENABLE_AUTO_REGISTRATION
value: "true"
- name: GITEA__oauth2_client__ACCOUNT_LINKING
value: "auto"
- name: GITEA__service__ALLOW_ONLY_EXTERNAL_REGISTRATION
value: "true"
- name: GITEA__service__DISABLE_REGISTRATION
value: "false"
- name: GITEA__log__LEVEL
value: "trace"
- name: GITEA__service__REQUIRE_SIGNIN_VIEW
value: "false"
- name: GITEA__webhook__ALLOWED_HOST_LIST
value: "ci.bstein.dev"
- name: GITEA__server__PROXY_HEADERS
value: "X-Forwarded-For, X-Forwarded-Proto, X-Forwarded-Host"
- name: GITEA__session__COOKIE_SECURE
value: "true"
- name: GITEA__session__DOMAIN
value: "scm.bstein.dev"
- name: GITEA__session__SAME_SITE
value: "lax"
- name: DB_TYPE
value: "postgres"
- name: DB_HOST
value: "postgres-service.postgres.svc.cluster.local:5432"
- name: DB_NAME
value: "gitea"
- name: DB_USER
value: "gitea"
- name: START_SSH_SERVER
value: "true"
- name: SSH_PORT
value: "2242"
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
cpu: 1500m
memory: 2Gi
volumeMounts:
- name: gitea-data
mountPath: /data
volumes:
- name: gitea-data
persistentVolumeClaim:
claimName: gitea-data