feat(infra): auto-generate Gitea admin password and runner token

- Replace var.gitea_admin_password with random_password (like Grafana)
- Replace var.gitea_runner_token with terraform_data bootstrapper that
  calls the Gitea admin API after first deploy and patches the secret
- Empty variables.tf — no manual secrets needed on terraform apply

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Gonçalo Rodrigues 2026-06-20 15:43:10 +01:00
parent dee8b5b40a
commit 07c2dc3ecb
3 changed files with 63 additions and 30 deletions

View File

@ -44,20 +44,6 @@ resource "kubernetes_cluster_role_binding" "act_runner" {
} }
} }
# Populated after initial Gitea deploy:
# 1. Open http://git.homelab.local Admin Area Runners Create Runner
# 2. Copy the token
# 3. terraform apply -var gitea_runner_token=<token>
resource "kubernetes_secret" "gitea_runner_token" {
metadata {
name = "gitea-runner-token"
namespace = kubernetes_namespace.domains["gitea"].metadata[0].name
}
data = {
token = var.gitea_runner_token
}
}
# ConfigMap for act runner config (host executor mode steps run directly in runner container) # ConfigMap for act runner config (host executor mode steps run directly in runner container)
resource "kubernetes_config_map" "act_runner" { resource "kubernetes_config_map" "act_runner" {
metadata { metadata {

View File

@ -1,3 +1,8 @@
resource "random_password" "gitea_admin" {
length = 24
special = false
}
resource "kubernetes_secret" "gitea_admin" { resource "kubernetes_secret" "gitea_admin" {
metadata { metadata {
name = "gitea-admin" name = "gitea-admin"
@ -5,7 +10,7 @@ resource "kubernetes_secret" "gitea_admin" {
} }
data = { data = {
username = "admin" username = "admin"
password = var.gitea_admin_password password = random_password.gitea_admin.result
email = "admin@homelab.local" email = "admin@homelab.local"
} }
} }
@ -81,6 +86,58 @@ resource "helm_release" "gitea" {
})] })]
} }
# Placeholder secret created by Terraform; data is populated by the
# terraform_data bootstrapper below after Gitea is reachable.
resource "kubernetes_secret" "gitea_runner_token" {
metadata {
name = "gitea-runner-token"
namespace = kubernetes_namespace.domains["gitea"].metadata[0].name
}
data = { token = "" }
lifecycle {
# After the bootstrapper writes the real token we must not overwrite it
# with the empty placeholder on subsequent applies.
ignore_changes = [data]
}
}
# On first apply: poll until Gitea is up, call the admin API to obtain a
# runner registration token, and patch the secret in place.
# On subsequent applies this resource is a no-op (terraform_data only
# re-runs its provisioner when triggers_replace changes).
resource "terraform_data" "gitea_runner_registration" {
depends_on = [helm_release.gitea, kubernetes_secret.gitea_runner_token]
# Re-bootstrap only if the admin password rotates.
triggers_replace = [random_password.gitea_admin.id]
provisioner "local-exec" {
interpreter = ["/bin/sh", "-c"]
command = <<-EOT
set -e
echo "Waiting for Gitea to be ready..."
until curl -sf "http://git.homelab.local/api/v1/version" > /dev/null 2>&1; do
sleep 5
done
PASSWORD=$(kubectl get secret gitea-admin -n gitea \
-o jsonpath='{.data.password}' | base64 -d)
TOKEN=$(curl -sf -X POST \
-u "admin:$PASSWORD" \
"http://git.homelab.local/api/v1/admin/runners/registration-token" \
| grep -o '"token":"[^"]*"' | cut -d'"' -f4)
kubectl patch secret gitea-runner-token -n gitea \
-p "{\"data\":{\"token\":\"$(printf '%s' "$TOKEN" | base64)\"}}"
echo "Runner registration token written to gitea-runner-token secret."
EOT
}
}
# imagePullSecret for finance namespace allows k8s to pull images from Gitea registry. # imagePullSecret for finance namespace allows k8s to pull images from Gitea registry.
# Containerd mirrors "git.homelab.local" to localhost:30002 (see k3d/config.yaml) and # Containerd mirrors "git.homelab.local" to localhost:30002 (see k3d/config.yaml) and
# forwards these credentials to authenticate against the Gitea NodePort. # forwards these credentials to authenticate against the Gitea NodePort.
@ -94,7 +151,7 @@ resource "kubernetes_secret" "gitea_registry_finance" {
".dockerconfigjson" = jsonencode({ ".dockerconfigjson" = jsonencode({
auths = { auths = {
"git.homelab.local" = { "git.homelab.local" = {
auth = base64encode("admin:${var.gitea_admin_password}") auth = base64encode("admin:${random_password.gitea_admin.result}")
} }
} }
}) })

View File

@ -1,13 +1,3 @@
variable "gitea_admin_password" { # No manual secrets required passwords are generated by random_password resources
description = "Gitea admin password — set TF_VAR_gitea_admin_password or override in terraform.tfvars" # and stored in Terraform state. Runner token is fetched from the Gitea API
type = string # automatically after the first deploy.
default = "gitea-dev-changeme"
sensitive = true
}
variable "gitea_runner_token" {
description = "Gitea runner registration token — obtain from Gitea UI: Admin Area → Runners → Create Runner, then set TF_VAR_gitea_runner_token"
type = string
default = ""
sensitive = true
}