1
0
Fork 0
forked from infra/ansible

dist-git update to latest forgejo

Signed-off-by: David Kirwan <davidkirwanirl@gmail.com>
This commit is contained in:
David Kirwan 2026-07-31 16:41:01 +01:00
commit e7c3e5a28c
Signed by untrusted user: dkirwan
GPG key ID: A5893AB6474AC37D
49 changed files with 2674 additions and 291 deletions

View file

@ -4,8 +4,6 @@
user: root
gather_facts: false
vars:
replicas: 6 # Total nodes: 3 primaries + 1 replica each for HA
vars_files:
- /srv/web/infra/ansible/vars/global.yml
- "/srv/private/ansible/vars.yml"

View file

@ -0,0 +1,67 @@
# Dist-git OpenShift App Role
Deploys Fedora dist-git (src) on OpenShift via the Forgejo/Gitea Helm chart: namespace, storage, PostgreSQL, Valkey, Helm release, CI runners, and control-host backups.
**Playbook:** [`playbooks/openshift-apps/dist-git.yml`](../../../playbooks/openshift-apps/dist-git.yml)
Kept in feature parity with [`roles/openshift-apps/forgejo`](../forgejo/) but with dist-git naming (`dist-git` namespace, `dist-git-ha`, `distgit_*` private vars, packager OIDC map).
## Entry point and execution model
- **Hosts:** `os_control_stg` (prod `os_control` still commented in the playbook), `gather_facts: false`
- **Where work runs:** On the control host under `/root/ocp4/openshift-apps/dist-git/` — templates rendered there, then applied with `kubernetes.core.k8s`, `oc apply`, or `kubernetes.core.helm`
- **Pattern:** Hybrid OpenShift app — raw manifests plus the upstream [forgejo-helm](https://codeberg.org/fedora/forgejo-helm) chart
- **Secrets/config:** `env` (`production` / `staging`) ternaries in `templates/values.yaml.j2`. Sensitive vars from private vars (`/srv/private/ansible/vars.yml`)
## Task flow (`tasks/main.yaml`)
### 1. Control-host backup infrastructure
- Creates `/root/ocp4/openshift-apps/dist-git/backups/{script,dump,log}/`
- Cron: **02:00** backup, **03:00** prune
### 2. Kubernetes foundation
| Step | Task file | Deploys |
|------|-----------|---------|
| Namespace | `create-dist-git-namespace.yaml` | `dist-git` namespace |
| Storage | `create-dist-git-pvc.yaml` | PV + PVC (NetApp / ostree notes in templates) |
| Database | `create-postgres-operator-config.yaml` | Crunchy `PostgresCluster` `dist-git-ha` + metrics Service `dist-git-ha-metrics` (:9187) |
| Cache | `deploy-valkey.yaml` | Standalone Valkey (1 replica) + `valkey-exporter` (:9121) |
| App | `call-helm.yaml` | Helm release `dist-git` |
| Metrics | helm + `patch-dist-git-http-service-oauth-proxy.yaml` | oauth-proxy sidecar; `/metrics` auth |
| Zabbix metrics SA | `create-dist-git-metrics-zabbix-sa-rbac.yaml` | SA + RBAC + token Secret |
### 3. Application (Helm)
- **DB:** External Crunchy Postgres
- **Cache:** Standalone Valkey — `redis://` to `valkey-0.valkey.dist-git.svc.cluster.local:6379/0` (not cluster mode)
- **Auth:** OIDC to Fedora Accounts with packager `group-team-map`
- **Metrics:** oauth-proxy; SAR on service `dist-git-http`
### 4. CI runners
Same pipeline as forgejo (load → vars → secret → SA RBAC → VM → register). Runner definitions live under `runners/<env>/` (stub only until populated). Uses [ansible-role-forgejo-runner](https://codeberg.org/fedora/ansible-role-forgejo-runner) via ansible-pull on the VM.
## Monitoring scrape URLs (in-cluster Zabbix proxy)
| Target | URL |
|--------|-----|
| App `/metrics` | Public hostname `/metrics` (Bearer token from `dist-git-metrics-zabbix` SA) |
| Postgres exporter | `http://dist-git-ha-metrics.dist-git.svc.cluster.local:9187/metrics` |
| Valkey exporter | `http://valkey-exporter.dist-git.svc.cluster.local:9121/metrics` |
Zabbix template exports: `files/zabbix/` (manual import; see README there).
## Private vars to set (ansible-private)
Beyond existing `distgit_*` / `distgit_stg_*` hostnames, DB, OIDC, Valkey password, runner secrets:
- `distgit_metrics` / `distgit_stg_metrics` — enable app Prometheus endpoint
- `distgit_metrics_servicemonitor` / `distgit_stg_metrics_servicemonitor` (usually false)
- `distgit_oauth_proxy_cookie_secret` / `distgit_stg_oauth_proxy_cookie_secret` (`openssl rand -base64 32`)
## Ops notes
- First deploy after Valkey standalone alignment **replaces** any prior 6-node cluster; expect brief cache/session disruption.
- Theme ConfigMap task remains available but is not wired in `main.yaml` (same as forgejo).

View file

@ -1,4 +0,0 @@
---
forgejo_namespace: "forgejo"
forgejo_project_description: "Forgejo Gitforge"
forgejo_application_name: "{{ forgejo_namespace }}"

View file

@ -0,0 +1,66 @@
---
distgit_namespace: "dist-git"
# Crunchy PostgresCluster name (matches templates/postgres-cluster.yaml.j2).
distgit_postgres_cluster_name: dist-git-ha
# ClusterIP Service for postgres_exporter sidecars (Zabbix HTTP scrape).
distgit_postgres_metrics_service_name: dist-git-ha-metrics
distgit_postgres_metrics_port: 9187
# KubeVirt headless Service name; must match spec.template.spec.subdomain and the
# network.kubevirt.io/headlessService label (cluster DNS: <vm-name>.<name>.<ns>.svc.cluster.local).
distgit_runnerhost_headless_service_name: "dist-git-runnerhost"
distgit_project_description: "Fedora dist-git (src)"
distgit_application_name: "{{ distgit_namespace }}"
distgit_runnerhost_packages:
- ansible
- podman
- python3
- python3-kubernetes
- git
- cronie
- gawk
- sed
- zabbix-agent
- zabbix
- ca-certificates
# Zabbix agent on the runnerhost VM (ansible-role-forgejo-runner reads these from dist-git-runners-vars.yaml).
# In-cluster proxy Service DNS — same default as roles/zabbix/zabbix_openshift_proxy.
distgit_runnerhost_zabbix_proxy_host: "{{ zabbix_openshift_agent_server_hostname | default('zabbix-zabbix-helm-chart-proxy.zabbix.svc.cluster.local') }}"
# OpenShift SDN pod network: passive polls from the proxy use pod source IPs (e.g. 10.131.x.x), not the Service ClusterIP.
distgit_runnerhost_openshift_pod_network_cidr: "{{ zabbix_openshift_pod_network_cidr | default('10.128.0.0/14') }}"
# Agent Server= allowlist (proxy DNS + cluster service CIDR + pod CIDR).
distgit_runnerhost_zabbix_agent_server:
- "{{ distgit_runnerhost_zabbix_proxy_host }}"
- "10.16.0.0/16"
- "{{ distgit_runnerhost_openshift_pod_network_cidr }}"
distgit_runnerhost_zabbix_agent_server_active: "{{ distgit_runnerhost_zabbix_proxy_host }}:10051"
# oauth-proxy sidecar on the dist-git pod protects /metrics via OpenShift OAuth.
# Set distgit_oauth_proxy_cookie_secret / distgit_stg_oauth_proxy_cookie_secret in
# ansible-private (openssl rand -base64 32).
distgit_metrics_oauth_proxy_port: 8080
distgit_metrics_oauth_proxy_prefix: /dist-git-metrics-oauth
distgit_metrics_oauth_proxy_auth_regex: "^/metrics"
# Image tag is set from ClusterVersion (major.minor); fallback below.
distgit_metrics_oauth_proxy_image_repo: quay.io/openshift/origin-oauth-proxy
distgit_metrics_oauth_proxy_image_version: "4.22"
distgit_metrics_oauth_proxy_image: "{{ distgit_metrics_oauth_proxy_image_repo }}:{{ distgit_metrics_oauth_proxy_image_version }}"
distgit_metrics_oauth_proxy_service_name: dist-git-http
# Dist-git metrics Zabbix SA token + oauth-proxy --openshift-delegate-urls on /metrics.
distgit_metrics_zabbix_sa_name: dist-git-metrics-zabbix
distgit_metrics_zabbix_token_secret_name: dist-git-metrics-zabbix-token
# Valkey metrics via oliver006/redis_exporter (Prometheus text for Zabbix HTTP agent).
# Scrape URL: http://valkey-exporter.dist-git.svc.cluster.local:9121/metrics
distgit_valkey_exporter_image: oliver006/redis_exporter:v1.87.0
distgit_valkey_exporter_port: 9121
distgit_valkey_exporter_redis_addr: "valkey-0.valkey.{{ distgit_namespace }}.svc.cluster.local:6379"
distgit_valkey_exporter_metrics_url: "http://valkey-exporter.{{ distgit_namespace }}.svc.cluster.local:{{ distgit_valkey_exporter_port }}/metrics"
# App Prometheus metrics toggles (override in private/group vars per env if needed).
distgit_metrics: false
distgit_stg_metrics: false
distgit_metrics_servicemonitor: false
distgit_stg_metrics_servicemonitor: false

View file

@ -0,0 +1,11 @@
#!/bin/sh
POD=`oc get pods -n dist-git --selector app.kubernetes.io/name=dist-git | awk '{print $1}' | grep dist-git`
echo $POD
oc -n dist-git rsync /root/ocp4/openshift-apps/dist-git/backups/script/ $POD:/tmp/
DUMP=`oc -n dist-git exec $POD sh /tmp/run_dist_git_dump.sh 2>&1 | tail -1`
echo $DUMP
oc -n dist-git rsync $POD:$DUMP /root/ocp4/openshift-apps/dist-git/backups/dump/
oc -n dist-git exec $POD sh /tmp/run_dist_git_cleanup.sh

View file

@ -0,0 +1,122 @@
#!/bin/bash
# Backup management script configuration
BACKUP_DIR="/root/ocp4/openshift-apps/dist-git/backups/dump/"
LOG_FILE="/root/ocp4/openshift-apps/dist-git/backups/log/dist_git_backup_prune.log"
# Retention settings - how many backups to keep at each tier
DAILY_RETENTION=2 # Keep 2 daily backups
WEEKLY_RETENTION=0 # Keep 0 weekly backups
MONTHLY_RETENTION=0 # Keep 0 monthly backups
YEARLY_RETENTION=0 # Keep 0 yearly backups
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}
# Prune backups of a given tier, keeping only the N most recent
# Usage: prune_tier "pattern" retention_count "tier_name"
prune_tier() {
local pattern="$1"
local retention="$2"
local tier="$3"
[[ $retention -lt 0 ]] && retention=0
local backups=$(find "$BACKUP_DIR" -name "$pattern" -printf "%T@ %p\n" 2>/dev/null | sort -nr | cut -d' ' -f2)
local count=$(echo "$backups" | grep -c . 2>/dev/null || echo 0)
if [[ $count -gt $retention ]]; then
echo "$backups" | tail -n +$((retention + 1)) | xargs -r rm -f
log "Pruned $tier backups: kept $retention of $count"
fi
}
# Ensure backup directory exists
mkdir -p "$BACKUP_DIR"
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root"
exit 1
fi
log "Starting backup pruning process"
# Step 1: Prune daily backups with size protection
DAILY_BACKUPS=$(find "$BACKUP_DIR" -name "dist-git-dump-*.zip" -printf "%T@ %p\n" | sort -nr | cut -d' ' -f2)
DAILY_COUNT=$(echo "$DAILY_BACKUPS" | grep -c . 2>/dev/null || echo 0)
if [[ $DAILY_COUNT -gt $DAILY_RETENTION ]]; then
LATEST_BACKUP=$(echo "$DAILY_BACKUPS" | head -n 1)
LATEST_SIZE=$(stat -c%s "$LATEST_BACKUP" 2>/dev/null || echo 0)
# Find the largest older backup
LARGEST_OLDER=""
LARGEST_OLDER_SIZE=0
while read -r backup; do
[[ -z "$backup" ]] && continue
SIZE=$(stat -c%s "$backup" 2>/dev/null || echo 0)
if [[ $SIZE -gt $LARGEST_OLDER_SIZE ]]; then
LARGEST_OLDER_SIZE=$SIZE
LARGEST_OLDER="$backup"
fi
done <<< "$(echo "$DAILY_BACKUPS" | tail -n +2)"
# Protect largest if latest is suspiciously small
PROTECT=""
if [[ $LATEST_SIZE -lt $LARGEST_OLDER_SIZE && -n "$LARGEST_OLDER" ]]; then
PROTECT="$LARGEST_OLDER"
log "WARNING: Latest backup ($LATEST_SIZE bytes) smaller than largest ($LARGEST_OLDER_SIZE bytes)"
log "Protecting: $LARGEST_OLDER"
fi
# Delete old backups, protecting the largest if needed
KEPT=0
while read -r backup; do
[[ -z "$backup" ]] && continue
if [[ $KEPT -lt $DAILY_RETENTION ]]; then
((KEPT++))
elif [[ "$backup" == "$PROTECT" ]]; then
log "Kept protected: $(basename "$backup")"
else
rm -f "$backup"
log "Deleted: $(basename "$backup")"
fi
done <<< "$DAILY_BACKUPS"
fi
# Step 2-4: Tiered backups (only if retention > 0)
# Weekly promotion (Sundays)
if [[ $WEEKLY_RETENTION -gt 0 && $(date +%u) -eq 7 ]]; then
LATEST=$(find "$BACKUP_DIR" -name "dist-git-dump-*.zip" -printf "%T@ %p\n" | sort -nr | head -n1 | cut -d' ' -f2)
if [[ -n "$LATEST" ]]; then
EPOCH=$(basename "$LATEST" | grep -o '[0-9]\{10,\}')
cp "$LATEST" "${BACKUP_DIR}/weekly$(date +%U)-dist-git-dump-${EPOCH}.zip"
log "Created weekly backup"
fi
prune_tier "weekly*-dist-git-dump-*.zip" "$WEEKLY_RETENTION" "weekly"
fi
# Monthly promotion (last day of month)
if [[ $MONTHLY_RETENTION -gt 0 && $(date -d tomorrow +%d) -eq 1 ]]; then
LATEST=$(find "$BACKUP_DIR" -name "weekly*-dist-git-dump-*.zip" -printf "%T@ %p\n" | sort -nr | head -n1 | cut -d' ' -f2)
if [[ -n "$LATEST" ]]; then
EPOCH=$(basename "$LATEST" | grep -o '[0-9]\{10,\}')
cp "$LATEST" "${BACKUP_DIR}/monthly$(date +%m)-dist-git-dump-${EPOCH}.zip"
log "Created monthly backup"
fi
prune_tier "monthly*-dist-git-dump-*.zip" "$MONTHLY_RETENTION" "monthly"
fi
# Yearly promotion (last day of year)
if [[ $YEARLY_RETENTION -gt 0 && $(date -d tomorrow +%j) -eq 1 ]]; then
LATEST=$(find "$BACKUP_DIR" -name "monthly*-dist-git-dump-*.zip" -printf "%T@ %p\n" | sort -nr | head -n1 | cut -d' ' -f2)
if [[ -n "$LATEST" ]]; then
EPOCH=$(basename "$LATEST" | grep -o '[0-9]\{10,\}')
cp "$LATEST" "${BACKUP_DIR}/yearly$(date +%Y)-dist-git-dump-${EPOCH}.zip"
log "Created yearly backup"
fi
prune_tier "yearly*-dist-git-dump-*.zip" "$YEARLY_RETENTION" "yearly"
fi
log "Backup pruning process completed"

View file

@ -0,0 +1,18 @@
#!/bin/bash
# sudo dnf install postgresql
# psql $(oc -n dist-git get secrets dist-git-pguser -o go-template='{{.data.uri | base64decode}}')
# psql --username=<db_user_name> databasename < data_base_dump
PG_CLUSTER_PRIMARY_POD=$(oc get pod \
-n dist-git \
-o name \
-l postgres-operator.crunchydata.com/cluster=dist-git-ha,postgres-operator.crunchydata.com/role=master)
oc -n dist-git port-forward "${PG_CLUSTER_PRIMARY_POD}" 5432:5432
PGPASSWORD=$(oc get secrets -n dist-git "dist-git-pguser" -o go-template='{{.data.password | base64decode}}')
PGUSER=$(oc get secrets -n dist-git "dist-git-pguser" -o go-template='{{.data.user | base64decode}}')
PGDATABASE=$(oc get secrets -n dist-git "dist-git-pguser" -o go-template='{{.data.dbname | base64decode}}')
psql -h localhost

View file

@ -0,0 +1,3 @@
#!/bin/sh
rm -f /tmp/forgejo-dump*.zip /tmp/dist-git-dump*.zip

View file

@ -0,0 +1,14 @@
#!/bin/sh
mkdir -p /tmp/dist_git_dump
cd /tmp/
/usr/local/bin/forgejo dump --tempdir /tmp/dist_git_dump
DUMP=`ls -t forgejo-dump*.zip | head -n1 | grep forgejo`
# rename to dist-git-dump for prune patterns
if [ -n "$DUMP" ]; then
NEW="dist-git-dump-${DUMP#forgejo-dump-}"
mv "$DUMP" "$NEW"
DUMP="$NEW"
fi
echo `realpath $DUMP`

View file

@ -0,0 +1,81 @@
# Dist-git Zabbix monitoring
Zabbix templates for dist-git OpenShift: app Prometheus `/metrics` and Crunchy PostgreSQL exporter.
| File | Purpose |
|------|---------|
| `template-dist-git.yml` | Zabbix 7.0 export — **Dist-git Monitoring** (app `/metrics`) |
| `template-dist-git-postgresql.yml` | Zabbix 7.0 export — **Dist-git PostgreSQL Monitoring** (Crunchy `:9187/metrics`) |
Both templates use an HTTP agent master item + `PROMETHEUS_PATTERN` dependents. Scrapes must run on the **OpenShift Zabbix proxy** (`openshift-cluster-proxy`), not the central server.
Feature parity with [`roles/openshift-apps/forgejo/files/zabbix`](../../forgejo/files/zabbix/).
---
## Dist-git app metrics (`template-dist-git.yml`)
### Prerequisites
- Dist-git metrics enabled (`distgit_metrics` / `distgit_stg_metrics` in private vars).
- `/metrics` reachable by the OpenShift Zabbix proxy HTTP agent poller.
- Authentication: oauth-proxy sidecar + `dist-git-metrics-zabbix` ServiceAccount (RBAC from `create-dist-git-metrics-zabbix-sa-rbac.yaml`).
### Host setup
1. Set **Monitored by proxy** to `openshift-cluster-proxy`.
2. Link template **Dist-git Monitoring**.
3. Override host macros:
| Macro | Description |
|-------|-------------|
| `{$DISTGIT.METRICS.URL}` | Full scrape URL (prod default: `https://src.fedoraproject.org/metrics`) |
| `{$DISTGIT.METRICS.TOKEN}` | Bearer token for metrics auth — use a **secret macro** |
| `{$DISTGIT.MEMORY.MAX}` | RSS warning threshold in bytes (default: 1 GiB) |
| `{$DISTGIT.GOROUTINES.MAX}` | Goroutine warning threshold (default: 500) |
Metric names use the upstream **`gitea_`** prefix.
---
## Dist-git PostgreSQL metrics (`template-dist-git-postgresql.yml`)
### Prerequisites
- `PostgresCluster` has `spec.monitoring.pgmonitor.exporter: {}`.
- Service `dist-git-ha-metrics` on port **9187**.
- In-cluster Zabbix proxy can reach `http://dist-git-ha-metrics.dist-git.svc.cluster.local:9187/metrics` (no auth).
### Host setup
1. **Monitored by** `openshift-cluster-proxy`.
2. Link **Dist-git PostgreSQL Monitoring**.
3. Default macro `{$DISTGIT.PG.METRICS.URL}` = `http://dist-git-ha-metrics.dist-git.svc.cluster.local:9187/metrics`.
Threshold macros mirror forgejo (`{$DISTGIT.PG.CONN.UTIL.WARN}`, disk free %, backup age, wraparound, etc.).
### ClusterIP caveat
`dist-git-ha-metrics` load-balances across primary and replica instance pods. Role-dependent series may flip between scrapes; triggers prefer metrics that work on either role or use `max()`/`min()` windows.
---
## Valkey exporter (no template yet)
Scrape URL for a future template / manual check:
`http://valkey-exporter.dist-git.svc.cluster.local:9121/metrics`
---
## Import (manual)
```yaml
community.zabbix.zabbix_template:
template_yaml: "{{ lookup('file', 'zabbix/template-dist-git.yml') }}"
state: present
community.zabbix.zabbix_template:
template_yaml: "{{ lookup('file', 'zabbix/template-dist-git-postgresql.yml') }}"
state: present
```

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,390 @@
zabbix_export:
version: '7.0'
template_groups:
- uuid: a333cbd6a3ad44baaa4eee4b0c0b1bec
name: Fedora
templates:
- uuid: ecf0b853cebc45308840c2dcfe1498f9
template: 'Dist-git Monitoring'
name: 'Dist-git Monitoring'
description: |
Prometheus metrics from the dist-git (Forgejo) /metrics endpoint.
Requires an HTTP agent poller (typically the in-cluster Zabbix proxy). Set host
macros before linking:
- {$DISTGIT.METRICS.URL} — full scrape URL (e.g. https://src.fedoraproject.org/metrics)
- {$DISTGIT.METRICS.TOKEN} — bearer token for oauth-proxy / metrics authentication
Master item fetches raw Prometheus text; dependents use PROMETHEUS_PATTERN extraction.
Metric names use the gitea_ prefix (Forgejo upstream convention).
groups:
- name: Fedora
items:
- uuid: cc2c04bd19b64648b829ab53e85b0400
name: 'Raw metrics'
type: HTTP_AGENT
key: distgit.get.metrics
delay: 1m
history: 1h
value_type: TEXT
trends: '0'
timeout: 15s
url: '{$DISTGIT.METRICS.URL}'
headers:
- name: Authorization
value: 'Bearer {$DISTGIT.METRICS.TOKEN}'
description: 'Master item for raw Prometheus metrics from Forgejo /metrics'
tags:
- tag: application
value: dist-git
- tag: component
value: raw
triggers:
- uuid: 82b32ea0795c493b9b5346f571661472
expression: 'nodata(/Dist-git Monitoring/distgit.get.metrics,30m)=1'
name: 'Dist-git: Failed to fetch metrics'
event_name: 'Dist-git: Failed to fetch metrics (no data for 30m)'
priority: WARNING
description: 'The Zabbix poller has not received /metrics data for 30 minutes.'
manual_close: 'YES'
tags:
- tag: scope
value: availability
- uuid: 0015498f81424c508c145a0aa73a2618
name: 'Process resident memory'
type: DEPENDENT
key: distgit.process.memory
delay: '0'
value_type: FLOAT
units: B
description: 'Resident memory size of the Forgejo process'
preprocessing:
- type: PROMETHEUS_PATTERN
parameters:
- process_resident_memory_bytes
- value
- ''
master_item:
key: distgit.get.metrics
tags:
- tag: application
value: dist-git
- tag: component
value: memory
triggers:
- uuid: bb5bcd15172a46a6a47998c368831920
expression: 'min(/Dist-git Monitoring/distgit.process.memory,15m)>{$DISTGIT.MEMORY.MAX}'
name: 'Dist-git: Process memory usage is high'
event_name: 'Dist-git: Process memory usage over {$DISTGIT.MEMORY.MAX} bytes for 15m'
priority: WARNING
manual_close: 'YES'
dependencies:
- name: 'Dist-git: Failed to fetch metrics'
expression: 'nodata(/Dist-git Monitoring/distgit.get.metrics,30m)=1'
tags:
- tag: scope
value: performance
- uuid: 653b1a9271dc4ed79d249e127260db4a
name: 'Go goroutines'
type: DEPENDENT
key: distgit.process.goroutines
delay: '0'
description: 'Number of active Go goroutines in the Forgejo process'
preprocessing:
- type: PROMETHEUS_PATTERN
parameters:
- go_goroutines
- value
- ''
master_item:
key: distgit.get.metrics
tags:
- tag: application
value: dist-git
- tag: component
value: performance
triggers:
- uuid: 4692f336b0f441348a1c9e1d8d52796b
expression: 'min(/Dist-git Monitoring/distgit.process.goroutines,15m)>{$DISTGIT.GOROUTINES.MAX}'
name: 'Dist-git: Goroutine count is high'
event_name: 'Dist-git: Goroutine count over {$DISTGIT.GOROUTINES.MAX} for 15m'
priority: WARNING
manual_close: 'YES'
dependencies:
- name: 'Dist-git: Failed to fetch metrics'
expression: 'nodata(/Dist-git Monitoring/distgit.get.metrics,30m)=1'
tags:
- tag: scope
value: performance
- uuid: 527b702f551b42b685daf3cb55074903
name: 'Process CPU utilization'
type: DEPENDENT
key: distgit.process.cpu.rate
delay: '0'
value_type: FLOAT
units: s/s
description: 'CPU time consumed per second by the Forgejo process'
preprocessing:
- type: PROMETHEUS_PATTERN
parameters:
- process_cpu_seconds_total
- value
- ''
- type: CHANGE_PER_SECOND
parameters:
- ''
- type: IN_RANGE
parameters:
- '0'
- ''
master_item:
key: distgit.get.metrics
tags:
- tag: application
value: dist-git
- tag: component
value: performance
- uuid: fd906b0596ad413da07bf8d2d6db0c0c
name: 'Process start time'
type: DEPENDENT
key: distgit.process.start_time
delay: '0'
value_type: FLOAT
units: unixtime
description: 'Unix epoch start time of the Forgejo process (changes on pod restart)'
preprocessing:
- type: PROMETHEUS_PATTERN
parameters:
- process_start_time_seconds
- value
- ''
master_item:
key: distgit.get.metrics
tags:
- tag: application
value: dist-git
- tag: component
value: health
triggers:
- uuid: a204878b7e294347945d5c59d3a06ad1
expression: |
last(/Dist-git Monitoring/distgit.process.start_time,#1)<>last(/Dist-git Monitoring/distgit.process.start_time,#2)
and last(/Dist-git Monitoring/distgit.process.start_time,#2)>0
name: 'Dist-git: Process has been restarted'
priority: INFO
description: 'Forgejo pod/process start time changed since the previous collection.'
manual_close: 'YES'
dependencies:
- name: 'Dist-git: Failed to fetch metrics'
expression: 'nodata(/Dist-git Monitoring/distgit.get.metrics,30m)=1'
tags:
- tag: scope
value: notice
- uuid: 1a2ddbb70072424b8c1008c93d08a89f
name: 'Hook task backlog'
type: DEPENDENT
key: distgit.tasks.hook
delay: '0'
description: 'Pending webhook delivery tasks (non-zero may indicate stuck hooks)'
preprocessing:
- type: PROMETHEUS_PATTERN
parameters:
- gitea_hooktasks
- value
- ''
master_item:
key: distgit.get.metrics
tags:
- tag: application
value: dist-git
- tag: component
value: queue
triggers:
- uuid: 301ea5c4af1a486d8ad64d88f2f0116e
expression: 'min(/Dist-git Monitoring/distgit.tasks.hook,30m)>0'
name: 'Dist-git: Hook task backlog'
event_name: 'Dist-git: Hook tasks pending for 30m'
priority: AVERAGE
description: 'Webhook delivery tasks have been queued for an extended period.'
manual_close: 'YES'
dependencies:
- name: 'Dist-git: Failed to fetch metrics'
expression: 'nodata(/Dist-git Monitoring/distgit.get.metrics,30m)=1'
tags:
- tag: scope
value: availability
- uuid: 7c83d6a64ce140b1bdb798ac153bd9d9
name: 'Update task backlog'
type: DEPENDENT
key: distgit.tasks.update
delay: '0'
description: 'Pending background update tasks (non-zero may indicate stuck work)'
preprocessing:
- type: PROMETHEUS_PATTERN
parameters:
- gitea_updatetasks
- value
- ''
master_item:
key: distgit.get.metrics
tags:
- tag: application
value: dist-git
- tag: component
value: queue
triggers:
- uuid: f96a890134774b44879178ffccb2db4a
expression: 'min(/Dist-git Monitoring/distgit.tasks.update,30m)>0'
name: 'Dist-git: Update task backlog'
event_name: 'Dist-git: Update tasks pending for 30m'
priority: AVERAGE
description: 'Background update tasks have been queued for an extended period.'
manual_close: 'YES'
dependencies:
- name: 'Dist-git: Failed to fetch metrics'
expression: 'nodata(/Dist-git Monitoring/distgit.get.metrics,30m)=1'
tags:
- tag: scope
value: availability
- uuid: a14bf0e52eb94fdba6b79f9cde8a5259
name: 'Users'
type: DEPENDENT
key: distgit.users
delay: '0'
description: 'Total registered users'
preprocessing:
- type: PROMETHEUS_PATTERN
parameters:
- gitea_users
- value
- ''
master_item:
key: distgit.get.metrics
tags:
- tag: application
value: dist-git
- tag: component
value: inventory
- uuid: c9251c1132814257bf1f5aa397c9f758
name: 'Repositories'
type: DEPENDENT
key: distgit.repositories
delay: '0'
description: 'Total repositories'
preprocessing:
- type: PROMETHEUS_PATTERN
parameters:
- gitea_repositories
- value
- ''
master_item:
key: distgit.get.metrics
tags:
- tag: application
value: dist-git
- tag: component
value: inventory
- uuid: 18e8a65d13f34847bbd87c582a0b85c2
name: 'Open issues'
type: DEPENDENT
key: distgit.issues.open
delay: '0'
description: 'Currently open issues'
preprocessing:
- type: PROMETHEUS_PATTERN
parameters:
- gitea_issues_open
- value
- ''
master_item:
key: distgit.get.metrics
tags:
- tag: application
value: dist-git
- tag: component
value: inventory
- uuid: efed1edffa6746d5bc56865e1772b958
name: 'Organizations'
type: DEPENDENT
key: distgit.organizations
delay: '0'
description: 'Total organizations'
preprocessing:
- type: PROMETHEUS_PATTERN
parameters:
- gitea_organizations
- value
- ''
master_item:
key: distgit.get.metrics
tags:
- tag: application
value: dist-git
- tag: component
value: inventory
- uuid: 611b72bd255349eaa398cf307313425d
name: 'Build version'
type: DEPENDENT
key: distgit.build.version
delay: '0'
value_type: CHAR
trends: '0'
description: 'Forgejo version string from gitea_build_info'
preprocessing:
- type: PROMETHEUS_PATTERN
parameters:
- gitea_build_info
- label
- version
master_item:
key: distgit.get.metrics
tags:
- tag: application
value: dist-git
- tag: component
value: inventory
- uuid: 56b5551ab6a8431db894c3f5ed10a264
name: 'Metrics handler errors'
type: DEPENDENT
key: distgit.metrics.errors
delay: '0'
description: 'Prometheus /metrics handler responses with HTTP 500'
preprocessing:
- type: PROMETHEUS_PATTERN
parameters:
- 'promhttp_metric_handler_requests_total{code="500"}'
- value
- ''
master_item:
key: distgit.get.metrics
tags:
- tag: application
value: dist-git
- tag: component
value: health
triggers:
- uuid: 7357d57378784a709ed70a763fd7abc4
expression: 'last(/Dist-git Monitoring/distgit.metrics.errors)>0'
name: 'Dist-git: Metrics handler returning errors'
priority: WARNING
manual_close: 'YES'
dependencies:
- name: 'Dist-git: Failed to fetch metrics'
expression: 'nodata(/Dist-git Monitoring/distgit.get.metrics,30m)=1'
tags:
- tag: scope
value: availability
macros:
- macro: '{$DISTGIT.METRICS.URL}'
value: 'https://src.fedoraproject.org/metrics'
description: 'Full URL of the Forgejo Prometheus /metrics endpoint'
- macro: '{$DISTGIT.METRICS.TOKEN}'
value: ''
description: 'Bearer token for /metrics authentication (set on host; secret macro recommended)'
- macro: '{$DISTGIT.MEMORY.MAX}'
value: '1073741824'
description: 'Maximum resident memory in bytes before warning (default 1 GiB)'
- macro: '{$DISTGIT.GOROUTINES.MAX}'
value: '500'
description: 'Maximum Go goroutine count before warning'

View file

@ -0,0 +1,36 @@
# Dist-git runner definitions
Each runner has one YAML file under `production/` or `staging/`. These files are public (this repo) and contain everything **except** the registration secret.
This directory is intentionally empty/stub until dist-git runners are defined. Do not copy forgejo org runner lists here.
## File format
```yaml
---
name: example-1
scope: global
labels:
- example-1
image: code.forgejo.org/forgejo/runner:11
```
- **name** — Unique runner name (must match the filename stem).
- **scope** — Org scope for `forgejo-cli actions register --scope` (omit or use `global` for instance-wide).
- **labels** — Workflow `runs-on` labels.
- **image** — Runner container image on the runner host.
- **capacity** — Optional concurrent job limit.
## Secrets (private ansible repo)
```yaml
distgit_runner_secrets:
example-1: "01c729e8f65dea42ddaf335dbfcf3841c71e58c8"
distgit_stg_runner_secrets:
# staging runners, same shape
```
Generate a new secret with: `openssl rand -hex 20`
`tasks/load-dist-git-runners.yaml` merges each definition file with its secret before templating and CLI registration.

View file

@ -10,6 +10,7 @@
ansible.builtin.git:
repo: "https://codeberg.org/fedora/forgejo-helm.git"
dest: /tmp/dist-git-helm_repo
version: main
- name: Build Helm chart dependencies
ansible.builtin.command:
@ -17,6 +18,14 @@
chdir: /tmp/dist-git-helm_repo/
changed_when: true
# dist-git-http Service defaults to targetPort "http" (app :3000). Route traffic must
# hit the oauth-proxy sidecar instead (container port name "oauth-proxy").
- name: Point dist-git-http Service at oauth-proxy in helm chart
ansible.builtin.replace:
path: /tmp/dist-git-helm_repo/templates/gitea/http-svc.yaml
regexp: 'targetPort: http'
replace: 'targetPort: oauth-proxy'
- name: Deploy Forgejo chart from local path
kubernetes.core.helm:
name: dist-git

View file

@ -5,12 +5,4 @@
dest: "/root/ocp4/openshift-apps/dist-git/dist-git-runners-vars.yaml"
mode: "0770"
- name: Checkout the Forgejo Runners Playbook
ansible.builtin.git:
repo: "https://codeberg.org/fedora/ansible-role-forgejo-runner.git"
dest: "/root/ocp4/openshift-apps/dist-git/ansible-role-forgejo-runner"
# Later we can extend this task to run the runners playbook/role
#
# ansible-role-forgejo-runner is applied on the VM via ansible-pull (see runnerhost VM cloud-init).

View file

@ -0,0 +1,55 @@
---
- name: Generate dist-git-http-auth-delegator-clusterrolebinding.yaml from template
ansible.builtin.template:
src: dist-git-http-auth-delegator-clusterrolebinding.yaml.j2
dest: "/root/ocp4/openshift-apps/dist-git/dist-git-http-auth-delegator-clusterrolebinding.yaml"
mode: "0770"
- name: Deploy dist-git-http-auth-delegator ClusterRoleBinding
kubernetes.core.k8s:
state: present
src: "/root/ocp4/openshift-apps/dist-git/dist-git-http-auth-delegator-clusterrolebinding.yaml"
- name: Generate the dist-git-metrics-zabbix-serviceaccount.yaml from template
ansible.builtin.template:
src: dist-git-metrics-zabbix-serviceaccount.yaml.j2
dest: "/root/ocp4/openshift-apps/dist-git/dist-git-metrics-zabbix-serviceaccount.yaml"
mode: "0770"
- name: Deploy the dist-git-metrics-zabbix-serviceaccount.yaml config
kubernetes.core.k8s:
state: present
src: "/root/ocp4/openshift-apps/dist-git/dist-git-metrics-zabbix-serviceaccount.yaml"
- name: Generate the dist-git-metrics-zabbix-view-rolebinding.yaml from template
ansible.builtin.template:
src: dist-git-metrics-zabbix-view-rolebinding.yaml.j2
dest: "/root/ocp4/openshift-apps/dist-git/dist-git-metrics-zabbix-view-rolebinding.yaml"
mode: "0770"
- name: Deploy the dist-git-metrics-zabbix-view-rolebinding.yaml config
kubernetes.core.k8s:
state: present
src: "/root/ocp4/openshift-apps/dist-git/dist-git-metrics-zabbix-view-rolebinding.yaml"
- name: Generate the dist-git-metrics-zabbix-auth-delegator-clusterrolebinding.yaml from template
ansible.builtin.template:
src: dist-git-metrics-zabbix-auth-delegator-clusterrolebinding.yaml.j2
dest: "/root/ocp4/openshift-apps/dist-git/dist-git-metrics-zabbix-auth-delegator-clusterrolebinding.yaml"
mode: "0770"
- name: Deploy the dist-git-metrics-zabbix-auth-delegator-clusterrolebinding.yaml config
kubernetes.core.k8s:
state: present
src: "/root/ocp4/openshift-apps/dist-git/dist-git-metrics-zabbix-auth-delegator-clusterrolebinding.yaml"
- name: Generate the dist-git-metrics-zabbix-sa-token-secret.yaml from template
ansible.builtin.template:
src: dist-git-metrics-zabbix-sa-token-secret.yaml.j2
dest: "/root/ocp4/openshift-apps/dist-git/dist-git-metrics-zabbix-sa-token-secret.yaml"
mode: "0770"
- name: Deploy the dist-git-metrics-zabbix-sa-token-secret.yaml config
kubernetes.core.k8s:
state: present
src: "/root/ocp4/openshift-apps/dist-git/dist-git-metrics-zabbix-sa-token-secret.yaml"

View file

@ -0,0 +1,17 @@
---
# generate the templates for project to be created
- name: Copy the templates to the host
ansible.builtin.template:
src: "dist-git-runners-secret.yaml.j2"
dest: "/root/ocp4/openshift-apps/dist-git/dist-git-runners-secret.yaml"
mode: "0770"
vars:
distgit_runners_config_file:
"{{ lookup('template',
'dist-git-runners.yaml.j2')
}}"
- name: Deploy the dist-git-runners-secret.yaml config
kubernetes.core.k8s:
state: present
src: "/root/ocp4/openshift-apps/dist-git/dist-git-runners-secret.yaml"

View file

@ -0,0 +1,44 @@
---
- name: Generate the dist-git-runnerhost-serviceaccount.yaml from template
ansible.builtin.template:
src: "dist-git-runnerhost-serviceaccount.yaml.j2"
dest: "/root/ocp4/openshift-apps/dist-git/dist-git-runnerhost-serviceaccount.yaml"
mode: "0770"
- name: Deploy the dist-git-runnerhost-serviceaccount.yaml config
kubernetes.core.k8s:
state: present
src: "/root/ocp4/openshift-apps/dist-git/dist-git-runnerhost-serviceaccount.yaml"
- name: Generate the dist-git-runnerhost-role.yaml from template
ansible.builtin.template:
src: "dist-git-runnerhost-role.yaml.j2"
dest: "/root/ocp4/openshift-apps/dist-git/dist-git-runnerhost-role.yaml"
mode: "0770"
- name: Deploy the dist-git-runnerhost-role.yaml config
kubernetes.core.k8s:
state: present
src: "/root/ocp4/openshift-apps/dist-git/dist-git-runnerhost-role.yaml"
- name: Generate the dist-git-runnerhost-rolebinding.yaml from template
ansible.builtin.template:
src: "dist-git-runnerhost-rolebinding.yaml.j2"
dest: "/root/ocp4/openshift-apps/dist-git/dist-git-runnerhost-rolebinding.yaml"
mode: "0770"
- name: Deploy the dist-git-runnerhost-rolebinding.yaml config
kubernetes.core.k8s:
state: present
src: "/root/ocp4/openshift-apps/dist-git/dist-git-runnerhost-rolebinding.yaml"
- name: Generate the dist-git-runnerhost-sa-token-secret.yaml from template
ansible.builtin.template:
src: "dist-git-runnerhost-sa-token-secret.yaml.j2"
dest: "/root/ocp4/openshift-apps/dist-git/dist-git-runnerhost-sa-token-secret.yaml"
mode: "0770"
- name: Deploy the dist-git-runnerhost-sa-token-secret.yaml config
kubernetes.core.k8s:
state: present
src: "/root/ocp4/openshift-apps/dist-git/dist-git-runnerhost-sa-token-secret.yaml"

View file

@ -1,4 +1,15 @@
---
- name: Generate the dist-git-runnerhost-headless-service.yaml from template
ansible.builtin.template:
src: "dist-git-runnerhost-headless-service.yaml.j2"
dest: "/root/ocp4/openshift-apps/dist-git/dist-git-runnerhost-headless-service.yaml"
mode: "0770"
- name: Deploy the dist-git-runnerhost headless Service
kubernetes.core.k8s:
state: present
src: "/root/ocp4/openshift-apps/dist-git/dist-git-runnerhost-headless-service.yaml"
- name: Generate the dist-git-runnerhost-vm.yaml from template
ansible.builtin.template:
src: "dist-git-runnerhost-vm.yaml.j2"

View file

@ -21,6 +21,17 @@
state: present
src: "/root/ocp4/openshift-apps/dist-git/postgres-secret.yaml"
- name: Generate the postgres-metrics-service.yaml from template
ansible.builtin.template:
src: "postgres-metrics-service.yaml.j2"
dest: "/root/ocp4/openshift-apps/dist-git/postgres-metrics-service.yaml"
mode: "0770"
- name: Deploy the postgres-metrics-service.yaml config
kubernetes.core.k8s:
state: present
src: "/root/ocp4/openshift-apps/dist-git/postgres-metrics-service.yaml"
- name: Sleep for 30 seconds, allow postgresql time to come up and then continue with play
ansible.builtin.wait_for:
timeout: 30

View file

@ -73,3 +73,40 @@
tags:
- valkey
- name: Create the valkey-exporter deployment template
ansible.builtin.template:
src: "valkey-exporter-deployment.yaml.j2"
dest: "/root/ocp4/openshift-apps/dist-git/valkey-exporter-deployment.yaml"
mode: "0770"
tags:
- valkey
- valkey_exporter
- name: Oc apply resources for the valkey-exporter deployment
ansible.builtin.command: "/root/bin/oc apply -f /root/ocp4/openshift-apps/dist-git/valkey-exporter-deployment.yaml"
retries: 3
delay: 5
register: deployment_result
until: deployment_result.rc == 0
tags:
- valkey
- valkey_exporter
- name: Create the valkey-exporter service template
ansible.builtin.template:
src: "valkey-exporter-service.yaml.j2"
dest: "/root/ocp4/openshift-apps/dist-git/valkey-exporter-service.yaml"
mode: "0770"
tags:
- valkey
- valkey_exporter
- name: Oc apply resources for the valkey-exporter service
ansible.builtin.command: "/root/bin/oc apply -f /root/ocp4/openshift-apps/dist-git/valkey-exporter-service.yaml"
retries: 3
delay: 5
register: deployment_result
until: deployment_result.rc == 0
tags:
- valkey
- valkey_exporter

View file

@ -0,0 +1,38 @@
---
# Build distgit_runners from per-runner YAML files in runners/<env>/ plus secrets in private vars.
# Private vars (distgit_runner_secrets / distgit_stg_runner_secrets) must be a dict keyed by runner name:
# distgit_runner_secrets:
# example-1: "0123...hex40"
- name: Find dist-git runner definition files
ansible.builtin.set_fact:
_distgit_runner_def_paths: "{{ query('ansible.builtin.fileglob', role_path ~ '/runners/' ~ env ~ '/*.yml') | sort }}"
- name: Build distgit_runners from definitions and private secrets
ansible.builtin.set_fact:
distgit_runners: "{{ distgit_runners | default([]) + [_runner] }}"
loop: "{{ _distgit_runner_def_paths }}"
vars:
_def: "{{ lookup('ansible.builtin.file', item) | from_yaml }}"
_secrets: "{{ (env == 'production') | ternary(distgit_runner_secrets, distgit_stg_runner_secrets) }}"
_runner: "{{ _def | combine({'secret': _secrets[_def.name]}) }}"
when: _distgit_runner_def_paths | length > 0
- name: Set empty distgit_runners when no definition files exist
ansible.builtin.set_fact:
distgit_runners: []
when: _distgit_runner_def_paths | length == 0
- name: Validate each runner has a secret in private vars
ansible.builtin.assert:
that:
- _secrets[item.name] is defined
- _secrets[item.name] | length > 0
fail_msg: >-
Missing secret for runner '{{ item.name }}'.
Add it to {{ (env == 'production') | ternary('distgit_runner_secrets', 'distgit_stg_runner_secrets') }}
in the ansible private repo.
loop: "{{ distgit_runners }}"
vars:
_secrets: "{{ (env == 'production') | ternary(distgit_runner_secrets, distgit_stg_runner_secrets) }}"
when: distgit_runners | length > 0

View file

@ -3,12 +3,96 @@
ansible.builtin.file:
path: "/root/ocp4/openshift-apps/dist-git/"
state: directory
mode: '0755'
- include_tasks: create-dist-git-namespace.yaml
- include_tasks: create-dist-git-pvc.yaml
- include_tasks: create-postgres-operator-config.yaml
# - include_tasks: create-custom-theme-configmap.yaml
- include_tasks: deploy-valkey.yaml
- include_tasks: call-helm.yaml
- include_tasks: create-dist-git-runnerhost-vm.yaml
- include_tasks: copy-dist-git-runner-vars.yaml
- name: Ensures dist-git backup directories exist
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: '0755'
loop:
- /root/ocp4/openshift-apps/dist-git/backups/
- /root/ocp4/openshift-apps/dist-git/backups/script/
- /root/ocp4/openshift-apps/dist-git/backups/dump/
- /root/ocp4/openshift-apps/dist-git/backups/log/
- name: Copy dist-git backup scripts
ansible.builtin.copy:
src: "{{ item }}"
dest: /root/ocp4/openshift-apps/dist-git/backups/
owner: root
group: root
mode: '0755'
with_fileglob:
- run_dist_git_backup.sh
- run_dist_git_pruning.sh
- name: Copy dist-git helper scripts
ansible.builtin.copy:
src: "{{ item }}"
dest: /root/ocp4/openshift-apps/dist-git/backups/script/
owner: root
group: root
mode: '0755'
with_fileglob:
- script/*.sh
- name: Setup dist-git backup cron job
ansible.builtin.cron:
name: dist-git-backup
user: root
minute: "0"
hour: "2"
job: "/root/ocp4/openshift-apps/dist-git/backups/run_dist_git_backup.sh >> /root/ocp4/openshift-apps/dist-git/backups/log/backup_cronjob.log 2>&1"
- name: Setup dist-git pruning cron job
ansible.builtin.cron:
name: dist-git-pruning
user: root
minute: "0"
hour: "3"
job: "/root/ocp4/openshift-apps/dist-git/backups/run_dist_git_pruning.sh >> /root/ocp4/openshift-apps/dist-git/backups/log/prune_cronjob.log 2>&1"
- name: Create dist-git namespace
ansible.builtin.include_tasks: create-dist-git-namespace.yaml
- name: Create dist-git PVC
ansible.builtin.include_tasks: create-dist-git-pvc.yaml
- name: Create postgres operator config
ansible.builtin.include_tasks: create-postgres-operator-config.yaml
- name: Deploy valkey
ansible.builtin.include_tasks: deploy-valkey.yaml
- name: Set oauth-proxy image tag from cluster version
ansible.builtin.include_tasks: set-dist-git-metrics-oauth-proxy-image.yaml
- name: Deploy dist-git via Helm
ansible.builtin.include_tasks: call-helm.yaml
- name: Point dist-git-http Service at oauth-proxy sidecar
ansible.builtin.include_tasks: patch-dist-git-http-service-oauth-proxy.yaml
- name: Create dist-git metrics Zabbix SA RBAC
ansible.builtin.include_tasks: create-dist-git-metrics-zabbix-sa-rbac.yaml
tags:
- distgit_metrics_zabbix
- name: Load dist-git runners
ansible.builtin.include_tasks: load-dist-git-runners.yaml
- name: Copy dist-git runner vars
ansible.builtin.include_tasks: copy-dist-git-runner-vars.yaml
- name: Create dist-git runner config secret
ansible.builtin.include_tasks: create-dist-git-runner-config-secret.yaml
- name: Create dist-git runnerhost SA RBAC
ansible.builtin.include_tasks: create-dist-git-runnerhost-sa-rbac.yaml
- name: Create dist-git runnerhost VM
ansible.builtin.include_tasks: create-dist-git-runnerhost-vm.yaml
- name: Register dist-git runners
ansible.builtin.include_tasks: register-runners.yaml

View file

@ -0,0 +1,18 @@
---
# forgejo-helm Service targetPort "http" points at app :3000; with the oauth-proxy
# sidecar, Route traffic must reach the proxy instead.
- name: Point dist-git-http Service at oauth-proxy sidecar
kubernetes.core.k8s:
state: present
merge_type: merge
definition:
apiVersion: v1
kind: Service
metadata:
name: dist-git-http
namespace: "{{ distgit_namespace }}"
spec:
ports:
- name: http
port: 3000
targetPort: oauth-proxy

View file

@ -0,0 +1,36 @@
---
# Register runners in the dist-git Forgejo database using CLI (idempotent with --secret).
- name: Get dist-git pod name
kubernetes.core.k8s_info:
kind: Pod
namespace: dist-git
label_selectors:
- app.kubernetes.io/name=dist-git
register: distgit_pods
- name: Create registration tokens in dist-git database (idempotent with same secret)
kubernetes.core.k8s_exec:
namespace: dist-git
pod: "{{ distgit_pods.resources[0].metadata.name }}"
command: "forgejo forgejo-cli actions register --name {{ item['name'] }} --labels {{ item['labels'] | map('regex_replace', ':.*', '') | join(',') }} --secret {{ item['secret'] }}{{ ' --scope ' + item['scope'] if item['scope'] is defined and item['scope'] != 'global' else '' }}"
loop: "{{ distgit_runners }}"
register: distgit_cli_outputs
failed_when: >-
(distgit_cli_outputs.rc is defined
and distgit_cli_outputs.rc != 0
and 'duplicate key' not in (distgit_cli_outputs.stderr | default('')))
or (distgit_cli_outputs.rc is not defined
and 'duplicate key' not in (distgit_cli_outputs.msg | default('')))
when:
- distgit_pods.resources | length > 0
- distgit_runners | length > 0
- name: Display CLI registration results
ansible.builtin.debug:
msg: |
Runner: {{ item['item']['name'] }}
Labels: {{ item['item']['labels'] | join(', ') }}
Status: {% if item['rc'] is defined and item['rc'] == 0 %}Registered{% elif 'duplicate key' in (item['stderr'] | default('')) + (item['msg'] | default('')) %}Already exists{% else %}Failed: {{ item['msg'] | default('unknown error') }}{% endif %}
loop: "{{ distgit_cli_outputs.results }}"
when: distgit_cli_outputs is defined and distgit_cli_outputs.results is defined

View file

@ -0,0 +1,46 @@
---
- name: Query OpenShift ClusterVersion for oauth-proxy image tag
kubernetes.core.k8s_info:
api_version: config.openshift.io/v1
kind: ClusterVersion
name: version
register: distgit_cluster_version
failed_when: false
- name: Pick ClusterVersion status from API response
ansible.builtin.set_fact:
distgit_cluster_version_status: "{{ distgit_cluster_version.resources[0].status | default({}, true) }}"
when: distgit_cluster_version.resources | default([]) | length > 0
- name: Resolve OpenShift full version string from ClusterVersion status
ansible.builtin.set_fact:
distgit_ocp_version_raw: >-
{{
(distgit_cluster_version_status.desired | default({}, true)).version
| default(
(
(distgit_cluster_version_status.history | default([], true) | length) > 0
)
| ternary(
(distgit_cluster_version_status.history[0] | default({}, true)).version | default('', true),
''
),
true
)
}}
when: distgit_cluster_version_status is defined
- name: Extract OpenShift minor version from ClusterVersion
ansible.builtin.set_fact:
distgit_ocp_minor_version: '{{ distgit_ocp_version_raw | regex_replace(''^(\d+\.\d+).*'', ''\1'') }}'
when:
- distgit_ocp_version_raw is defined
- distgit_ocp_version_raw | length > 0
- name: Override oauth-proxy image with cluster OpenShift version
ansible.builtin.set_fact:
distgit_metrics_oauth_proxy_image: >-
{{ distgit_metrics_oauth_proxy_image_repo }}:{{ distgit_ocp_minor_version }}
when:
- distgit_ocp_minor_version is defined
- distgit_ocp_minor_version is match('^\d+\.\d+$')

View file

@ -0,0 +1,18 @@
---
# oauth-proxy must ask the API server "is this Bearer token valid?" — that requires
# system:auth-delegator on the dist-git-http SA (OpenShift requirement, not our invention).
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: dist-git-oauth-proxy-auth-delegator
labels:
app: dist-git
component: oauth-proxy
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: dist-git-http
namespace: {{ distgit_namespace }}

View file

@ -0,0 +1,20 @@
---
# Bearer tokens from this SA are validated by oauth-proxy --openshift-delegate-urls.
# Equivalent to:
# oc adm policy add-cluster-role-to-user system:auth-delegator \
# system:serviceaccount:{{ distgit_namespace }}:{{ distgit_metrics_zabbix_sa_name }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ distgit_metrics_zabbix_sa_name }}-auth-delegator
labels:
app: dist-git
component: metrics-zabbix
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: {{ distgit_metrics_zabbix_sa_name }}
namespace: {{ distgit_namespace }}

View file

@ -0,0 +1,16 @@
---
# Long-lived (non-expiring) ServiceAccount token for Zabbix HTTP agent checks.
# Unlike projected tokens, this does not expire and does not require
# kubelet-based refresh. The token is revoked when this Secret or the
# ServiceAccount is deleted.
apiVersion: v1
kind: Secret
metadata:
name: {{ distgit_metrics_zabbix_token_secret_name }}
namespace: {{ distgit_namespace }}
labels:
app: dist-git
component: metrics-zabbix
annotations:
kubernetes.io/service-account.name: {{ distgit_metrics_zabbix_sa_name }}
type: kubernetes.io/service-account-token

View file

@ -0,0 +1,9 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ distgit_metrics_zabbix_sa_name }}
namespace: {{ distgit_namespace }}
labels:
app: dist-git
component: metrics-zabbix

View file

@ -0,0 +1,20 @@
---
# Equivalent to:
# oc policy add-role-to-user view -n {{ distgit_namespace }} \
# system:serviceaccount:{{ distgit_namespace }}:{{ distgit_metrics_zabbix_sa_name }}
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ distgit_metrics_zabbix_sa_name }}-view
namespace: {{ distgit_namespace }}
labels:
app: dist-git
component: metrics-zabbix
subjects:
- kind: ServiceAccount
name: {{ distgit_metrics_zabbix_sa_name }}
namespace: {{ distgit_namespace }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: view

View file

@ -0,0 +1,18 @@
---
# Headless Service for KubeVirt VM pod DNS (subdomain + network.kubevirt.io/headlessService on the VM).
# VirtualMachine FQDN: <vm-metadata.name>.{{ distgit_runnerhost_headless_service_name }}.{{ distgit_namespace }}.svc.cluster.local
apiVersion: v1
kind: Service
metadata:
name: "{{ distgit_runnerhost_headless_service_name }}"
namespace: {{ distgit_namespace }}
spec:
clusterIP: None
selector:
network.kubevirt.io/headlessService: "{{ distgit_runnerhost_headless_service_name }}"
ports:
# Required by Service; not used for VM connectivity (masquerade handles traffic).
- name: placeholder
port: 15017
targetPort: 15017
protocol: TCP

View file

@ -0,0 +1,12 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: dist-git-runner-config-reader
namespace: dist-git
labels:
app: dist-git-runner
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch"]

View file

@ -0,0 +1,16 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dist-git-runner-config-reader
namespace: dist-git
labels:
app: dist-git-runner
subjects:
- kind: ServiceAccount
name: dist-git-runner-vm
namespace: dist-git
roleRef:
kind: Role
name: dist-git-runner-config-reader
apiGroup: rbac.authorization.k8s.io

View file

@ -0,0 +1,15 @@
---
# Long-lived (non-expiring) ServiceAccount token.
# Unlike projected tokens, this does not expire and does not require
# kubelet-based refresh -- suitable for use inside KubeVirt VMs.
# The token is revoked when this Secret or the ServiceAccount is deleted.
apiVersion: v1
kind: Secret
metadata:
name: dist-git-runner-vm-token
namespace: dist-git
labels:
app: dist-git-runner
annotations:
kubernetes.io/service-account.name: dist-git-runner-vm
type: kubernetes.io/service-account-token

View file

@ -0,0 +1,8 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: dist-git-runner-vm
namespace: dist-git
labels:
app: dist-git-runner

View file

@ -29,12 +29,17 @@ spec:
metadata:
creationTimestamp: null
labels:
network.kubevirt.io/headlessService: headless
network.kubevirt.io/headlessService: "{{ distgit_runnerhost_headless_service_name }}"
spec:
serviceAccountName: dist-git-runner-vm
architecture: amd64
domain:
devices:
autoattachPodInterface: false
disks:
- name: sa-token-disk
disk: {}
serial: SATOKEN000001
interfaces:
- macAddress: "{{ '02:79:58' | community.general.random_mac }}"
masquerade: {}
@ -45,7 +50,7 @@ spec:
networks:
- name: default
pod: {}
subdomain: headless
subdomain: "{{ distgit_runnerhost_headless_service_name }}"
volumes:
- dataVolume:
name: dist-git-runnerhost-vm-volume
@ -57,4 +62,38 @@ spec:
expire: false
password: "{{ (env == 'production') | ternary(distgit_runnerhostvm_password, distgit_stg_runnerhostvm_password) }}"
user: "{{ (env == 'production') | ternary(distgit_runnerhostvm_user, distgit_stg_runnerhostvm_user) }}"
bootcmd:
- "mkdir -p /mnt/sa-token"
- "mount /dev/$(lsblk --nodeps -no name,serial | grep SATOKEN000001 | cut -f1 -d' ') /mnt/sa-token"
{% if distgit_runnerhost_packages | default([]) | length > 0 %}
package_update: true
packages:
{% for pkg in distgit_runnerhost_packages %}
- {{ pkg }}
{% endfor %}
{% endif %}
{% set _vm_user = (env == 'production') | ternary(distgit_runnerhostvm_user, distgit_stg_runnerhostvm_user) %}
write_files:
- path: /home/{{ _vm_user }}/.config/systemd/user/podman.socket.d/chown.conf
owner: "{{ _vm_user }}:{{ _vm_user }}"
defer: true
content: |
[Socket]
ExecStartPost=/usr/bin/podman unshare chown 0:1000 %t/podman/podman.sock
runcmd:
- "chown -R {{ _vm_user }}:{{ _vm_user }} /home/{{ _vm_user }}"
- "loginctl enable-linger {{ _vm_user }}"
- >-
sudo -u {{ _vm_user }} bash -c
'export XDG_RUNTIME_DIR=/run/user/$(id -u)
&& systemctl --user daemon-reload
&& systemctl --user enable --now podman.socket'
- >-
sudo -u {{ _vm_user }} bash -c
'ansible-pull -U https://codeberg.org/fedora/ansible-role-forgejo-runner.git -C main
playbooks/ansible-pull.yml
>> /home/{{ _vm_user }}/ansible-pull.log 2>&1'
name: cloudinitdisk
- name: sa-token-disk
secret:
secretName: dist-git-runner-vm-token

View file

@ -0,0 +1,10 @@
---
apiVersion: v1
kind: Secret
metadata:
# Name/key match ansible-role-forgejo-runner expectations (shared with forgejo).
name: "forgejo-runner-config"
namespace: "dist-git"
data:
forgejo-runners-vars.yaml:
"{{ distgit_runners_config_file | b64encode }}"

View file

@ -1,18 +1,22 @@
---
# Forgejo instance URL
# External URL: https://forge.stg.fedoraproject.org
# Internal URL (accessible from VM): http://forgejo-http.forgejo.svc.cluster.local:3000
# Forgejo instance URL (keys match ansible-role-forgejo-runner expectations).
# Internal URL (accessible from VM): http://dist-git-http.dist-git.svc.cluster.local:3000
forgejo_instance_url: "{{ (env == 'production') | ternary(distgit_runner_instance_url, distgit_stg_runner_instance_url) }}"
# Forgejo runners to register and configure
# Note: Generate secrets with: openssl rand -hex 20
# Runners to register and configure (built by load-dist-git-runners.yaml).
# Non-secret fields live in roles/openshift-apps/dist-git/runners/<env>/*.yml;
# registration secrets live in private vars (distgit_runner_secrets / distgit_stg_runner_secrets).
#
# Runner configuration:
# - name: Unique runner name
# - labels: List of label names (the runner container will automatically add schema:arg based on its environment)
# These are the label names that workflows will use in "runs-on"
# - image: Container image to use for the runner
# The image determines what execution environment and tools are available
# - secret: 40-character hex string for idempotent registration
#
forgejo_runners: {{ (env == 'production') | ternary(distgit_runner_secrets, distgit_stg_runner_secrets) }}
forgejo_runners: {{ distgit_runners }}
# Configuration for the zabbix agent running on the runnerhost
forgejo_runnerhost_zabbix_agent_identity: {{ zabbix_tls_psk_identity }}
forgejo_runnerhost_zabbix_agent_psk: {{ (env == 'production') | ternary(zabbix_tls_prod_psk, zabbix_tls_stg_psk) }}
# Passive checks: allow in-cluster Zabbix proxy (pod source IPs are in OpenShift SDN, not Service ClusterIP).
zabbix_proxy_host: {{ distgit_runnerhost_zabbix_proxy_host | to_json }}
zabbix_agent_server:
{% for entry in distgit_runnerhost_zabbix_agent_server %}
- {{ entry | to_json }}
{% endfor %}
zabbix_agent_server_active: {{ distgit_runnerhost_zabbix_agent_server_active | to_json }}

View file

@ -13,6 +13,9 @@ spec:
- gitea
options: 'SUPERUSER'
postgresVersion: 17
monitoring:
pgmonitor:
exporter: {}
instances:
- name: dist-git-ha
replicas: 2

View file

@ -0,0 +1,22 @@
---
# ClusterIP Service for Crunchy postgres_exporter sidecars (:9187/metrics).
# Scraped by the in-cluster Zabbix proxy (HTTP agent); not exposed via Route.
apiVersion: v1
kind: Service
metadata:
name: {{ distgit_postgres_metrics_service_name }}
namespace: {{ distgit_namespace }}
labels:
app: dist-git
component: postgres-metrics
postgres-operator.crunchydata.com/cluster: {{ distgit_postgres_cluster_name }}
spec:
type: ClusterIP
selector:
postgres-operator.crunchydata.com/cluster: {{ distgit_postgres_cluster_name }}
postgres-operator.crunchydata.com/instance-set: {{ distgit_postgres_cluster_name }}
ports:
- name: metrics
port: {{ distgit_postgres_metrics_port }}
targetPort: {{ distgit_postgres_metrics_port }}
protocol: TCP

View file

@ -7,9 +7,7 @@ metadata:
data:
valkey.conf: |
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
bind 0.0.0.0 -::0
appendonly yes
port 6379
@ -18,112 +16,5 @@ data:
cp /etc/valkey/valkey.conf /tmp/valkey.conf
echo "requirepass ${VALKEY_PASSWORD}" >> /tmp/valkey.conf
echo "masterauth ${VALKEY_PASSWORD}" >> /tmp/valkey.conf
echo "cluster-announce-ip ${POD_IP}" >> /tmp/valkey.conf
cp /tmp/valkey.conf /config/valkey.conf
#mkdir -p /data
#chown -R 1000:1000 /data
init-cluster.sh: |
#!/bin/sh
set -e
# === Wait for local Valkey to be ready ================================
until valkey-cli -h localhost -p 6379 -a "${VALKEY_PASSWORD}" ping >/dev/null 2>&1; do
echo "[$(hostname)] Waiting for local Valkey to start..."
sleep 2
done
echo "[$(hostname)] Local Valkey is ready"
ORDINAL=$(hostname | rev | cut -d'-' -f1 | rev)
TOTAL_NODES=6
PRIMARIES=$(( (TOTAL_NODES + 1) / 2 ))
REPLICAS_PER_PRIMARY=$(( (TOTAL_NODES - PRIMARIES) / PRIMARIES ))
# === Only primary-0 creates the cluster ===============================
if [ "$ORDINAL" -ne 0 ]; then
echo "[$(hostname)] Not primary-0 (ordinal $ORDINAL). Skipping cluster creation."
exit 0
fi
# === Wait for ALL nodes to be reachable ================================
echo "[$(hostname)] Waiting for all $TOTAL_NODES nodes to be reachable..."
for i in $(seq 0 $((TOTAL_NODES - 1))); do
HOST="valkey-${i}.valkey.dist-git.svc.cluster.local"
until valkey-cli -h "$HOST" -p 6379 -a "${VALKEY_PASSWORD}" ping >/dev/null 2>&1; do
echo " → Waiting for $HOST..."
sleep 3
done
echo " ✓ $HOST is reachable"
done
# === Check if cluster is already healthy ===============================
if valkey-cli -a "${VALKEY_PASSWORD}" cluster info 2>/dev/null | grep -q "cluster_known_nodes:$TOTAL_NODES"; then
if valkey-cli -a "${VALKEY_PASSWORD}" cluster info | grep -q "cluster_state:ok"; then
echo "[$(hostname)] Cluster already healthy with $TOTAL_NODES nodes"
exit 0
fi
fi
# === Build node list ===================================================
NODES=""
for i in $(seq 0 $((TOTAL_NODES - 1))); do
HOST="valkey-${i}.valkey.dist-git.svc.cluster.local"
NODES="$NODES $HOST:6379"
done
echo "[$(hostname)] Creating cluster:"
echo " Primaries: $PRIMARIES"
echo " Replicas per primary: $REPLICAS_PER_PRIMARY"
echo " Nodes: $NODES"
# === Retry cluster creation up to 5 times ==============================
for attempt in $(seq 1 5); do
echo "[$(hostname)] Attempt $attempt to create cluster..."
if valkey-cli -a "${VALKEY_PASSWORD}" \
--cluster create $NODES \
--cluster-replicas $REPLICAS_PER_PRIMARY \
--cluster-yes; then
echo "[$(hostname)] Cluster created successfully"
break
else
echo "[$(hostname)] Failed. Retrying in 10s..."
sleep 10
fi
[ $attempt -eq 5 ] && echo "[$(hostname)] All attempts failed" && exit 1
done
# === Final health check ================================================
sleep 5
if valkey-cli -a "${VALKEY_PASSWORD}" cluster info | grep -q "cluster_state:ok"; then
echo "[$(hostname)] CLUSTER IS HEALTHY — ALL 16384 SLOTS COVERED"
else
echo "[$(hostname)] ERROR: Cluster not OK"
valkey-cli -a "${VALKEY_PASSWORD}" cluster nodes
exit 1
fi
# === NON-PRIMARY NODES: Join the cluster ===============================
if [ "$ORDINAL" -ge "$PRIMARIES" ]; then
# Replica N joins primary (N - PRIMARIES)
PRIMARY_IDX=$(( ORDINAL - PRIMARIES ))
PRIMARY_HOST="valkey-${PRIMARY_IDX}.valkey.dist-git.svc.cluster.local"
echo "[$(hostname)] Replica joining primary $PRIMARY_IDX ($PRIMARY_HOST)"
until valkey-cli -h "${PRIMARY_HOST}" -p 6379 -a "${VALKEY_PASSWORD}" ping >/dev/null 2>&1; do
sleep 5
done
valkey-cli -a "${VALKEY_PASSWORD}" \
--cluster add-node "${POD_IP}:6379" "${PRIMARY_HOST}:6379" --cluster-slave
elif [ "$ORDINAL" -gt 0 ] && [ "$ORDINAL" -lt "$PRIMARIES" ]; then
# Additional primary joins via primary-0
echo "[$(hostname)] Primary joining via valkey-0"
until valkey-cli -h valkey-0.valkey.dist-git.svc.cluster.local \
-p 6379 -a "${VALKEY_PASSWORD}" ping >/dev/null 2>&1; do
sleep 5
done
valkey-cli -a "${VALKEY_PASSWORD}" \
--cluster add-node "${POD_IP}:6379" valkey-0.valkey.dist-git.svc.cluster.local:6379
fi

View file

@ -0,0 +1,62 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: valkey-exporter
namespace: {{ distgit_namespace }}
labels:
app: valkey-exporter
component: metrics
spec:
replicas: 1
selector:
matchLabels:
app: valkey-exporter
template:
metadata:
labels:
app: valkey-exporter
component: metrics
spec:
containers:
- name: redis-exporter
image: {{ distgit_valkey_exporter_image }}
imagePullPolicy: IfNotPresent
args:
- --redis.addr={{ distgit_valkey_exporter_redis_addr }}
- --web.listen-address=:{{ distgit_valkey_exporter_port }}
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: valkey-auth
key: password
ports:
- name: metrics
containerPort: {{ distgit_valkey_exporter_port }}
readinessProbe:
httpGet:
path: /health
port: metrics
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /health
port: metrics
initialDelaySeconds: 10
periodSeconds: 20
resources:
requests:
cpu: 10m
memory: 32Mi
limits:
memory: 64Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault

View file

@ -0,0 +1,16 @@
---
apiVersion: v1
kind: Service
metadata:
name: valkey-exporter
namespace: {{ distgit_namespace }}
labels:
app: valkey-exporter
component: metrics
spec:
selector:
app: valkey-exporter
ports:
- name: metrics
port: {{ distgit_valkey_exporter_port }}
targetPort: metrics

View file

@ -11,5 +11,3 @@ spec:
ports:
- name: client
port: 6379
- name: cluster-bus
port: 16379

View file

@ -6,8 +6,7 @@ metadata:
namespace: dist-git
spec:
serviceName: valkey
replicas: 6
podManagementPolicy: Parallel
replicas: 1
selector:
matchLabels:
app: valkey
@ -15,18 +14,14 @@ spec:
metadata:
labels:
app: valkey
annotations:
valkey-config/checksum: "{{ lookup('template', 'valkey-configmap.yaml.j2') | hash('sha256') }}"
spec:
initContainers:
- name: init-config
image: busybox:1.36
command: ["/scripts/init-config.sh"]
env:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: REPLICAS
value: "6"
- name: VALKEY_PASSWORD
valueFrom:
secretKeyRef:
@ -45,22 +40,8 @@ spec:
containers:
- name: valkey
image: valkey/valkey:7.2.5
command: ["/bin/sh", "-c"]
args:
- |
/scripts/init-cluster.sh &
exec valkey-server /config/valkey.conf
command: ["valkey-server", "/config/valkey.conf"]
env:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: REPLICAS
value: "6"
- name: HOSTNAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: VALKEY_PASSWORD
valueFrom:
secretKeyRef:
@ -69,8 +50,6 @@ spec:
ports:
- containerPort: 6379
name: client
- containerPort: 16379
name: cluster-bus
volumeMounts:
- name: data
mountPath: /data
@ -80,7 +59,7 @@ spec:
mountPath: /scripts
readinessProbe:
exec:
command: ["valkey-cli", "-a", "x", "ping"]
command: ["/bin/sh", "-c", "valkey-cli -a \"${VALKEY_PASSWORD}\" ping | grep -q PONG"]
initialDelaySeconds: 5
periodSeconds: 10
volumes:

View file

@ -287,11 +287,13 @@ deployment:
## @param serviceAccount.labels Custom labels for the ServiceAccount
serviceAccount:
create: true
name: 'forgejo-http'
automountServiceAccountToken: false
name: 'dist-git-http'
automountServiceAccountToken: true
imagePullSecrets: []
# - name: private-registry-access
annotations: {}
annotations:
# Absolute URI must match the Host clients use via external proxy,
# not only the OpenShift Route spec.host.
serviceaccounts.openshift.io/oauth-redirecturi.primary: "https://{{ (env == 'production') | ternary(distgit_hostname, distgit_stg_hostname) }}{{ distgit_metrics_oauth_proxy_prefix }}/callback"
labels: {}
## @section Persistence
@ -328,6 +330,35 @@ extraVolumes: []
# secret:
# secretName: gitea-postgres-ssl
## @param extraContainers Additional sidecar containers (oauth-proxy for /metrics)
extraContainers:
- name: oauth-proxy
image: {{ distgit_metrics_oauth_proxy_image }}
ports:
- name: oauth-proxy
containerPort: {{ distgit_metrics_oauth_proxy_port }}
args:
- --http-address=:{{ distgit_metrics_oauth_proxy_port }}
# Disable default :443 listener; edge-terminated Route provides TLS.
- --https-address=
- --provider=openshift
- --openshift-service-account=dist-git-http
- --upstream=http://127.0.0.1:3000/
- --cookie-secret={{ (env == 'production') | ternary(distgit_oauth_proxy_cookie_secret, distgit_stg_oauth_proxy_cookie_secret) | mandatory }}
- --proxy-prefix={{ distgit_metrics_oauth_proxy_prefix }}
- '--bypass-auth-except-for={{ distgit_metrics_oauth_proxy_auth_regex }}'
- --pass-basic-auth=false
# Browser OAuth users (--openshift-sar).
- '--openshift-sar={"namespace":"{{ distgit_namespace }}","resource":"services","resourceName":"{{ distgit_metrics_oauth_proxy_service_name }}","verb":"get"}}'
# Zabbix SA Bearer tokens (see dist-git-metrics-zabbix SA RBAC tasks).
- '--openshift-delegate-urls={"/metrics":{"namespace":"{{ distgit_namespace }}","resource":"services","resourceName":"{{ distgit_metrics_oauth_proxy_service_name }}","verb":"get"}}'
resources:
requests:
cpu: 10m
memory: 32Mi
limits:
memory: 128Mi
## @param extraContainerVolumeMounts Mounts that are only mapped into the Forgejo runtime/main container, to e.g. override custom templates.
extraContainerVolumeMounts: []
@ -401,9 +432,9 @@ gitea:
## @param gitea.metrics.serviceMonitor.enabled Enable Forgejo metrics service monitor
## @param gitea.metrics.serviceMonitor.namespace Namespace in which Prometheus is running
metrics:
enabled: false
enabled: {{ (env == 'production') | ternary(distgit_metrics, distgit_stg_metrics) }}
serviceMonitor:
enabled: false
enabled: {{ (env == 'production') | ternary(distgit_metrics_servicemonitor, distgit_stg_metrics_servicemonitor) }}
namespace: ''
# additionalLabels:
# prometheus-release: prom1
@ -480,7 +511,7 @@ gitea:
# are un-namespaced
## @param gitea.config.APP_NAME Application name, used in the page title
APP_NAME: 'Fedora Forge'
APP_NAME: 'Fedora dist-git'
## @param gitea.config.RUN_MODE Application run mode, affects performance and debugging: `dev` or `prod`
RUN_MODE: prod
@ -588,10 +619,10 @@ gitea:
## @param gitea.config.email.incoming Configuration for handling incoming mail (disabled by default)
email.incoming: {}
## @param gitea.config.cache Cache configuration
## @param gitea.config.cache Cache configuration (standalone Valkey deployed by this role)
cache:
TYPE: redis
CONN_STR: "redis+cluster://:{{ (env == 'production') | ternary(distgit_valkey_password, distgit_stg_valkey_password) }}@valkey-0.distgit.default.svc.cluster.local:6379,valkey-1.distgit.default.svc.cluster.local:6379,valkey-2.distgit.default.svc.cluster.local:6379,valkey-3.distgit.default.svc.cluster.local:6379,valkey-4.distgit.default.svc.cluster.local:6379,valkey-5.distgit.default.svc.cluster.local:6379/0"
ADAPTER: redis
HOST: "redis://:{{ (env == 'production') | ternary(distgit_valkey_password, distgit_stg_valkey_password) }}@valkey-0.valkey.dist-git.svc.cluster.local:6379/0"
## @param gitea.config.session Session/cookie handling
session: {}
@ -673,7 +704,8 @@ gitea:
proxy: {}
## @param gitea.config.actions Configuration for [Forgejo Actions](https://forgejo.org/docs/latest/user/actions/)
actions: {}
actions:
DEFAULT_ACTIONS_URL: "https://{{ (env == 'production') | ternary(distgit_hostname, distgit_stg_hostname) }}"
## @param gitea.config.other Uncategorized configuration options
other: {}
@ -744,109 +776,6 @@ gitea:
successThreshold: 1
failureThreshold: 10
## @section Redis&reg; Cluster
## @descriptionStart
## Redis&reg; Cluster is loaded as a dependency from [Bitnami](https://github.com/bitnami/charts/tree/master/bitnami/redis-cluster) if enabled in the values.
## Full configuration options are available on their website.
## Redis cluster and [Redis](#redis) cannot be enabled at the same time.
## @descriptionEnd
#
## @param redis-cluster.enabled Enable redis cluster
## @param redis-cluster.usePassword Whether to use password authentication
## @param redis-cluster.cluster.nodes Number of redis cluster master nodes
## @param redis-cluster.cluster.replicas Number of redis cluster master node replicas
redis-cluster:
enabled: true
usePassword: false
cluster:
nodes: 3 # default: 6
replicas: 0 # default: 1
## @section Redis&reg;
## @descriptionStart
## Redis&reg; is loaded as a dependency from [Bitnami](https://github.com/bitnami/charts/tree/master/bitnami/redis) if enabled in the values.
## Full configuration options are available on their website.
## Redis and [Redis cluster](#redis-cluster) cannot be enabled at the same time.
## @descriptionEnd
#
## @param redis.enabled Enable redis standalone or replicated
## @param redis.architecture Whether to use standalone or replication
## @param redis.global.redis.password Required password
## @param redis.master.count Number of Redis master instances to deploy
redis:
enabled: false
architecture: standalone
global:
redis:
password: changeme
master:
count: 1
## @section PostgreSQL HA
## @descriptionStart
## PostgreSQL HA is loaded as a dependency from [Bitnami](https://github.com/bitnami/charts/tree/master/bitnami/postgresql-ha) if enabled in the values.
## Full configuration options are available on their website.
## @descriptionEnd
#
## @param postgresql-ha.enabled Enable PostgreSQL HA chart
## @param postgresql-ha.crunchydataOperator Indicate that we are using the crunchydata Operator to deploy PostgreSQL HA
## @param postgresql-ha.postgresql.password Password for the `gitea` user (overrides `auth.password`)
## @param postgresql-ha.global.postgresql.database Name for a custom database to create (overrides `auth.database`)
## @param postgresql-ha.global.postgresql.username Name for a custom user to create (overrides `auth.username`)
## @param postgresql-ha.global.postgresql.password Name for a custom password to create (overrides `auth.password`)
## @param postgresql-ha.postgresql.repmgrPassword Repmgr Password
## @param postgresql-ha.postgresql.postgresPassword postgres Password
## @param postgresql-ha.pgpool.adminPassword pgpool adminPassword
## @param postgresql-ha.service.ports.postgresql PostgreSQL service port (overrides `service.ports.postgresql`)
## @param postgresql-ha.primary.persistence.size PVC Storage Request for PostgreSQL HA volume
postgresql-ha:
global:
postgresql:
database: gitea
password: gitea
username: gitea
enabled: false
crunchydataOperator: true
postgresql:
repmgrPassword: changeme2
postgresPassword: changeme1
password: changeme4
pgpool:
adminPassword: changeme3
service:
ports:
postgresql: 5432
primary:
persistence:
size: 10Gi
## @section PostgreSQL
## @descriptionStart
## PostgreSQL is loaded as a dependency from [Bitnami](https://github.com/bitnami/charts/tree/master/bitnami/postgresql) if enabled in the values.
## Full configuration options are available on their website.
## @descriptionEnd
#
## @param postgresql.enabled Enable PostgreSQL
## @param postgresql.global.postgresql.auth.password Password for the `gitea` user (overrides `auth.password`)
## @param postgresql.global.postgresql.auth.database Name for a custom database to create (overrides `auth.database`)
## @param postgresql.global.postgresql.auth.username Name for a custom user to create (overrides `auth.username`)
## @param postgresql.global.postgresql.service.ports.postgresql PostgreSQL service port (overrides `service.ports.postgresql`)
## @param postgresql.primary.persistence.size PVC Storage Request for PostgreSQL volume
postgresql:
enabled: false
global:
postgresql:
auth:
password: gitea
database: gitea
username: gitea
service:
ports:
postgresql: 5432
primary:
persistence:
size: 10Gi
# By default, removed or moved settings that still remain in a user defined values.yaml will cause Helm to fail running the install/update.
# Set it to false to skip this basic validation check.
## @section Advanced