fix(opentofu): remove retired Gitea/Woodpecker LXC state drift (Fixes #199) #232

Merged
k.renner merged 1 commits from fix/issue-199-tofu-state-drift into master 2026-07-14 17:41:09 +00:00
8 changed files with 0 additions and 237 deletions
-43
View File
@@ -1,43 +0,0 @@
when:
# Deploy only on master (merge) + manual — never from a feature branch.
- event: push
branch: master
path:
- "ansible/roles/woodpecker-agent/**"
- "ansible/plays/install-woodpecker-agent.yml"
- ".woodpecker/deploy-woodpecker-agent.yml"
- event: manual
evaluate: 'PIPELINE == "deploy-woodpecker-agent"'
# NOTE: this deploys the agents *from* an agent, so applying a change that
# restarts Docker (e.g. the daemon.json IPv6 config) will kill this job's own
# container mid-run — the pipeline reports failure, but the change still
# applies on both agents (the restart commands are dispatched in parallel
# before the executing agent's daemon goes down). Re-run / re-trigger
# deploy-netbird-proxy afterwards.
timeout: 30
steps:
- name: deploy-woodpecker-agent
image: gitea.renner.uno/gitea_admin/ci-ansible:2026-04-29
environment:
ANSIBLE_FORCE_COLOR: "true"
ANSIBLE_HOST_KEY_CHECKING: "false"
ANSIBLE_ROLES_PATH: "../roles:./roles"
SSH_PRIVATE_KEY:
from_secret: ssh_private_key
VAULT_PASS:
from_secret: vault_pass
PROXMOX_TOKEN_ID:
from_secret: proxmox_token_id
PROXMOX_TOKEN_SECRET:
from_secret: proxmox_token_secret
commands:
- mkdir -p ~/.ssh
- echo "$SSH_PRIVATE_KEY" | base64 -d > ~/.ssh/id_ed25519
- chmod 600 ~/.ssh/id_ed25519
- printf "Host *\n\tStrictHostKeyChecking no\n\tUserKnownHostsFile /dev/null\n" > ~/.ssh/config
- cd ansible
- echo "$VAULT_PASS" > .vault_pass && chmod 600 .vault_pass
- export ANSIBLE_VAULT_PASSWORD_FILE=.vault_pass
- ansible-playbook -i inventory/ plays/install-woodpecker-agent.yml -v
-28
View File
@@ -1,28 +0,0 @@
when:
- event: manual
evaluate: 'PIPELINE == "install-woodpecker-server"'
steps:
- name: run-playbook
image: gitea.renner.uno/gitea_admin/ci-ansible:2026-04-29
environment:
ANSIBLE_FORCE_COLOR: "true"
ANSIBLE_HOST_KEY_CHECKING: "false"
ANSIBLE_ROLES_PATH: "../roles:./roles"
SSH_PRIVATE_KEY:
from_secret: ssh_private_key
VAULT_PASS:
from_secret: vault_pass
PROXMOX_TOKEN_ID:
from_secret: proxmox_token_id
PROXMOX_TOKEN_SECRET:
from_secret: proxmox_token_secret
commands:
- mkdir -p ~/.ssh
- echo "$SSH_PRIVATE_KEY" | base64 -d > ~/.ssh/id_ed25519
- chmod 600 ~/.ssh/id_ed25519
- 'printf "Host *\n\tStrictHostKeyChecking no\n\tUserKnownHostsFile /dev/null\n" > ~/.ssh/config'
- cd ansible
- echo "$$VAULT_PASS" > .vault_pass && chmod 600 .vault_pass
- export ANSIBLE_VAULT_PASSWORD_FILE=.vault_pass
- ansible-playbook -i inventory/ plays/install-woodpecker-server.yml -v
-4
View File
@@ -24,14 +24,10 @@ locals {
],
# LXCs
[
"114", # gitea
"118", # proxmox-dns-1 (jupiter)
"218", # proxmox-dns-2 (saturn)
"231", # woodpecker
"318", # proxmox-dns-3 (neptune)
],
# Woodpecker CI agents (VMIDs 910..)
[for a in local.woodpecker_agents : tostring(a.vmid)],
)
}
-18
View File
@@ -6,22 +6,4 @@ locals {
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBB1OFjh6Q5xeioI6Cwfuv8Xka27veomYy9tKBbpMo8mcrsB4yIN4FX8HovBLtogetBhwBUefBar8nhA9GbRh6HQ= krenner@krenner-XPS-13-9310"
])
woodpecker_agents = [
for i in range(var.woodpecker_agent_count) : {
vmid = 910 + i
name = "wp-agent-${i + 1}.srv.renner.uno"
node = "jupiter"
memory = 4096
cores = 2
type = "lxc"
state = "started"
tags = "woodpecker;ci;docker"
bridge = "v40srv"
disk_size = "30G"
storage = "local-zfs"
nesting = true
ostemplate = "local:vztmpl/debian-12-standard_12.12-1_amd64.tar.zst"
}
]
}
-44
View File
@@ -1,44 +0,0 @@
moved {
from = proxmox_lxc.lxc["114"]
to = proxmox_lxc.gitea_srv_renner_uno
}
module "gitea_srv_renner_uno" {
source = "./modules/proxmox_lxc"
target_node = "jupiter"
hostname = "gitea.srv.renner.uno"
vmid = 114
memory = 2048
cores = 2
cpuunits = 1024
tags = "community-script;git"
hagroup = "olymp"
hastate = "started"
unprivileged = false
onboot = true
start = true
storage = "local-zfs"
# Bumped 4G→16G on 2026-05-01: container registry blob storage filled
# the rootfs and gitea returned 500 on every blob upload during
# build-ci-images runs (pipeline 841 — three of four image pushes
# failed with "no space left on device" on /var/lib/alloy too).
disk_size = "16G"
# ingress_cnames removed: gitea is now fronted by ingress-nginx via
# the ExternalName Service in kubernetes/apps/gitea/. Removing the
# CNAMEs to ingress.renner.uno (Caddy VIP) lets external-dns-unifi
# take ownership of git/gitea.renner.uno and write A records to the
# ingress-nginx LB at 10.2.40.80.
ingress_cnames = []
}
moved {
from = proxmox_lxc.gitea_srv_renner_uno
to = module.gitea_srv_renner_uno.proxmox_lxc.this
}
-58
View File
@@ -1,58 +0,0 @@
# Woodpecker CI Server
# Lightweight CI/CD engine with Gitea integration
# Replaces Gitea Actions for better UI and worker management
module "woodpecker_srv_renner_uno" {
source = "./modules/proxmox_lxc"
hostname = "woodpecker.srv.renner.uno"
vmid = 231
target_node = "jupiter"
# 1 GiB was insufficient under concurrent pipeline load — SQLite mmap
# contention caused "database is locked" cascades that killed otherwise-
# healthy long-running steps with `queue: task expired` and
# `sql: no rows in result set`.
memory = 4096
cores = 2
unprivileged = true
network_bridge = "v40srv"
storage = "local-zfs"
disk_size = "10G"
ostemplate = "local:vztmpl/debian-12-standard_12.12-1_amd64.tar.zst"
ssh_public_keys = local.common_ssh_keys
tags = "ci;docker;woodpecker"
onboot = true
start = true
features = {
nesting = true
fuse = false
keyctl = false
mknod = false
}
# ingress_cnames removed: woodpecker UI is now fronted by ingress-nginx
# via the ExternalName Service in kubernetes/apps/woodpecker/. Agents
# talk to woodpecker.srv.renner.uno:9000 directly, so the gRPC path
# was never on Caddy.
ingress_cnames = []
cnames = []
description = <<-EOT
Woodpecker CI Server
https://woodpecker-ci.org/
Deployed via Ansible role: woodpecker-server
Web UI: https://ci.renner.uno (port 8000)
gRPC: port 9000 (agent communication)
Auth: Gitea OAuth2
Database: SQLite
EOT
}
-6
View File
@@ -28,12 +28,6 @@ variable "proxmox_tls_insecure" {
default = false
}
variable "woodpecker_agent_count" {
description = "Number of Woodpecker CI agents to deploy"
type = number
default = 2
}
variable "ssh_public_key" {
description = "Public SSH key to inject into containers"
type = string
-36
View File
@@ -1,36 +0,0 @@
# Woodpecker CI Agents
# Docker-based build agents connecting to woodpecker.srv.renner.uno via gRPC
module "woodpecker_agents" {
source = "./modules/proxmox_lxc"
for_each = {
for lxc in local.woodpecker_agents : lxc.vmid => lxc
}
hostname = each.value.name
target_node = each.value.node
vmid = each.value.vmid
memory = each.value.memory
cores = each.value.cores
unprivileged = true
tags = join(",", compact([each.value.tags, "transient"]))
ostemplate = each.value.ostemplate
storage = each.value.storage != "" ? each.value.storage : "local-zfs"
disk_size = each.value.disk_size
ssh_public_keys = local.common_ssh_keys
start = each.value.state == "started" ? true : false
network_bridge = each.value.bridge
# CI steps must reach IPv6-only hosts; give the LXC SLAAC v6 off v40srv so
# Docker has a v6 uplink to NAT the pipeline networks onto.
ipv6_address = "auto"
features = {
nesting = each.value.nesting
fuse = false
keyctl = false
mknod = false
}
}