From c436075c1ba875b5908eb0d420ca0e4f8c889b0a Mon Sep 17 00:00:00 2001 From: kasun Date: Thu, 28 May 2026 02:59:23 +0200 Subject: [PATCH] fix: restore stack config step in workflow, add README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restore Stack Config steps were incorrectly removed in the previous commit — Pulumi.dev.yaml is gitignored so CI cannot access it without decoding it from the PULUMI_DEV_YAML secret at runtime. Also adds README.md documenting the project, stack layout, setup steps, CI/CD secrets, and roadmap. --- .gitea/workflows/deploy-proxmox-infra.yaml | 6 + README.md | 147 +++++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 README.md diff --git a/.gitea/workflows/deploy-proxmox-infra.yaml b/.gitea/workflows/deploy-proxmox-infra.yaml index 951fd37..10b3728 100644 --- a/.gitea/workflows/deploy-proxmox-infra.yaml +++ b/.gitea/workflows/deploy-proxmox-infra.yaml @@ -29,6 +29,9 @@ jobs: with: node-version: '24' + - name: Restore Stack Config + run: echo "${{ secrets.PULUMI_DEV_YAML }}" | base64 -d > proxmox-infra/Pulumi.dev.yaml + - name: Install Dependencies run: npm install working-directory: proxmox-infra @@ -56,6 +59,9 @@ jobs: with: node-version: '24' + - name: Restore Stack Config + run: echo "${{ secrets.PULUMI_DEV_YAML }}" | base64 -d > proxmox-infra/Pulumi.dev.yaml + - name: Install Dependencies run: npm install working-directory: proxmox-infra diff --git a/README.md b/README.md new file mode 100644 index 0000000..4eaf679 --- /dev/null +++ b/README.md @@ -0,0 +1,147 @@ +# Homelab Infrastructure as Code + +A Pulumi-based IaC template for managing a Proxmox homelab. The goal is to replace manual GUI configuration and ad-hoc YAML stacks (LXC, VM, Docker, etc.) with version-controlled, reproducible infrastructure — starting with a highly available k3s cluster across multiple Proxmox nodes. + +This repo is intentionally abstract: credentials are never hardcoded, making it easy to fork and adapt as a template for your own homelab. + +## Why IaC for a homelab? + +- **Reproducibility** — rebuild your entire environment from scratch with a single command +- **Version history** — every change is tracked in git; roll back at any time +- **Auditability** — diff infrastructure changes before applying them (`pulumi preview`) +- **Automation** — CI/CD handles deploys; no manual SSH into nodes +- **Portability** — swap node names, datastores, or credentials without touching logic + +## Repository layout + +``` +. +├── proxmox-infra/ # Pulumi TypeScript stack — VMs & LXC on Proxmox +│ ├── index.ts # All Pulumi resources +│ ├── Pulumi.yaml # Stack project definition +│ └── Pulumi.dev.yaml # Encrypted stack config (gitignored) +├── .gitea/ +│ └── workflows/ +│ └── deploy-proxmox-infra.yaml # Gitea Actions CI/CD pipeline +``` + +## Current stack: `proxmox-infra` + +Provisions a 5-node k3s cluster spread across two Proxmox hosts (`pve` and `pve-bckp`, third bare metal host to be added later for actual parity): + +| VM name | Role | Proxmox node | +| ------------ | ------ | ------------ | +| k3s-master-1 | master | pve | +| k3s-master-2 | master | pve | +| k3s-worker-1 | worker | pve | +| k3s-master-3 | master | pve-bckp | +| k3s-worker-2 | worker | pve-bckp | + +Each node is a full clone of an Ubuntu Noble (24.04) cloud-image template, with cloud-init injecting hostname, user credentials, and SSH key at boot. + +**Tech stack:** + +- [Pulumi](https://www.pulumi.com/) with TypeScript +- [`@muhlba91/pulumi-proxmoxve`](https://github.com/muhlba91/pulumi-provider-proxmoxve) v8.x community provider +- Self-hosted Pulumi state backend (PostgreSQL) +- Gitea Actions for CI/CD + +## Prerequisites + +- [Pulumi CLI](https://www.pulumi.com/docs/install/) installed +- Node.js 18+ and npm +- Access to a Proxmox node with an API token +- A self-hosted Pulumi state backend (PostgreSQL connection string) +- Gitea instance for CI/CD (optional for local use) + +## Getting started + +### 1. Clone and install + +```bash +git clone +cd proxmox-infra +npm install +``` + +### 2. Configure credentials + +All secrets are stored as encrypted Pulumi config values — never in plain environment variables or committed files. + +```bash +# Set Proxmox API credentials +pulumi config set --secret pve1Endpoint https://:8006 +pulumi config set --secret pve1ApiToken @pam!= +pulumi config set --secret pve2Endpoint https://:8006 +pulumi config set --secret pve2ApiToken @pam!= + +# Set VM credentials +pulumi config set --secret k3sVmPassword +pulumi config set --secret sshPvePublicKey "ssh-ed25519 AAAA..." +``` + +Pulumi encrypts these values into `Pulumi.dev.yaml` using your `PULUMI_CONFIG_PASSPHRASE`. + +### 3. Set the state backend + +```bash +export PULUMI_BACKEND_URL=postgresql://:@/ +export PULUMI_CONFIG_PASSPHRASE= +``` + +### 4. Preview and deploy + +```bash +# See what will change before touching anything +pulumi preview + +# Sync Pulumi state with actual Proxmox state (run after any manual GUI changes) +pulumi refresh --yes + +# Deploy +pulumi refresh --yes && pulumi up --yes +``` + +## CI/CD (Gitea Actions) + +The workflow at `.gitea/workflows/deploy-proxmox-infra.yaml` runs automatically: + +| Event | Action | +| --------------------- | ------------------------------ | +| Pull request → `main` | `pulumi preview` (read-only) | +| Push to `main` | `pulumi refresh` + `pulumi up` | +| Manual trigger | `pulumi refresh` + `pulumi up` | + +### Required Gitea secrets + +Configure these under **Settings → Actions → Secrets** in your Gitea repo: + +| Secret | Description | +| -------------------------- | -------------------------------------------------- | +| `PULUMI_BACKEND_URL` | PostgreSQL connection string for the state backend | +| `PULUMI_CONFIG_PASSPHRASE` | Passphrase to decrypt secrets in `Pulumi.dev.yaml` | +| `PULUMI_DEV_YAML` | Base64-encoded content of `Pulumi.dev.yaml` | + +`Pulumi.dev.yaml` is gitignored because it contains your encryption salt. Whenever it changes (e.g. after adding or rotating a secret), re-encode it and paste the output into the Gitea secret: + +```bash +base64 -w 0 proxmox-infra/Pulumi.dev.yaml +``` + +## Adapting this as a template + +1. Fork or copy the repo +2. Update node names (`pve`, `pve-bckp`) and datastore IDs in `index.ts` to match your setup +3. Add or remove VMs from the `nodeConfigs` array +4. Set your own secrets with `pulumi config set --secret` +5. Point the CI/CD workflow at your own Git instance + +## Roadmap + +- LXC container management +- Docker / Compose stack provisioning +- Network and firewall rules +- Automated k3s bootstrapping (kubeconfig export) +- Additional worker nodes and storage volumes +- Migrate secrets management to [OpenBao](https://openbao.org/) — replace `PULUMI_CONFIG_PASSPHRASE` and manual `Pulumi.dev.yaml` encoding with a self-hosted vault +- Add a third bare metal proxmox instance to create an actual 3 node parity.