From 8fbecaa8643d9087d3f9561c02f9afb6efa921be Mon Sep 17 00:00:00 2001 From: Tibo De Peuter Date: Fri, 17 Jul 2026 23:01:44 +0200 Subject: [PATCH] refactor(security): move staging age key from forgejo secrets to proxmox snippet --- .forgejo/workflows/staging.yml | 2 -- BOOTSTRAP.md | 21 ++++++++++++++++++++- terraform/staging-env/main.tf | 29 ++--------------------------- 3 files changed, 22 insertions(+), 30 deletions(-) diff --git a/.forgejo/workflows/staging.yml b/.forgejo/workflows/staging.yml index 691866f..9ab3470 100644 --- a/.forgejo/workflows/staging.yml +++ b/.forgejo/workflows/staging.yml @@ -38,7 +38,6 @@ jobs: TF_VAR_pr_number: ${{ github.event.pull_request.number }} # VM_ID could be dynamically generated or based on PR number (e.g., 8000 + PR_NUMBER) TF_VAR_vm_id: ${{ format('8{0:03}', github.event.pull_request.number) }} - TF_VAR_staging_age_key: ${{ secrets.STAGING_AGE_KEY }} # TrueNAS integration (Secrets would need to be added to Forgejo) TRUENAS_IP: "truenas.local" @@ -61,7 +60,6 @@ jobs: PROXMOX_VE_API_TOKEN: ${{ secrets.PROXMOX_TOKEN_SECRET }} TF_VAR_pr_number: ${{ github.event.pull_request.number }} TF_VAR_vm_id: ${{ format('8{0:03}', github.event.pull_request.number) }} - TF_VAR_staging_age_key: "" # TrueNAS integration TRUENAS_IP: "truenas.local" diff --git a/BOOTSTRAP.md b/BOOTSTRAP.md index 836bafc..2cd99aa 100644 --- a/BOOTSTRAP.md +++ b/BOOTSTRAP.md @@ -45,8 +45,27 @@ The CI/CD actions require access to the Proxmox token and the staging secret key 2. Go to **Settings > Actions > Secrets** for this repository. 3. Add the following repository secrets: * `PROXMOX_TOKEN_SECRET`: Paste the token generated from Step 2. - * `STAGING_AGE_KEY`: Paste the *entire contents* of your `staging-master.txt` file (the private key). * `RENOVATE_TOKEN`: Create a Personal Access Token (PAT) for your user in Forgejo with read/write access to code and pull requests, and paste it here. +## 4. Staging Golden Key Provisioning (Proxmox Snippet) + +Instead of relying on Forgejo CI/CD to store the staging private key, we use a secure hypervisor-level Cloud-Init snippet. + +1. SSH into your Proxmox server (`pve`). +2. Create the Cloud-Init snippet file: + ```bash + cat << 'EOF' > /var/lib/vz/snippets/staging-key.yaml + #cloud-config + write_files: + - path: /var/lib/sops-nix/key.txt + permissions: '0600' + content: | + AGE-SECRET-KEY-1... (paste your staging-master private key here) + runcmd: + - echo "Staging age key injected successfully." + EOF + ``` +3. This completely removes the secret from Forgejo. When Terraform spins up a staging VM, it simply tells Proxmox to attach this local snippet! + ## Next Steps Once these bootstrap steps are complete, the foundational authentication is in place. The Forgejo CI actions will now have the necessary permissions to build images, provision VMs, and test staging environments autonomously. diff --git a/terraform/staging-env/main.tf b/terraform/staging-env/main.tf index 08ff226..b77ee4a 100644 --- a/terraform/staging-env/main.tf +++ b/terraform/staging-env/main.tf @@ -17,12 +17,6 @@ variable "pr_number" { type = string } -variable "staging_age_key" { - description = "The private age key for decrypting staging secrets. Injected via Cloud-Init." - type = string - sensitive = true -} - provider "proxmox" { # Relies on PROXMOX_VE_ENDPOINT and PROXMOX_VE_API_TOKEN environment variables } @@ -58,37 +52,18 @@ resource "proxmox_virtual_environment_vm" "staging_vm" { # Cloud-Init configuration to inject the staging age key and set up networking - initialization { + initialization { ip_config { ipv4 { address = "dhcp" } } - user_data_file_id = proxmox_virtual_environment_file.cloud_config.id + user_data_file_id = "local:snippets/staging-key.yaml" } } -resource "proxmox_virtual_environment_file" "cloud_config" { - content_type = "snippets" - datastore_id = "local-zfs" - node_name = "pve" - source_raw { - data = <<-EOF - #cloud-config - write_files: - - path: /var/lib/sops-nix/key.txt - permissions: '0600' - content: | - ${indent(10, var.staging_age_key)} - runcmd: - - echo "Staging age key injected successfully." - EOF - - file_name = "staging-pr-${var.pr_number}-cloud-init.yaml" - } -} resource "proxmox_virtual_environment_firewall_options" "staging_vm_fw_options" { vm_id = proxmox_virtual_environment_vm.staging_vm.vm_id