diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml
new file mode 100644
index 0000000..e4c5d73
--- /dev/null
+++ b/.forgejo/workflows/release.yml
@@ -0,0 +1,54 @@
+name: Build and Release
+on: [push]
+
+jobs:
+ build-sign-package:
+ runs-on: ubuntu-latest
+ container: archlinux:latest
+ steps:
+ - name: Install Tools
+ run: pacman -Syu --noconfirm mingw-w64-gcc nsis osslsigncode opentofu ansible python-pywinrm packer
+
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Cross-Compile (MinGW)
+ run: x86_64-w64-mingw32-gcc src/main.c -o dist/app.exe
+
+ - name: Package (NSIS)
+ run: makensis -DVERSION=${{ gitea.ref_name }} installer.nsi
+
+ - name: Code Sign (Linux Native)
+ env:
+ PFX_PASS: ${{ secrets.PFX_PASS }}
+ run: |
+ osslsigncode sign -pkcs12 cert.pfx -pass "$PFX_PASS" \
+ -t http://timestamp.digicert.com \
+ -in dist/installer.exe -out dist/installer_signed.exe
+
+ - name: Provision Windows VM (OpenTofu)
+ env:
+ PM_API_TOKEN_ID: ${{ secrets.PM_TOKEN_ID }}
+ PM_API_TOKEN_SECRET: ${{ secrets.PM_TOKEN_SECRET }}
+ TF_VAR_build_id: ${{ gitea.run_number }}
+ run: |
+ cd terraform
+ tofu init
+ tofu apply -auto-approve
+ echo "VM_IP=$(tofu output -raw vm_ip)" >> $GITHUB_ENV
+
+ - name: Verify on Windows (Ansible)
+ env:
+ ANSIBLE_USER: Administrator
+ ANSIBLE_PASSWORD: ${{ secrets.WIN_ADMIN_PASS }}
+ run: |
+ echo "[windows_vm]" > inventory.ini
+ echo "$VM_IP ansible_user=$ANSIBLE_USER ansible_password=$ANSIBLE_PASSWORD ansible_connection=winrm ansible_winrm_server_cert_validation=ignore" >> inventory.ini
+
+ ansible-playbook -i inventory.ini ansible/pipeline.yml
+
+ - name: Cleanup
+ if: always()
+ run: |
+ cd terraform
+ tofu destroy -auto-approve
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0ff17f2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,40 @@
+# Packer
+*.pkr.hcl.pkr.hcl
+
+# Terraform
+*.tfstate
+*.tfstate.*
+.terraform/
+.terraform.lock.hcl
+crash.log
+override.tf
+override.tf.json
+*.tfplan
+
+# Ansible
+*.retry
+inventory.ini
+
+# Forgejo
+*.pfx
+
+# Build artifacts
+dist/
+*.exe
+*.msi
+*.dll
+*.o
+
+# OS
+.DS_Store
+Thumbs.db
+
+# IDE
+.vscode/
+.idea/
+*.swp
+*.swo
+*~
+
+# Logs
+*.log
diff --git a/README.md b/README.md
index ef36bc9..6acf542 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,355 @@
-# windows-iac-vm-tooling
+# ๐ฅ๏ธ Windows Automation on Proxmox
-This repo contains scripts and docs on how to create a golden image and then also how to use IaC tooling (OpenTofu, Ansibla and Jinja) to deploy windows build and test machines.
\ No newline at end of file
+
+[](LICENSE)
+[](.forgejo/workflows/release.yml)
+[](https://www.microsoft.com/en-us/windows/windows-11-enterprise)
+
+## ๐ Table of Contents
+
+1. [Overview](#-overview)
+2. [Architecture](#-architecture)
+3. [Quick Start](#-quick-start)
+4. [Project Structure](#-project-structure)
+5. [Documentation Index](#-documentation-index)
+6. [Prerequisites](#-prerequisites)
+7. [Pipeline Phases](#-pipeline-phases)
+8. [Advanced Topics](#-advanced-topics)
+9. [Contributing](#-contributing)
+
+---
+
+## ๐ Overview
+
+This repository contains a complete **automated build, package, and test pipeline** for Windows applications using infrastructure as code. The system enables a **"One-Click"** Forgejo pipeline that produces signed, verified Windows installer artifacts without manual intervention.
+
+### Key Features
+
+- **๐ง Automated Golden Image Creation** - Packer builds reproducible Windows templates
+- **โ๏ธ Ephemeral Infrastructure** - OpenTofu provisions temporary Windows VMs for testing
+- **๐ Code Signing** - Linux-native code signing with timestamp verification
+- **โ
Automated Testing** - Ansible verifies installations on live Windows VMs
+- **๐ Cross-Platform Compilation** - MinGW cross-compilation for Windows on Linux
+
+---
+
+## ๐๏ธ Architecture
+
+```mermaid
+flowchart TB
+ subgraph CI["Forgejo CI/CD"]
+ direction LR
+ C[Checkout] --> X[Cross-Compile
MinGW] --> P[Package
NSIS] --> S[Sign
osslsigncode]
+ end
+
+ subgraph Build["Build Phase"]
+ P --> B[Packer Build
Windows Template]
+ B --> T[OpenTofu Provision
Windows VM]
+ end
+
+ subgraph Verify["Verification Phase"]
+ S --> A[Ansible Test
Smoke Test]
+ T --> A
+ end
+
+ subgraph Artifacts["Output"]
+ A --> EXE[ installer_signed.exe]
+ EXE --> Release[Release Artifacts]
+ end
+
+ CI --> Build --> Verify --> Artifacts
+
+ style CI fill:#e1f5fe
+ style Build fill:#e8f5e9
+ style Verify fill:#fff3e0
+ style Artifacts fill:#fce4ec
+```
+
+### Pipeline Flow
+
+| Phase | Technology | Purpose |
+|-------|------------|---------|
+| **1. Build** | Packer | Create Windows golden image template |
+| **2. Provision** | OpenTofu | Spin up ephemeral Windows test VMs |
+| **3. Compile** | MinGW | Cross-compile Windows applications on Linux |
+| **4. Package** | NSIS | Create Windows installer packages |
+| **5. Sign** | osslsigncode | Code-sign binaries with timestamp |
+| **6. Verify** | Ansible | Test installation on live Windows VM |
+
+---
+
+## โก Quick Start
+
+### Prerequisites
+
+Before beginning, ensure ISOs are available on Proxmox:
+
+```bash
+# ISO Storage Location
+/mnt/pve-07-iso-nvme/template/iso/
+```
+
+**Required Files:**
+- `CLIENT_LTSC_EVAL_x64FRE_en-us.iso` - Windows 11 LTSC 2024
+- `virtio-win.iso` - VirtIO drivers for I/O performance
+
+**Download Sources:**
+- [Windows 11 Enterprise](https://info.microsoft.com/ww-landing-windows-11-enterprise.html)
+- [VirtIO Drivers](https://github.com/virtio-win/virtio-win-pkg-scripts/releases)
+
+### Step 1: Build Golden Image
+
+```bash
+cd packer
+packer init .
+packer build windows.pkr.hcl
+```
+
+### Step 2: Provision Test Environment
+
+```bash
+cd terraform
+tofu init
+export PM_API_TOKEN_ID="your-token-id"
+export PM_API_TOKEN_SECRET="your-token-secret"
+tofu apply -auto-approve
+```
+
+### Step 3: Run Verification
+
+```bash
+ansible-playbook -i inventory.ini ../ansible/pipeline.yml
+```
+
+---
+
+## ๐ Project Structure
+
+```
+windows-iac-vm-tooling/
+โโโ ๐ README.md # โ Entry point (this file)
+โโโ ๐ doc.tex # Full LaTeX documentation
+โโโ ๐ LICENSE # MIT License
+โโโ ๐ installer.nsi # NSIS installer script
+โโโ ๐ .forgejo/
+โ โโโ ๐ workflows/
+โ โโโ ๐ release.yml # Forgejo CI/CD pipeline
+โโโ ๐ ansible/
+โ โโโ ๐ pipeline.yml # Ansible verification playbook
+โโโ ๐ docs/ # Hierarchical documentation
+โ โโโ ๐ index.md # Documentation index
+โ โโโ ๐ 01-overview/
+โ โ โโโ ๐ architecture.md # Detailed architecture
+โ โโโ ๐ 02-prerequisites/
+โ โ โโโ ๐ isos.md # ISO requirements
+โ โ โโโ ๐ secrets.md # Secret management
+โ โโโ ๐ 03-packer/
+โ โ โโโ ๐ configuration.md # Packer HCL config
+โ โ โโโ ๐ autounattend.md # Windows answer file
+โ โโโ ๐ 04-terraform/
+โ โ โโโ ๐ main.tf.md # OpenTofu resources
+โ โ โโโ ๐ variables.md # Terraform variables
+โ โโโ ๐ 05-ansible/
+โ โ โโโ ๐ pipeline.md # Ansible playbook guide
+โ โโโ ๐ 06-ci-cd/
+โ โ โโโ ๐ forgejo-workflows.md # CI/CD pipeline details
+โ โโโ ๐ 07-advanced/
+โ โโโ ๐ evaluation.md # 90-day evaluation management
+โ โโโ ๐ troubleshooting.md # Common issues & solutions
+โโโ ๐ packer/
+โ โโโ ๐ windows.pkr.hcl # Packer template configuration
+โ โโโ ๐ Autounattend.xml # Windows unattended installation
+โโโ ๐ src/
+โ โโโ ๐ main.c # Example Windows application
+โโโ ๐ terraform/
+ โโโ ๐ main.tf # OpenTofu main configuration
+ โโโ ๐ variables.tf # Input variables
+ โโโ ๐ outputs.tf # Output values
+```
+
+---
+
+## ๐ Documentation Index
+
+### Getting Started
+- **[Documentation Index](docs/index.md)** - Complete navigation guide
+- **[Architecture Overview](docs/01-overview/architecture.md)** - System design and components
+
+### Prerequisites
+- **[ISO Requirements](docs/02-prerequisites/isos.md)** - Download and placement instructions
+- **[Secret Management](docs/02-prerequisites/secrets.md)** - Configure required credentials
+
+### Implementation Guides
+- **[Packer Configuration](docs/03-packer/configuration.md)** - Build Windows templates
+- **[Autounattend.xml Guide](docs/03-packer/autounattend.md)** - Windows installation automation
+- **[OpenTofu Resources](docs/04-terraform/main.tf.md)** - Infrastructure as code
+- **[Ansible Pipeline](docs/05-ansible/pipeline.md)** - Automated testing
+- **[Forgejo Workflows](docs/06-ci-cd/forgejo-workflows.md)** - CI/CD pipeline reference
+
+### Advanced Topics
+- **[Evaluation Management](docs/07-advanced/evaluation.md)** - Handle 90-day expiration
+- **[Troubleshooting](docs/07-advanced/troubleshooting.md)** - Debug common issues
+
+---
+
+## ๐ Prerequisites
+
+### Required ISO Images on Proxmox Storage
+
+**Storage Location:** `/mnt/pve-07-iso-nvme/template/iso/`
+
+| File | Description | Required |
+|------|-------------|----------|
+| `CLIENT_LTSC_EVAL_x64FRE_en-us.iso` | Windows 11 LTSC 2024 | โ
Yes |
+| `virtio-win.iso` | VirtIO drivers | โ
Yes |
+| `SERVER_EVAL_x64FRE_en-us.iso` | Windows Server 2022 | Optional |
+| `26100.1742.240906-0331...iso` | Alternate Windows 11 | Optional |
+
+### Required Secrets
+
+Configure these in your Forgejo repository settings:
+
+| Secret | Description | Usage |
+|--------|-------------|-------|
+| `PFX_PASS` | Code signing certificate password | `osslsigncode sign` |
+| `PM_TOKEN_ID` | Proxmox API token ID | `tofu apply` |
+| `PM_TOKEN_SECRET` | Proxmox API token secret | `tofu apply` |
+| `WIN_ADMIN_PASS` | Windows Administrator password | Ansible connection |
+
+---
+
+## ๐ Pipeline Phases
+
+### Phase 1: Automated Image Build (Packer)
+
+```mermaid
+flowchart LR
+ subgraph Packer["Packer Process"]
+ ISO[Mount ISO] --> VM[Create VM] --> Install[Windows Install] --> Drivers[Install VirtIO] --> Template[Convert to Template]
+ end
+
+ Packer --> Output[Windows Golden Image]
+
+ style Packer fill:#e3f2fd
+ style Output fill:#c8e6c9
+```
+
+**Related Documentation:**
+- [Packer Configuration](docs/03-packer/configuration.md)
+- [Autounattend.xml Guide](docs/03-packer/autounattend.md)
+
+### Phase 2: Infrastructure as Code (OpenTofu)
+
+```mermaid
+flowchart TB
+ subgraph OpenTofu["OpenTofu Workflow"]
+ Init[tofu init] --> Plan[tofu plan] --> Apply[tofu apply] --> VM[Provision VM] --> Test[Test] --> Destroy[tofu destroy]
+ end
+
+ Input[Template VM ID] --> VM
+ Output[VM IP Address] --> Test
+
+ style OpenTofu fill:#f3e5f5
+ style Input fill:#fff3e0
+ style Output fill:#e8f5e9
+```
+
+**Related Documentation:**
+- [OpenTofu Resources](docs/04-terraform/main.tf.md)
+- [Terraform Variables](docs/04-terraform/variables.md)
+
+### Phase 3: Cross-Compile & Package (Linux)
+
+```mermaid
+flowchart LR
+ subgraph Linux["Linux Build Container"]
+ Src[Source Code] --> Compile[MinGW GCC] --> Binary[app.exe] --> Package[NSIS] --> Installer[installer.exe]
+ end
+
+ Compile --> Sign[osslsigncode] --> Signed[installer_signed.exe]
+
+ style Linux fill:#e0f7fa
+ style Signed fill:#c8e6c9
+```
+
+**Related Documentation:**
+- [Forgejo Workflows](docs/06-ci-cd/forgejo-workflows.md)
+
+### Phase 4: Verification (Ansible)
+
+```mermaid
+flowchart TB
+ subgraph Ansible["Ansible Verification"]
+ Upload[Upload Installer] --> Install[Silent Install] --> Verify[Check Installation] --> Assert[Pass/Fail]
+ end
+
+ VM[Windows VM] --> Upload
+ Assert --> Report[Test Report]
+
+ style Ansible fill:#fff8e1
+ style Report fill:#e8f5e9
+```
+
+**Related Documentation:**
+- [Ansible Pipeline](docs/05-ansible/pipeline.md)
+
+---
+
+## ๐ง Advanced Topics
+
+### Managing the 90-Day Evaluation
+
+Windows Evaluation ISO expires after 90 days. Two management strategies:
+
+| Method | Command | Limit |
+|--------|---------|-------|
+| **Rearm** | `slmgr /rearm` | 3 times |
+| **Rebuild** | Monthly Packer build | Unlimited |
+
+**Recommended Approach:**
+Schedule a monthly Packer build in Forgejo to regenerate the Golden Template, ensuring:
+- Fresh 90-day timer
+- Latest security updates
+- Consistent baseline
+
+### Troubleshooting
+
+**Common Issues:**
+
+| Issue | Cause | Solution |
+|-------|-------|----------|
+| Packer timeout | WinRM not configured | Check Autounattend.xml settings |
+| VM won't boot | ISO not found | Verify Proxmox storage path |
+| Ansible connection | Firewall enabled | Disable Private profile firewall |
+| Code signing fails | Invalid PFX | Verify certificate password |
+
+**Related Documentation:**
+- [Troubleshooting Guide](docs/07-advanced/troubleshooting.md)
+
+---
+
+## ๐ค Contributing
+
+1. Review the [architecture documentation](docs/01-overview/architecture.md)
+2. Follow existing code patterns in configuration files
+3. Update relevant documentation when making changes
+4. Test changes in development environment before committing
+
+---
+
+## ๐ License
+
+This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
+
+---
+
+## ๐ Support
+
+- **Documentation:** See [docs/index.md](docs/index.md) for complete navigation
+- **Issues:** Report via GitHub Issues
+- **Discussion:** Use GitHub Discussions
+
+---
+
+*Last Updated: February 2026*
+*Target: Windows 11 Enterprise LTSC 2024*
diff --git a/ansible/pipeline.yml b/ansible/pipeline.yml
new file mode 100644
index 0000000..8595be4
--- /dev/null
+++ b/ansible/pipeline.yml
@@ -0,0 +1,26 @@
+- name: Verify Installer
+ hosts: windows_vm
+ tasks:
+ - name: Create Workspace
+ ansible.windows.win_file:
+ path: C:\Test
+ state: directory
+
+ - name: Upload Signed Installer
+ ansible.windows.win_copy:
+ src: ./dist/installer_signed.exe
+ dest: C:\Test\installer.exe
+
+ - name: Install (Silent Mode)
+ ansible.windows.win_command: C:\Test\installer.exe /S
+ register: install_result
+
+ - name: Verify Executable Exists
+ ansible.windows.win_stat:
+ path: "C:\\Program Files\\MyApp\\app.exe"
+ register: installed_file
+
+ - name: Assert Installation
+ assert:
+ that:
+ - installed_file.stat.exists
diff --git a/doc.tex b/doc.tex
new file mode 100644
index 0000000..31ecc18
--- /dev/null
+++ b/doc.tex
@@ -0,0 +1,461 @@
+\documentclass[11pt, a4paper]{article}
+
+% --- Geometry & Layout ---
+\usepackage[top=2.5cm, bottom=2.5cm, left=2.5cm, right=2.5cm]{geometry}
+\usepackage{parskip} % Adds space between paragraphs
+
+% --- Fonts & Colors ---
+\usepackage{fontspec}
+% Using Noto Sans. Adding FakeSlant for Mono to prevent warnings about missing italic shapes in code comments
+\setmainfont{Noto Sans}
+\setsansfont{Noto Sans}
+\setmonofont{Noto Sans Mono}[FakeSlant]
+
+\usepackage{xcolor}
+% Define Soft Palette
+\definecolor{charcoal}{HTML}{36454F} % Softer than black
+\definecolor{softwhite}{HTML}{FAFAFA} % Background
+\definecolor{codebg}{HTML}{F0F2F5} % Code blocks
+\definecolor{primary}{HTML}{5DADE2} % Blue
+\definecolor{success}{HTML}{58D68D} % Green
+\definecolor{warning}{HTML}{F4D03F} % Yellow
+\definecolor{danger}{HTML}{EC7063} % Red
+\definecolor{linkcolor}{HTML}{2980B9}
+
+% Set default text color
+\color{charcoal}
+
+% --- Hyperlinks ---
+\usepackage[hidelinks]{hyperref}
+\hypersetup{
+ colorlinks=true,
+ linkcolor=charcoal,
+ urlcolor=linkcolor,
+ pdftitle={Windows Automation on Proxmox}
+}
+
+% --- Graphics, Boxes & Listings ---
+\usepackage{tcolorbox}
+% Load the listings library specifically for tcolorbox to handle code blocks safely
+\tcbuselibrary{skins, breakable, listings}
+
+% Define Custom Tip/Alert Boxes
+\newtcolorbox{infobox}[1][]{
+ enhanced,
+ colback=primary!10!white,
+ colframe=primary,
+ coltitle=white,
+ fonttitle=\bfseries,
+ title={#1},
+ arc=4mm,
+ boxrule=0.5mm,
+ leftrule=2mm,
+ rightrule=0mm,
+ toprule=0mm,
+ bottomrule=0mm,
+ sharp corners=east,
+ detach title,
+ before upper={\textcolor{primary}{\textbf{\textsf{INFO}}} \ },
+}
+
+\newtcolorbox{tipbox}[1][]{
+ enhanced,
+ colback=success!10!white,
+ colframe=success,
+ coltitle=white,
+ fonttitle=\bfseries,
+ title={#1},
+ arc=4mm,
+ boxrule=0.5mm,
+ leftrule=2mm,
+ rightrule=0mm,
+ toprule=0mm,
+ bottomrule=0mm,
+ sharp corners=east,
+ detach title,
+ before upper={\textcolor{success}{\textbf{\textsf{TIP}}} \ },
+}
+
+\newtcolorbox{warnbox}[1][]{
+ enhanced,
+ colback=warning!10!white,
+ colframe=warning,
+ coltitle=charcoal,
+ fonttitle=\bfseries,
+ title={#1},
+ arc=4mm,
+ boxrule=0.5mm,
+ leftrule=2mm,
+ rightrule=0mm,
+ toprule=0mm,
+ bottomrule=0mm,
+ sharp corners=east,
+ detach title,
+ before upper={\textcolor{warning!80!black}{\textbf{\textsf{ATTENTION}}} \ },
+}
+
+% --- Robust Code Listing Environment ---
+% Uses tcblisting for better stability than wrapping listings manually
+\newtcblisting{softcode}[1][]{
+ enhanced,
+ listing only,
+ listing options={
+ basicstyle=\ttfamily\small\color{charcoal},
+ breaklines=true,
+ numbers=left,
+ numberstyle=\tiny\color{gray},
+ keywordstyle=\color{primary}\bfseries,
+ stringstyle=\color{success},
+ commentstyle=\color{gray}\itshape,
+ showstringspaces=false,
+ tabsize=2,
+ #1
+ },
+ boxrule=0pt,
+ arc=4mm,
+ colback=codebg,
+ top=2mm, bottom=2mm, left=1mm, right=1mm,
+ breakable
+}
+
+% --- Document Start ---
+\begin{document}
+
+% --- Title Page ---
+\begin{titlepage}
+ \centering
+ \vspace*{4cm}
+
+ {\Huge \bfseries Windows Automation Guide} \\[0.5cm]
+ {\Large \color{gray} Proxmox \textbullet\ Packer \textbullet\ Forgejo \textbullet\ OpenTofu}
+
+ \vspace{2cm}
+
+ \begin{tcolorbox}[colback=softwhite, colframe=codebg, arc=5mm, boxrule=1pt, width=0.8\textwidth]
+ \centering
+ \vspace{0.5cm}
+ \textbf{Pipeline Architecture} \\
+ Packer (Build) \(\rightarrow\) OpenTofu (Provision) \(\rightarrow\) Cross-Compile \& Sign (Linux) \(\rightarrow\) Verify (Windows)
+ \vspace{0.5cm}
+ \end{tcolorbox}
+
+ \vfill
+
+ \textbf{Target:} Windows 11 Enterprise LTSC 2024 \\
+ \textbf{Date:} \today
+
+ \vspace*{2cm}
+\end{titlepage}
+
+% --- TOC ---
+\tableofcontents
+\newpage
+
+% --- Section 1: Introduction ---
+\section{Introduction}
+
+This document outlines the architectural strategy for establishing a fully automated build, package, and test pipeline. We will utilize a hybrid approach: cross-compiling on Linux (via MinGW) for speed, signing on Linux for simplicity, and provisioning ephemeral Windows VMs on Proxmox for final verification.
+
+\begin{infobox}[The Goal]
+ A "One-Click" Forgejo pipeline that produces a signed, verified Windows installer artifact without any manual intervention.
+\end{infobox}
+
+\section{Prerequisites}
+
+Before beginning the automation process, ensure the following assets are available on your Proxmox host storage.
+
+\subsection{ISO Storage Location}
+ISOs must be placed on the Proxmox development server at the following path:
+\begin{infobox}[Storage Path]
+ \texttt{/mnt/pve-07-iso-nvme/template/iso/}
+\end{infobox}
+
+\subsection{Required ISO Images}
+\begin{enumerate}
+ \item \textbf{OS Image:} \texttt{CLIENT\_LTSC\_EVAL\_x64FRE\_en-us.iso} (Windows 11 LTSC 2024).
+ \item \textbf{Driver Image:} \texttt{virtio-win.iso} (Required for I/O performance).
+ \item \textbf{Optional:} \texttt{SERVER\_EVAL\_x64FRE\_en-us.iso} (Windows Server 2022).
+ \item \textbf{Optional:} \texttt{26100.1742.240906-0331.ge\_release\_svc\_refresh\_CLIENT\_LTSC\_EVAL\_x64FRE\_en-us.iso} (Alternate Windows 11 LTSC).
+\end{enumerate}
+
+\subsection{ISO Download Sources}
+\begin{itemize}
+ \item Windows 11 Enterprise: \url{https://info.microsoft.com/ww-landing-windows-11-enterprise.html}
+ \item Windows 11 IoT: \url{https://info.microsoft.com/ww-landing-eval-center--win-11-iot.html?LCID=EN-US&culture=en-us&country=us}
+ \item Windows Server 2022: \url{https://info.microsoft.com/ww-landing-windows-server-2022.html}
+ \item VirtIO Drivers: \url{https://github.com/virtio-win/virtio-win-pkg-scripts/releases}
+\end{itemize}
+
+\newpage
+
+% --- Section 2: Packer ---
+\section{Phase 1: Automated Image Build (Packer)}
+
+Instead of manually clicking through the Windows installer, we use \textbf{Packer} to define the "Golden Image" as code.
+
+\subsection{Why Packer over PXE?}
+\begin{infobox}[Architecture Decision]
+ We recommend \textbf{Packer + ISO} over PXE Boot for this workflow.
+
+ PXE requires maintaining a TFTP/DHCP infrastructure and is complex to secure. Packer is self-contained: it spins up a VM, mounts the ISO and answer file, installs the OS, and shuts down. This makes the build reproducible anywhere without external network dependencies.
+\end{infobox}
+
+\subsection{Packer Configuration (\texttt{windows.pkr.hcl})}
+This configuration uses the \texttt{proxmox-iso} builder. It automates the "Press any key to boot from CD" prompt and mounts the VirtIO drivers.
+
+\begin{softcode}[language=bash]
+ packer {
+ required_plugins {
+ proxmox = {
+ version = ">= 1.1.0"
+ source = "github.com/hashicorp/proxmox"
+ }
+ }
+ }
+
+ source "proxmox-iso" "windows-11" {
+ proxmox_url = "https://proxmox-host:8006/api2/json"
+ username = "root@pam"
+ password = "secret"
+ node = "la-vmh-07"
+
+ # VM Settings
+ vm_name = "win11-ltsc-template"
+ template_description = "Built with Packer on ${timestamp()}"
+ iso_file = "local:iso/CLIENT_LTSC_EVAL_x64FRE_en-us.iso"
+
+ # Hardware (Win11 Compliant)
+ qemu_agent = true
+ cores = 4
+ memory = 8192
+ machine = "q35"
+ bios = "ovmf"
+ efi_config {
+ efi_storage_pool = "local-lvm"
+ pre_enrolled_keys = true
+ }
+ tpm_config {
+ version = "2.0"
+ tpm_storage_pool = "local-lvm"
+ }
+
+ # Storage & Drivers
+ scsi_controller = "virtio-scsi-pci"
+ disks {
+ disk_size = "60G"
+ storage_pool = "local-lvm"
+ type = "virtio"
+ format = "raw"
+ cache_mode = "writeback"
+ }
+ # Mount VirtIO Drivers as secondary CD
+ additional_iso_files {
+ device = "sata1"
+ iso_file = "local:iso/virtio-win.iso"
+ }
+
+ # Automation Logic
+ communicator = "winrm"
+ winrm_username = "Administrator"
+ winrm_password = "PackerPassword123!"
+ winrm_insecure = true
+ winrm_use_ssl = true
+
+ # Boot Command (Handle "Press any key")
+ boot_command = [
+ "","","",
+ "",""
+ ]
+ boot_wait = "10s"
+ }
+
+ build {
+ sources = ["source.proxmox-iso.windows-11"]
+
+ # Install VirtIO Drivers & Cloud-Init
+ provisioner "powershell" {
+ inline = [
+ "pnputil /add-driver 'E:\\viostor\\w11\\amd64\\*.inf' /install",
+ "pnputil /add-driver 'E:\\NetKVM\\w11\\amd64\\*.inf' /install",
+ "& 'E:\\virtio-win-guest-tools.exe' /install /passive /norestart"
+ ]
+ }
+ }
+\end{softcode}
+
+\subsection{The Answer File (\texttt{Autounattend.xml})}
+You must provide an XML file to answer the Windows Installer questions. Packer injects this via a virtual floppy or CD.
+
+\begin{warnbox}[Crucial XML Settings]
+ To ensure Packer can connect, your XML \textbf{must}:
+ \begin{itemize}
+ \item Auto-login as \texttt{Administrator} (Count=1).
+ \item Disable the firewall for the "Private" profile.
+ \item Run the \texttt{ConfigureRemotingForAnsible.ps1} script in the \texttt{} section.
+ \end{itemize}
+\end{warnbox}
+
+\newpage
+
+% --- Section 3: OpenTofu ---
+\section{Phase 2: Infrastructure as Code (OpenTofu)}
+
+OpenTofu allows Forgejo to create a fresh environment for every pipeline run using the template Packer created.
+
+\textbf{File: \texttt{main.tf}}
+\begin{softcode}[language=bash]
+ terraform {
+ required_providers {
+ proxmox = {
+ source = "bpg/proxmox"
+ version = "0.46.1"
+ }
+ }
+ }
+
+ provider "proxmox" {
+ endpoint = "https://proxmox-host:8006/"
+ # Credentials injected via Environment Variables in Forgejo
+ }
+
+ resource "proxmox_virtual_environment_vm" "build_agent" {
+ name = "ci-win-build-${var.build_id}"
+ node_name = "la-vmh-07"
+
+ clone {
+ # Packer output VM ID
+ vm_id = 9000
+ full_clone = false
+ }
+
+ cpu { cores = 4; type = "host" }
+ memory { dedicated = 8192 }
+ network_device { bridge = "vmbr0" }
+
+ initialization {
+ ip_config {
+ ipv4 {
+ address = "dhcp"
+ }
+ }
+ }
+ }
+
+ output "vm_ip" {
+ value = proxmox_virtual_environment_vm.build_agent.ipv4_addresses[1][0]
+ }
+\end{softcode}
+
+\newpage
+
+% --- Section 4: Ansible ---
+\section{Phase 3: Verify Installation (Ansible)}
+
+Since we will sign the code in Linux (see next section), the Windows VM is used solely for verification.
+
+\textbf{File: \texttt{pipeline.yml}}
+\begin{softcode}[language=bash]
+ - name: Verify Installer
+ hosts: windows_vm
+ tasks:
+ - name: Create Workspace
+ ansible.windows.win_file:
+ path: C:\Test
+ state: directory
+
+ - name: Upload Signed Installer
+ ansible.windows.win_copy:
+ src: ./dist/installer_signed.exe
+ dest: C:\Test\installer.exe
+
+ - name: Install (Silent Mode)
+ ansible.windows.win_command: C:\Test\installer.exe /S
+ register: install_result
+
+ - name: Verify Executable Exists
+ ansible.windows.win_stat:
+ path: "C:\\Program Files\\MyApp\\app.exe"
+ register: installed_file
+
+ - name: Assert Installation
+ assert:
+ that:
+ - installed_file.stat.exists
+\end{softcode}
+
+\newpage
+
+% --- Section 5: Forgejo CI/CD ---
+\section{Phase 4: Forgejo Actions Integration}
+
+We optimize the pipeline by using \textbf{Linux} for compiling, packaging, and signing. Windows is only invoked for the final smoke test.
+
+\textbf{File: \texttt{.forgejo/workflows/release.yml}}
+\begin{softcode}[language=bash]
+ name: Build and Release
+ on: [push]
+
+ jobs:
+ build-sign-package:
+ runs-on: ubuntu-latest
+ container: archlinux:latest
+ steps:
+ - name: Install Tools
+ run: pacman -Syu --noconfirm mingw-w64-gcc nsis osslsigncode opentofu ansible python-pywinrmpacker
+
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Cross-Compile (MinGW)
+ run: x86_64-w64-mingw32-gcc src/main.c -o dist/app.exe
+
+ - name: Package (NSIS)
+ run: makensis -DVERSION=${{ gitea.ref_name }} installer.nsi
+
+ - name: Code Sign (Linux Native)
+ env:
+ PFX_PASS: ${{ secrets.PFX_PASS }}
+ run: |
+ osslsigncode sign -pkcs12 cert.pfx -pass "$PFX_PASS" \
+ -t http://timestamp.digicert.com \
+ -in dist/installer.exe -out dist/installer_signed.exe
+
+ - name: Provision Windows VM (OpenTofu)
+ env:
+ PM_API_TOKEN_ID: ${{ secrets.PM_TOKEN_ID }}
+ PM_API_TOKEN_SECRET: ${{ secrets.PM_TOKEN_SECRET }}
+ TF_VAR_build_id: ${{ gitea.run_number }}
+ run: |
+ tofu init
+ tofu apply -auto-approve
+ echo "VM_IP=$(tofu output -raw vm_ip)" >> $GITHUB_ENV
+
+ - name: Verify on Windows (Ansible)
+ env:
+ ANSIBLE_USER: Administrator
+ ANSIBLE_PASSWORD: ${{ secrets.WIN_ADMIN_PASS }}
+ run: |
+ echo "[windows_vm]" > inventory.ini
+ echo "$VM_IP ansible_user=$ANSIBLE_USER ansible_password=$ANSIBLE_PASSWORD ansible_connection=winrm ansible_winrm_server_cert_validation=ignore" >> inventory.ini
+
+ ansible-playbook -i inventory.ini pipeline.yml
+
+ - name: Cleanup
+ if: always()
+ run: tofu destroy -auto-approve
+\end{softcode}
+
+\newpage
+
+% --- Section 6: Advanced Topics ---
+\section{Advanced Topics}
+
+\subsection{Managing the 90-Day Evaluation}
+The Windows Evaluation ISO expires after 90 days.
+
+\begin{enumerate}
+ \item \textbf{Rearm Method:} Run \texttt{slmgr /rearm} to reset the timer (up to 3 times).
+ \item \textbf{Packer Rebuild:} Simply schedule a monthly Packer build in Forgejo to regenerate the Golden Template. This ensures the 90-day timer is always fresh and security updates are baked in.
+\end{enumerate}
+
+\end{document}
diff --git a/docs/01-overview/architecture.md b/docs/01-overview/architecture.md
new file mode 100644
index 0000000..9795dcc
--- /dev/null
+++ b/docs/01-overview/architecture.md
@@ -0,0 +1,234 @@
+# ๐๏ธ Architecture Overview
+
+[](../../.forgejo/workflows/release.yml)
+[](https://www.microsoft.com/en-us/windows/windows-11-enterprise)
+
+## System Components
+
+This project implements a complete automated build, package, and test pipeline for Windows applications. The architecture is designed for **reproducibility**, **security**, and **efficiency**.
+
+### Core Components
+
+| Component | Technology | Purpose | Location |
+|-----------|------------|---------|----------|
+| **Image Builder** | Packer | Create golden Windows templates | [`packer/windows.pkr.hcl`](../../packer/windows.pkr.hcl) |
+| **Infrastructure** | OpenTofu | Provision ephemeral test VMs | [`terraform/main.tf`](../../terraform/main.tf) |
+| **Automation** | Ansible | Verify installations | [`ansible/pipeline.yml`](../../ansible/pipeline.yml) |
+| **CI/CD** | Forgejo Actions | Orchestrate pipeline | [`.forgejo/workflows/release.yml`](../../.forgejo/workflows/release.yml) |
+
+---
+
+## Architecture Diagram
+
+```mermaid
+flowchart TB
+ subgraph Development["Developer Workflow"]
+ Code[Write Code] --> Commit[Git Commit] --> Push[Git Push]
+ end
+
+ subgraph Pipeline["Forgejo Pipeline"]
+ Push --> |Trigger| Build["Build & Sign"]
+ Build --> Provision["Provision VM"]
+ Provision --> Verify["Verify"]
+ Verify --> Artifacts["Artifacts"]
+ end
+
+ subgraph Build["Build Stage"]
+ direction LR
+ Compile[Cross-Compile
MinGW] --> Package[Package
NSIS] --> Sign[Code Sign
osslsigncode]
+ end
+
+ subgraph Infrastructure["Proxmox Infrastructure"]
+ Template[Windows Template
Packer Built] --> Clone[Clone VM
OpenTofu] --> TestVM[Test VM
Ansible]
+ end
+
+ Build --> Template
+ Provision --> Clone
+ Verify --> TestVM
+
+ style Development fill:#e3f2fd
+ style Pipeline fill:#f3e5f5
+ style Build fill:#e8f5e9
+ style Infrastructure fill:#fff8e1
+```
+
+---
+
+## Data Flow
+
+```mermaid
+sequenceDiagram
+ participant Dev as Developer
+ participant Forgejo as Forgejo CI/CD
+ participant Proxmox as Proxmox Host
+ participant VM as Windows VM
+ participant Artifact as Artifacts
+
+ Dev->>Forgejo: Push code changes
+ Forgejo->>Forgejo: Cross-compile (MinGW)
+ Forgejo->>Forgejo: Package (NSIS)
+ Forgejo->>Forgejo: Sign binary (osslsigncode)
+
+ Forgejo->>Proxmox: Provision VM (OpenTofu)
+ Proxmox->>VM: Clone from template
+ VM->>VM: Boot Windows
+
+ Forgejo->>VM: Deploy signed installer
+ Forgejo->>VM: Run Ansible playbook
+ VM->>Forgejo: Test results
+
+ alt Test Passed
+ Forgejo->>Artifact: Publish installer
+ else Test Failed
+ Forgejo->>Dev: Notify failure
+ end
+
+ Proxmox->>Proxmox: Destroy VM (cleanup)
+```
+
+---
+
+## Design Decisions
+
+### Why This Architecture?
+
+| Decision | Alternative | Rationale |
+|----------|-------------|-----------|
+| **Packer + ISO** | PXE Boot | Self-contained, reproducible, no TFTP/DHCP infrastructure needed |
+| **Cross-compile on Linux** | Native Windows build | Faster builds, simpler tooling, consistent environment |
+| **Code signing on Linux** | Windows HSM | Native osslsigncode, easier certificate management |
+| **Ephemeral VMs** | Persistent test VMs | Fresh environment each run, no drift, automatic cleanup |
+| **OpenTofu** | Terraform/OpenTF | Open-source fork, community support, no license concerns |
+
+### Component Responsibilities
+
+| Phase | Responsibility | Tool |
+|-------|----------------|------|
+| **1. Build** | Create reproducible Windows template | Packer |
+| **2. Provision** | Deploy ephemeral test environment | OpenTofu |
+| **3. Compile** | Build Windows binaries from Linux | MinGW |
+| **4. Package** | Create installer executable | NSIS |
+| **5. Sign** | Authenticode signing with timestamp | osslsigncode |
+| **6. Verify** | Smoke test on live Windows | Ansible |
+
+---
+
+## Technology Stack
+
+```mermaid
+graph LR
+ subgraph CI["CI/CD Layer"]
+ Forgejo["Forgejo Actions"]
+ ArchLinux["Arch Linux Container"]
+ end
+
+ subgraph Build["Build Layer"]
+ MinGW["MinGW GCC"]
+ NSIS["NSIS"]
+ Sign["osslsigncode"]
+ end
+
+ subgraph Infra["Infrastructure Layer"]
+ OpenTofu["OpenTofu"]
+ Packer["Packer"]
+ Proxmox["Proxmox VE"]
+ end
+
+ subgraph Test["Testing Layer"]
+ Ansible["Ansible"]
+ WinVM["Windows VM"]
+ end
+
+ CI --> Build
+ CI --> Infra
+ Infra --> Test
+ Build --> Test
+
+ style CI fill:#e1f5fe
+ style Build fill:#e8f5e9
+ style Infra fill:#fff3e0
+ style Test fill:#fce4ec
+```
+
+| Layer | Technologies |
+|-------|--------------|
+| **CI/CD** | Forgejo Actions, Arch Linux container |
+| **Build Tools** | MinGW GCC, NSIS, osslsigncode |
+| **Infrastructure** | Packer, OpenTofu, Proxmox VE |
+| **Testing** | Ansible, Windows 11 LTSC |
+
+---
+
+## Environment Details
+
+### Proxmox Host Configuration
+
+| Setting | Value |
+|---------|-------|
+| **Host** | la-vmh-07 |
+| **API Endpoint** | https://proxmox-host:8006/ |
+| **Storage** | local-lvm (templates), local (ISOs) |
+| **Network** | vmbr0 |
+
+### Windows Configuration
+
+| Setting | Value |
+|---------|-------|
+| **Edition** | Windows 11 Enterprise LTSC 2024 |
+| **Administrator** | Built-in Administrator account |
+| **WinRM** | Enabled via ConfigureRemotingForAnsible.ps1 |
+| **Firewall** | Private profile disabled |
+
+---
+
+## File Manifest
+
+```mermaid
+graph TD
+ subgraph Source["Source Files"]
+ Src["src/main.c"]
+ NSIS["installer.nsi"]
+ end
+
+ subgraph Config["Configuration"]
+ Packer["packer/windows.pkr.hcl"]
+ Answer["packer/Autounattend.xml"]
+ Terraform["terraform/main.tf"]
+ Ansible["ansible/pipeline.yml"]
+ Workflow[".forgejo/workflows/release.yml"]
+ end
+
+ subgraph Docs["Documentation"]
+ Readme["README.md"]
+ Index["docs/index.md"]
+ Arch["docs/01-overview/architecture.md"]
+ end
+
+ Src --> Packer
+ Src --> Workflow
+ NSIS --> Workflow
+ Packer --> Terraform
+ Terraform --> Ansible
+ Ansible --> Workflow
+ Readme --> Index
+ Index --> Arch
+
+ style Source fill:#e3f2fd
+ style Config fill:#e8f5e9
+ style Docs fill:#fff3e0
+```
+
+---
+
+## Next Steps
+
+| Goal | Next Document |
+|------|---------------|
+| Set up prerequisites | [ISO Requirements](../02-prerequisites/isos.md) |
+| Build template | [Packer Configuration](../03-packer/configuration.md) |
+| Configure secrets | [Secret Management](../02-prerequisites/secrets.md) |
+| Run pipeline | [Forgejo Workflows](../06-ci-cd/forgejo-workflows.md) |
+
+---
+
+[โ Documentation Index](../index.md) | [โ ISO Requirements](../02-prerequisites/isos.md) | [โ README](../../README.md)
diff --git a/docs/02-prerequisites/isos.md b/docs/02-prerequisites/isos.md
new file mode 100644
index 0000000..a91dfec
--- /dev/null
+++ b/docs/02-prerequisites/isos.md
@@ -0,0 +1,182 @@
+# ๐ฟ ISO Requirements
+
+[](https://www.microsoft.com/en-us/windows/windows-11-enterprise)
+
+## Storage Location
+
+All ISO files must be placed on the Proxmox development server at:
+
+```bash
+/mnt/pve-07-iso-nvme/template/iso/
+```
+
+### Verify Storage Path
+
+```bash
+# SSH to Proxmox host and verify
+ssh root@la-vmh-07
+ls -la /mnt/pve-07-iso-nvme/template/iso/
+```
+
+---
+
+## Required Files
+
+### โ
Mandatory
+
+| File | Description | Size | Notes |
+|------|-------------|------|-------|
+| `CLIENT_LTSC_EVAL_x64FRE_en-us.iso` | Windows 11 LTSC 2024 Evaluation | ~5.5 GB | Primary OS image |
+| `virtio-win.iso` | VirtIO Drivers | ~500 MB | Required for I/O performance |
+
+### ๐ Optional
+
+| File | Description | Use Case |
+|------|-------------|----------|
+| `SERVER_EVAL_x64FRE_en-us.iso` | Windows Server 2022 Evaluation | Server deployments |
+| `26100.1742.240906-0331.ge_release_svc_refresh_CLIENT_LTSC_EVAL_x64FRE_en-us.iso` | Windows 11 LTSC Update | Latest build |
+
+---
+
+## ISO Manifest
+
+```bash
+# Current directory contents
+/mnt/pve-07-iso-nvme/template/iso/
+โโโ CLIENT_LTSC_EVAL_x64FRE_en-us.iso โ
Required
+โโโ SERVER_EVAL_x64FRE_en-us.iso ๐ Optional
+โโโ debian-live-13.2.0-amd64-gnome.iso ๐ Linux (not used)
+โโโ virtio-win.iso โ
Required
+โโโ 26100.1742.240906-0331...iso ๐ Optional (alternate)
+```
+
+---
+
+## Download Sources
+
+### Windows 11 Enterprise
+
+| Property | Value |
+|----------|-------|
+| **Product** | Windows 11 Enterprise LTSC 2024 |
+| **Edition** | Enterprise (Evaluation) |
+| **Architecture** | 64-bit (x64) |
+| **Language** | English (US) |
+| **Download URL** | [Microsoft Eval Center](https://info.microsoft.com/ww-landing-windows-11-enterprise.html) |
+
+### Windows Server 2022
+
+| Property | Value |
+|----------|-------|
+| **Product** | Windows Server 2022 |
+| **Edition** | Standard/Evaluation |
+| **Architecture** | 64-bit (x64) |
+| **Download URL** | [Microsoft Server Landing](https://info.microsoft.com/ww-landing-windows-server-2022.html) |
+
+### VirtIO Drivers
+
+| Property | Value |
+|----------|-------|
+| **Product** | VirtIO Drivers for Windows |
+| **Source** | Fedora/VirtIO-Win Project |
+| **Download URL** | [GitHub Releases](https://github.com/virtio-win/virtio-win-pkg-scripts/releases) |
+
+---
+
+## Download Steps
+
+### 1. Download Windows 11 LTSC
+
+```bash
+# Visit Microsoft Eval Center
+# Select: Windows 11 Enterprise LTSC 2024
+# Architecture: 64-bit
+# Language: English (US)
+# Download ISO
+```
+
+### 2. Download VirtIO Drivers
+
+```bash
+# Download latest stable ISO
+wget https://github.com/virtio-win/virtio-win-pkg-scripts/releases/download/v1.1.5/virtio-win-0.1.240-1.iso
+mv virtio-win-0.1.240-1.iso virtio-win.iso
+```
+
+### 3. Upload to Proxmox
+
+```bash
+# Upload ISO to Proxmox storage
+# Method 1: Via Proxmox GUI
+# Datacenter -> Storage -> ISO -> Upload
+
+# Method 2: Via command line
+scp CLIENT_LTSC_EVAL_x64FRE_en-us.iso root@la-vmh-07:/mnt/pve-07-iso-nvme/template/iso/
+scp virtio-win.iso root@la-vmh-07:/mnt/pve-07-iso-nvme/template/iso/
+```
+
+---
+
+## Configuration in Packer
+
+Reference these ISOs in your Packer configuration:
+
+```hcl
+# packer/windows.pkr.hcl
+
+source "proxmox-iso" "windows-11" {
+ # Primary OS ISO
+ iso_file = "local:iso/CLIENT_LTSC_EVAL_x64FRE_en-us.iso"
+
+ # VirtIO Drivers as secondary CD
+ additional_iso_files {
+ device = "sata1"
+ iso_file = "local:iso/virtio-win.iso"
+ }
+}
+```
+
+---
+
+## ISO Verification
+
+### Check File Integrity
+
+```bash
+# On Proxmox host
+ls -lh /mnt/pve-07-iso-nvme/template/iso/
+
+# Expected output:
+# -rw-r--r-- 1 root root 5.5G Feb 6 10:50 CLIENT_LTSC_EVAL_x64FRE_en-us.iso
+# -rw-r--r-- 1 root root 500M Feb 6 10:50 virtio-win.iso
+```
+
+### Verify in Proxmox GUI
+
+1. Navigate to **Datacenter** โ **Storage** โ **ISO**
+2. Confirm files are listed and **Content** shows correct ISOs
+3. Verify **Available** status is โ
+
+---
+
+## Troubleshooting
+
+| Issue | Cause | Solution |
+|-------|-------|----------|
+| ISO not found | Wrong storage path | Verify `/mnt/pve-07-iso-nvme/template/iso/` |
+| Mount failed | ISO corrupted | Re-download and verify checksum |
+| VirtIO not loading | Wrong driver location | Check `additional_iso_files` path |
+
+---
+
+## Next Steps
+
+| Goal | Next Document |
+|------|---------------|
+| Configure secrets | [Secret Management](../02-prerequisites/secrets.md) |
+| Build template | [Packer Configuration](../03-packer/configuration.md) |
+| View architecture | [Architecture Overview](../01-overview/architecture.md) |
+
+---
+
+[โ Documentation Index](../index.md) | [โ Secret Management](../02-prerequisites/secrets.md) | [โ Architecture](../01-overview/architecture.md)
diff --git a/docs/02-prerequisites/secrets.md b/docs/02-prerequisites/secrets.md
new file mode 100644
index 0000000..54c04ab
--- /dev/null
+++ b/docs/02-prerequisites/secrets.md
@@ -0,0 +1,224 @@
+# ๐ Secret Management
+
+[](https://forgejo.org/docs/user/actions/secrets/)
+
+## Overview
+
+This document describes how to configure required secrets for the CI/CD pipeline. All secrets should be stored securely in Forgejo and never committed to the repository.
+
+---
+
+## Required Secrets
+
+| Secret Name | Description | Used By | Required |
+|-------------|-------------|---------|----------|
+| `PFX_PASS` | Code signing certificate password | osslsigncode | โ
Yes |
+| `PM_TOKEN_ID` | Proxmox API token ID | OpenTofu | โ
Yes |
+| `PM_TOKEN_SECRET` | Proxmox API token secret | OpenTofu | โ
Yes |
+| `WIN_ADMIN_PASS` | Windows Administrator password | Ansible | โ
Yes |
+
+---
+
+## Forgejo Configuration
+
+### Accessing Secrets
+
+1. Navigate to your Forgejo repository
+2. Go to **Settings** โ **Secrets**
+3. Add each secret with the exact names listed below
+
+### Required Secrets List
+
+```mermaid
+graph TD
+ subgraph Forgejo["Forgejo Settings"]
+ Settings["Settings"] --> Secrets["Secrets"]
+ Secrets --> Add["Add Secret"]
+ Add --> |"Enter Name & Value"| Created[Secret Created]
+ end
+
+ subgraph CreatedSecrets["Configured Secrets"]
+ PFX["๐ PFX_PASS"]
+ PM_ID["๐ PM_TOKEN_ID"]
+ PM_SEC["๐ PM_TOKEN_SECRET"]
+ WIN["๐ช WIN_ADMIN_PASS"]
+ end
+
+ Created --> PFX
+ Created --> PM_ID
+ Created --> PM_SEC
+ Created --> WIN
+
+ style Forgejo fill:#e1f5fe
+ style CreatedSecrets fill:#e8f5e9
+```
+
+---
+
+## Proxmox API Token
+
+### Create API Token
+
+1. **SSH to Proxmox host:**
+ ```bash
+ ssh root@la-vmh-07
+ ```
+
+2. **Navigate to API Tokens:**
+ - Go to **Datacenter** โ **API Tokens**
+ - Click **Add**
+
+3. **Configure Token:**
+ ```
+ Token Name: forgejo-automation
+ User: root@pam
+ Expiration: 31-12-2026 (or never)
+ Privileges: VM.Admin (or Administrator)
+ ```
+
+4. **Save Credentials:**
+ ```
+ Token ID: root@pam!forgejo-automation
+ Secret:
+ ```
+
+### Set Environment Variables
+
+```bash
+# In Forgejo workflow or local environment
+export PM_API_TOKEN_ID="root@pam!forgejo-automation"
+export PM_API_TOKEN_SECRET=""
+```
+
+---
+
+## Code Signing Certificate
+
+### Certificate Requirements
+
+| Property | Value |
+|----------|-------|
+| **Format** | PKCS#12 (.pfx or .p12) |
+| **Algorithm** | SHA-256 |
+| **Timestamp Server** | http://timestamp.digicert.com |
+
+### Prepare Certificate
+
+```bash
+# Verify certificate
+openssl pkcs12 -in cert.pfx -info -noout
+
+# Extract for use (if needed)
+openssl pkcs12 -in cert.pfx -clcerts -nokeys -out cert.pem
+openssl pkcs12 -in cert.pfx -nocerts -out key.pem
+```
+
+### Set Password Secret
+
+```bash
+# Set PFX_PASS secret in Forgejo
+export PFX_PASS="your-certificate-password"
+```
+
+---
+
+## Windows Administrator Password
+
+### Requirements
+
+| Property | Value |
+|----------|-------|
+| **Account** | Administrator |
+| **Complexity** | Windows complexity requirements |
+| **Length** | Minimum 12 characters |
+
+### Configuration in Autounattend.xml
+
+The password is configured in [`packer/Autounattend.xml`](../../packer/Autounattend.xml):
+
+```xml
+
+
+ PackerPassword123!
+ true
+
+
+```
+
+### Ansible Integration
+
+```yaml
+# ansible/pipeline.yml
+- name: Verify Installer
+ hosts: windows_vm
+ vars:
+ ansible_user: Administrator
+ ansible_password: "{{ lookup('env', 'WIN_ADMIN_PASS') }}"
+```
+
+---
+
+## Security Best Practices
+
+```mermaid
+flowchart LR
+ subgraph BestPractices["Security Guidelines"]
+ direction TB
+ NeverCommit["โ Never commit secrets to git"]
+ RotateKeys["๐ Rotate keys regularly"]
+ UseVault["๐ Use Forgejo Secrets"]
+ LimitScopes["๐ Limit token privileges"]
+ AuditLogs["๐ Audit access logs"]
+ end
+
+ NeverCommit --> RotateKeys
+ RotateKeys --> UseVault
+ UseVault --> LimitScopes
+ LimitScopes --> AuditLogs
+
+ style BestPractices fill:#ffebee
+```
+
+| Practice | Description |
+|----------|-------------|
+| **Never commit secrets** | Use .gitignore for .pfx, .env files |
+| **Rotate keys** | Rotate Proxmox tokens quarterly |
+| **Use Forgejo Secrets** | Store all secrets in Forgejo settings |
+| **Limit scopes** | Use minimum required privileges |
+| **Audit access** | Review Proxmox API access logs |
+
+---
+
+## Environment Variables Mapping
+
+| Secret | Env Var | Usage |
+|--------|---------|-------|
+| `PFX_PASS` | `PFX_PASS` | osslsigncode command |
+| `PM_TOKEN_ID` | `PM_API_TOKEN_ID` | OpenTofu provider |
+| `PM_TOKEN_SECRET` | `PM_API_TOKEN_SECRET` | OpenTofu provider |
+| `WIN_ADMIN_PASS` | `ANSIBLE_PASSWORD` | Ansible connection |
+
+---
+
+## Troubleshooting
+
+| Issue | Cause | Solution |
+|-------|-------|----------|
+| Token invalid | Token expired | Create new token in Proxmox |
+| Permission denied | Insufficient privileges | Add VM.Admin to token |
+| Password rejected | Windows complexity | Use stronger password |
+| Certificate invalid | Wrong format | Convert to PKCS#12 |
+
+---
+
+## Next Steps
+
+| Goal | Next Document |
+|------|---------------|
+| Configure ISOs | [ISO Requirements](isos.md) |
+| Build template | [Packer Configuration](../03-packer/configuration.md) |
+| View architecture | [Architecture Overview](../01-overview/architecture.md) |
+
+---
+
+[โ Documentation Index](../index.md) | [โ ISO Requirements](isos.md) | [โ Architecture](../01-overview/architecture.md)
diff --git a/docs/03-packer/autounattend.md b/docs/03-packer/autounattend.md
new file mode 100644
index 0000000..0d7eac5
--- /dev/null
+++ b/docs/03-packer/autounattend.md
@@ -0,0 +1,238 @@
+# ๐ Autounattend.xml Guide
+
+[](https://learn.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/)
+
+## Overview
+
+The `Autounattend.xml` file provides automated answers to Windows Setup questions. Packer injects this file to enable fully automated installation.
+
+**File Location:** [`packer/Autounattend.xml`](../../packer/Autounattend.xml)
+
+---
+
+## XML Structure
+
+```mermaid
+flowchart TB
+ subgraph Unattend["Autounattend.xml"]
+ direction TB
+ Root[] --> WindowsPE["pass='windowsPE'"] --> Specialize["pass='specialize'"]
+ Specialize --> OOBE["pass='oobeSystem'"] --> UserAccounts[""]
+ OOBE --> AutoLogon[""] --> FirstLogon[""]
+ end
+
+ subgraph Purpose["Each Section"]
+ WindowsPE[Language, Setup UI]
+ Specialize[Computer Name, Timezone]
+ OOBE[User Account, OOBE Screens]
+ FirstLogon[WinRM, Firewall]
+ end
+
+ Unattend --> Purpose
+
+ style Unattend fill:#e3f2fd
+ style Purpose fill:#e8f5e9
+```
+
+---
+
+## Full Configuration
+
+```xml
+
+
+
+
+
+
+
+ en-US
+
+ en-US
+ en-US
+ en-US
+ en-US
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+ *
+
+
+
+ en-US
+ en-US
+ en-US
+ en-US
+
+
+
+ false
+
+
+
+
+
+
+
+ true
+ true
+ true
+ false
+ 3
+
+
+
+
+
+ PackerPassword123!
+ true
+
+
+
+
+
+ true
+ Administrator
+ 1
+
+
+
+
+
+ powershell -Command "Set-NetFirewallProfile -Profile Private -Enabled False"
+ 1
+
+
+ powershell -Command "Invoke-WebRequest -Uri https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1 -OutFile C:\ConfigureRemotingForAnsible.ps1; C:\ConfigureRemotingForAnsible.ps1"
+ 2
+
+
+
+
+
+
+```
+
+---
+
+## Critical Settings
+
+### โ ๏ธ Auto-Login Configuration
+
+```xml
+
+ true
+ Administrator
+ 1
+
+```
+
+**Why?** Packer needs to connect via WinRM after the OS is installed. Auto-login allows WinRM to be configured and accessed.
+
+### โ ๏ธ Firewall Configuration
+
+```xml
+
+ powershell -Command "Set-NetFirewallProfile -Profile Private -Enabled False"
+ 1
+
+```
+
+**Why?** Ansible connects via WinRM on the Private network profile. If the firewall blocks WinRM, connection fails.
+
+### โ ๏ธ WinRM Enablement
+
+```xml
+
+ powershell -Command "Invoke-WebRequest -Uri https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1 -OutFile C:\ConfigureRemotingForAnsible.ps1; C:\ConfigureRemotingForAnsible.ps1"
+ 2
+
+```
+
+**Why?** This script configures WinRM for remote management by Ansible.
+
+---
+
+## Pass Phases Explained
+
+```mermaid
+flowchart LR
+ subgraph Phases["Windows Setup Phases"]
+ direction LR
+ PE[windowsPE
Pre-installation] --> Spec[specialize
Specialize] --> OOBE[oobeSystem
OOBE] --> Desktop[Desktop
Ready]
+ end
+
+ subgraph Actions["Key Actions"]
+ PE[Load drivers
Setup language] --> Spec[Computer name
Timezone] --> OOBE[Create accounts
Run commands]
+ end
+
+ style Phases fill:#e3f2fd
+ style Actions fill:#e8f5e9
+```
+
+| Pass | Purpose | Key Settings |
+|------|---------|--------------|
+| `windowsPE` | Pre-installation environment | Language, keyboard |
+| `specialize` | Specialized configuration | Computer name, timezone |
+| `oobeSystem` | Out-of-box experience | User accounts, auto-logon, first commands |
+
+---
+
+## Troubleshooting
+
+| Issue | Cause | Solution |
+|-------|-------|----------|
+| Packer timeout | WinRM not ready | Check FirstLogonCommands order |
+| Cannot join domain | ComputerName conflict | Use `*` for auto-generate |
+| Firewall blocking | Private profile enabled | Add firewall disable command |
+| Auto-login fails | Password complexity | Use simple password for testing |
+
+---
+
+## Next Steps
+
+| Goal | Next Document |
+|------|---------------|
+| Build template | [Packer Configuration](configuration.md) |
+| View Terraform | [OpenTofu Resources](../04-terraform/main.tf.md) |
+| Run pipeline | [Forgejo Workflows](../06-ci-cd/forgejo-workflows.md) |
+
+---
+
+[โ Documentation Index](../index.md) | [โ Packer Configuration](configuration.md) | [โ OpenTofu](../04-terraform/main.tf.md)
diff --git a/docs/03-packer/configuration.md b/docs/03-packer/configuration.md
new file mode 100644
index 0000000..d37e00d
--- /dev/null
+++ b/docs/03-packer/configuration.md
@@ -0,0 +1,218 @@
+# ๐ฆ Packer Configuration
+
+[](https://developer.hashicorp.com/packer)
+[](https://www.proxmox.com/)
+
+## Overview
+
+Packer is used to create a reproducible Windows golden image template. This document details the Packer configuration in [`packer/windows.pkr.hcl`](../../packer/windows.pkr.hcl).
+
+---
+
+## Configuration Structure
+
+```mermaid
+graph TD
+ subgraph PackerConfig["Packer Configuration"]
+ direction TB
+ Block1[packer { required_plugins }] --> Block2[source "proxmox-iso" "windows-11"]
+ Block2 --> Block3[build { sources } + provisioners]
+ end
+
+ subgraph Plugins["Plugins"]
+ Plugin[proxmox >= 1.1.0]
+ end
+
+ subgraph Sources["Source Settings"]
+ VM[VM Settings] --> HW[Hardware] --> Storage[Storage] --> Comm[Communicator]
+ end
+
+ PackerConfig --> Plugins
+ PackerConfig --> Sources
+```
+
+---
+
+## Full Configuration
+
+```hcl
+packer {
+ required_plugins {
+ proxmox = {
+ version = ">= 1.1.0"
+ source = "github.com/hashicorp/proxmox"
+ }
+ }
+}
+
+source "proxmox-iso" "windows-11" {
+ # === Connection ===
+ proxmox_url = "https://proxmox-host:8006/api2/json"
+ username = "root@pam"
+ password = "secret"
+ node = "la-vmh-07"
+
+ # === VM Settings ===
+ vm_name = "win11-ltsc-template"
+ template_description = "Built with Packer on ${timestamp()}"
+ iso_file = "local:iso/CLIENT_LTSC_EVAL_x64FRE_en-us.iso"
+
+ # === Hardware (Win11 Compliant) ===
+ qemu_agent = true
+ cores = 4
+ memory = 8192
+ machine = "q35"
+ bios = "ovmf"
+
+ # UEFI + TPM 2.0
+ efi_config {
+ efi_storage_pool = "local-lvm"
+ pre_enrolled_keys = true
+ }
+ tpm_config {
+ version = "2.0"
+ tpm_storage_pool = "local-lvm"
+ }
+
+ # === Storage ===
+ scsi_controller = "virtio-scsi-pci"
+ disks {
+ disk_size = "60G"
+ storage_pool = "local-lvm"
+ type = "virtio"
+ format = "raw"
+ cache_mode = "writeback"
+ }
+
+ # === Additional ISOs ===
+ additional_iso_files {
+ device = "sata1"
+ iso_file = "local:iso/virtio-win.iso"
+ }
+
+ # === Communicator (WinRM) ===
+ communicator = "winrm"
+ winrm_username = "Administrator"
+ winrm_password = "PackerPassword123!"
+ winrm_insecure = true
+ winrm_use_ssl = true
+
+ # === Boot Command ===
+ boot_command = [
+ "", "", "",
+ "", ""
+ ]
+ boot_wait = "10s"
+}
+
+build {
+ sources = ["source.proxmox-iso.windows-11"]
+
+ # === Provisioners ===
+ provisioner "powershell" {
+ inline = [
+ # Install VirtIO storage driver
+ "pnputil /add-driver 'E:\\viostor\\w11\\amd64\\*.inf' /install",
+ # Install VirtIO network driver
+ "pnputil /add-driver 'E:\\NetKVM\\w11\\amd64\\*.inf' /install",
+ # Install VirtIO guest tools
+ "& 'E:\\virtio-win-guest-tools.exe' /install /passive /norestart"
+ ]
+ }
+}
+```
+
+---
+
+## Section Details
+
+### Connection Settings
+
+| Setting | Value | Description |
+|---------|-------|-------------|
+| `proxmox_url` | `https://proxmox-host:8006/api2/json` | Proxmox API endpoint |
+| `username` | `root@pam` | Authentication user |
+| `password` | `secret` | Authentication password |
+| `node` | `la-vmh-07` | Target Proxmox node |
+
+### Hardware Configuration
+
+| Setting | Value | Notes |
+|---------|-------|-------|
+| `cores` | 4 | Windows 11 minimum |
+| `memory` | 8192 | 8 GB RAM |
+| `machine` | `q35` | Modern chipset |
+| `bios` | `ovmf` | UEFI firmware |
+
+### Storage Configuration
+
+| Setting | Value | Notes |
+|---------|-------|-------|
+| `disk_size` | 60G | 60 GB disk |
+| `storage_pool` | `local-lvm` | LVM storage |
+| `format` | `raw` | Raw disk format |
+
+### Boot Command
+
+```hcl
+boot_command = [
+ "", # Wait 30 seconds
+ "", # Press Enter (handle "Press any key")
+ "", # Confirm boot
+ "", # Continue installation
+ "" # Final confirmation
+]
+boot_wait = "10s" # Initial wait before sending commands
+```
+
+---
+
+## Provisioners
+
+### PowerShell Provisioner
+
+The PowerShell provisioner installs VirtIO drivers:
+
+```powershell
+# Install VirtIO storage driver
+pnputil /add-driver 'E:\viostor\w11\amd64\*.inf' /install
+
+# Install VirtIO network driver
+pnputil /add-driver 'E:\NetKVM\w11\amd64\*.inf' /install
+
+# Install VirtIO guest tools (silent)
+& 'E:\virtio-win-guest-tools.exe' /install /passive /norestart
+```
+
+---
+
+## Build Process
+
+```mermaid
+flowchart LR
+ subgraph BuildSteps["Packer Build Process"]
+ direction TB
+ Start[Start Build] --> Create[Create VM] --> MountISO[Mount ISO] --> Install[Windows Install] --> InstallDrivers[Install Drivers] --> Shutdown[Shutdown] --> Template[Convert to Template]
+ end
+
+ subgraph InstallActions["Windows Setup"]
+ Boot[Boot from ISO] --> WinSetup[Windows Setup] --> OOBE[OOBE - Autounattend.xml] --> Desktop[Desktop - WinRM Ready]
+ end
+
+ style BuildSteps fill:#e3f2fd
+ style InstallActions fill:#e8f5e9
+```
+
+---
+
+## Next Steps
+
+| Goal | Next Document |
+|------|---------------|
+| Configure Autounattend.xml | [Autounattend.xml Guide](autounattend.md) |
+| Build the template | Run `packer build windows.pkr.hcl` |
+| View Terraform | [OpenTofu Resources](../04-terraform/main.tf.md) |
+
+---
+
+[โ Documentation Index](../index.md) | [โ Autounattend.xml](autounattend.md) | [โ ISO Requirements](../02-prerequisites/isos.md)
diff --git a/docs/04-terraform/main.tf.md b/docs/04-terraform/main.tf.md
new file mode 100644
index 0000000..36437b5
--- /dev/null
+++ b/docs/04-terraform/main.tf.md
@@ -0,0 +1,223 @@
+# ๐๏ธ OpenTofu Resources
+
+[](https://opentofu.org/)
+[](https://www.proxmox.com/)
+
+## Overview
+
+OpenTofu provisions ephemeral Windows VMs from the Packer-built template. This document details the Terraform/OpenTofu configuration in [`terraform/main.tf`](../../terraform/main.tf).
+
+---
+
+## Configuration Structure
+
+```mermaid
+graph TD
+ subgraph OpenTofu["OpenTofu Configuration"]
+ direction TB
+ Provider[Provider Config] --> Resources[VM Resource] --> Clone[Clone Strategy] --> Output[VM IP Output]
+ end
+
+ subgraph ResourceParts["VM Resource Parts"]
+ Basic[Basic Settings] --> Hardware[CPU/Memory] --> Network[Network Config] --> Init[Cloud-Init/IP]
+ end
+
+ Provider --> Resources
+ Resources --> ResourceParts
+
+ style OpenTofu fill:#e3f2fd
+ style ResourceParts fill:#e8f5e9
+```
+
+---
+
+## Full Configuration
+
+```hcl
+terraform {
+ required_providers {
+ proxmox = {
+ source = "bpg/proxmox"
+ version = "0.46.1"
+ }
+ }
+}
+
+provider "proxmox" {
+ endpoint = "https://proxmox-host:8006/"
+ # Credentials injected via Environment Variables in Forgejo
+ # PM_API_TOKEN_ID and PM_API_TOKEN_SECRET
+}
+
+resource "proxmox_virtual_environment_vm" "build_agent" {
+ name = "ci-win-build-${var.build_id}"
+ node_name = "la-vmh-07"
+
+ clone {
+ # Packer template VM ID
+ vm_id = var.template_vm_id
+ full_clone = false
+ }
+
+ cpu {
+ cores = 4
+ type = "host"
+ }
+
+ memory {
+ dedicated = 8192
+ }
+
+ network_device {
+ bridge = "vmbr0"
+ }
+
+ initialization {
+ ip_config {
+ ipv4 {
+ address = "dhcp"
+ }
+ }
+ }
+}
+
+output "vm_ip" {
+ value = proxmox_virtual_environment_vm.build_agent.ipv4_addresses[1][0]
+ description = "IP address of the provisioned VM"
+}
+```
+
+---
+
+## Variables
+
+### Input Variables
+
+**File:** [`terraform/variables.tf`](../../terraform/variables.tf)
+
+```hcl
+variable "build_id" {
+ description = "Unique identifier for the build"
+ type = string
+}
+
+variable "template_vm_id" {
+ description = "VM ID of the Packer-built template"
+ type = number
+ default = 9000
+}
+```
+
+### Usage
+
+```bash
+export TF_VAR_build_id="123"
+export TF_VAR_template_vm_id="9000"
+tofu apply -auto-approve
+```
+
+---
+
+## Section Details
+
+### Provider Configuration
+
+| Setting | Value | Description |
+|---------|-------|-------------|
+| `endpoint` | `https://proxmox-host:8006/` | Proxmox API URL |
+| `source` | `bpg/proxmox` | Proxmox provider |
+| `version` | `0.46.1` | Provider version |
+
+### VM Clone Configuration
+
+| Setting | Value | Description |
+|---------|-------|-------------|
+| `vm_id` | `var.template_vm_id` | Template VM ID to clone |
+| `full_clone` | `false` | Fast linked clone |
+| `node_name` | `la-vmh-07` | Target Proxmox node |
+
+### Hardware Configuration
+
+| Setting | Value | Notes |
+|---------|-------|-------|
+| `cores` | 4 | CPU cores |
+| `type` | `host` | Host-passthrough CPU |
+| `dedicated` | 8192 | 8 GB dedicated RAM |
+
+### Network Configuration
+
+| Setting | Value | Notes |
+|---------|-------|-------|
+| `bridge` | `vmbr0` | Default Proxmox bridge |
+| `ip_config` | DHCP | Automatic IP assignment |
+
+---
+
+## Provisioning Process
+
+```mermaid
+flowchart LR
+ subgraph Process["OpenTofu Process"]
+ direction TB
+ Init[tofu init] --> Plan[tofu plan] --> Apply[tofu apply] --> Clone[Clone VM] --> Start[Start VM] --> IP[Get VM IP]
+ end
+
+ subgraph Template["Template"]
+ T[Template VM] --> |Clone| V[New VM]
+ end
+
+ Apply --> Template
+ V --> Start
+
+ style Process fill:#e3f2fd
+ style Template fill:#e8f5e9
+```
+
+---
+
+## Output
+
+```hcl
+output "vm_ip" {
+ value = proxmox_virtual_environment_vm.build_agent.ipv4_addresses[1][0]
+}
+```
+
+**Usage in pipeline:**
+```bash
+VM_IP=$(tofu output -raw vm_ip)
+echo "VM_IP=$VM_IP" >> $GITHUB_ENV
+```
+
+---
+
+## Environment Variables
+
+| Secret | Env Var | Purpose |
+|--------|---------|---------|
+| Proxmox Token ID | `PM_API_TOKEN_ID` | Authentication |
+| Proxmox Token Secret | `PM_API_TOKEN_SECRET` | Authentication |
+
+---
+
+## Troubleshooting
+
+| Issue | Cause | Solution |
+|-------|-------|----------|
+| Clone failed | Wrong VM ID | Check template VM ID in Proxmox |
+| No IP assigned | DHCP not working | Check network bridge |
+| Permission denied | Token lacks privileges | Add VM.Admin to token |
+
+---
+
+## Next Steps
+
+| Goal | Next Document |
+|------|---------------|
+| View variables | [Terraform Variables](variables.md) |
+| Run Ansible | [Ansible Pipeline](../05-ansible/pipeline.md) |
+| Run full pipeline | [Forgejo Workflows](../06-ci-cd/forgejo-workflows.md) |
+
+---
+
+[โ Documentation Index](../index.md) | [โ Variables](variables.md) | [โ Packer Autounattend](../03-packer/autounattend.md)
diff --git a/docs/04-terraform/variables.md b/docs/04-terraform/variables.md
new file mode 100644
index 0000000..b6a58ae
--- /dev/null
+++ b/docs/04-terraform/variables.md
@@ -0,0 +1,158 @@
+# ๐ Terraform Variables
+
+[](https://opentofu.org/)
+
+## Overview
+
+This document details all input variables for the OpenTofu configuration.
+
+---
+
+## Variables File
+
+**File:** [`terraform/variables.tf`](../../terraform/variables.tf)
+
+```hcl
+variable "build_id" {
+ description = "Unique identifier for the build"
+ type = string
+}
+
+variable "template_vm_id" {
+ description = "VM ID of the Packer-built template"
+ type = number
+ default = 9000
+}
+```
+
+---
+
+## Variable Details
+
+### build_id
+
+| Property | Value |
+|----------|-------|
+| Description | Unique identifier for the build |
+| Type | String |
+| Required | Yes |
+| Example | `"2024-02-06-001"` |
+
+**Purpose:** Creates unique VM names for each pipeline run, enabling parallel builds and preventing naming conflicts.
+
+```hcl
+# Generated VM name
+name = "ci-win-build-${var.build_id}"
+# Example: ci-win-build-2024-02-06-001
+```
+
+### template_vm_id
+
+| Property | Value |
+|----------|-------|
+| Description | VM ID of the Packer-built template |
+| Type | Number |
+| Default | `9000` |
+| Required | No |
+
+**Purpose:** Specifies which template to clone when provisioning VMs.
+
+```hcl
+# Default value
+vm_id = 9000
+
+# Custom value
+vm_id = var.template_vm_id
+```
+
+---
+
+## Setting Variables
+
+### Method 1: Environment Variables
+
+```bash
+export TF_VAR_build_id="123"
+export TF_VAR_template_vm_id="9000"
+tofu plan
+```
+
+### Method 2: tfvars File
+
+Create `terraform/terraform.tfvars`:
+
+```hcl
+build_id = "2024-02-06-001"
+template_vm_id = 9000
+```
+
+### Method 3: Command Line
+
+```bash
+tofu apply -var="build_id=123" -var="template_vm_id=9000"
+```
+
+---
+
+## Sensitive Variables
+
+| Variable | Sensitive | Reason |
+|----------|-----------|--------|
+| `build_id` | No | Public identifier |
+| `template_vm_id` | No | Configuration value |
+
+**Note:** Proxmox credentials are passed via environment variables, not variables file:
+- `PM_API_TOKEN_ID`
+- `PM_API_TOKEN_SECRET`
+
+---
+
+## Variable Validation
+
+```hcl
+variable "build_id" {
+ description = "Unique identifier for the build"
+ type = string
+
+ validation {
+ condition = can(regex("^[a-zA-Z0-9-_]+$", var.build_id))
+ error_message = "build_id must contain only alphanumeric characters, hyphens, and underscores."
+ }
+}
+
+variable "template_vm_id" {
+ description = "VM ID of the Packer-built template"
+ type = number
+
+ validation {
+ condition = var.template_vm_id >= 100 && var.template_vm_id <= 999999
+ error_message = "template_vm_id must be a valid VM ID (100-999999)."
+ }
+}
+```
+
+---
+
+## Best Practices
+
+| Practice | Description |
+|----------|-------------|
+| โ
Use descriptive names | `build_id` vs `id` |
+| โ
Set defaults | Provide safe defaults where possible |
+| โ
Add validation | Prevent invalid configurations |
+| โ
Document all variables | Clear description for each |
+| โ
Use type constraints | Enforce correct data types |
+
+---
+
+## Next Steps
+
+| Goal | Next Document |
+|------|---------------|
+| View main.tf | [OpenTofu Resources](main.tf.md) |
+| Run provisioning | Apply Terraform configuration |
+| View Ansible | [Ansible Pipeline](../05-ansible/pipeline.md) |
+
+---
+
+[โ Documentation Index](../index.md) | [โ OpenTofu Resources](main.tf.md) | [โ Ansible Pipeline](../05-ansible/pipeline.md)
diff --git a/docs/05-ansible/pipeline.md b/docs/05-ansible/pipeline.md
new file mode 100644
index 0000000..8bd8348
--- /dev/null
+++ b/docs/05-ansible/pipeline.md
@@ -0,0 +1,195 @@
+# โ
Ansible Pipeline
+
+[](https://www.ansible.com/)
+
+## Overview
+
+Ansible automates verification of the Windows installer on the provisioned VM. This document details the playbook in [`ansible/pipeline.yml`](../../ansible/pipeline.yml).
+
+---
+
+## Playbook Structure
+
+```mermaid
+flowchart TD
+ subgraph Playbook["Ansible Pipeline"]
+ direction TB
+ Play[Play: Verify Installer] --> Tasks[Tasks List]
+ Tasks --> T1[Create Workspace] --> T2[Upload Installer] --> T3[Install] --> T4[Verify] --> T5[Assert]
+ end
+
+ subgraph Hosts["Host Selection"]
+ H[windows_vm] --> Play
+ end
+
+ style Playbook fill:#e3f2fd
+ style Hosts fill:#e8f5e9
+```
+
+---
+
+## Full Playbook
+
+```yaml
+- name: Verify Installer
+ hosts: windows_vm
+ tasks:
+ - name: Create Workspace
+ ansible.windows.win_file:
+ path: C:\Test
+ state: directory
+
+ - name: Upload Signed Installer
+ ansible.windows.win_copy:
+ src: ./dist/installer_signed.exe
+ dest: C:\Test\installer.exe
+
+ - name: Install (Silent Mode)
+ ansible.windows.win_command: C:\Test\installer.exe /S
+ register: install_result
+
+ - name: Verify Executable Exists
+ ansible.windows.win_stat:
+ path: "C:\\Program Files\\MyApp\\app.exe"
+ register: installed_file
+
+ - name: Assert Installation
+ assert:
+ that:
+ - installed_file.stat.exists
+```
+
+---
+
+## Task Details
+
+### 1. Create Workspace
+
+```yaml
+- name: Create Workspace
+ ansible.windows.win_file:
+ path: C:\Test
+ state: directory
+```
+
+**Purpose:** Creates a directory for temporary files on the Windows VM.
+
+### 2. Upload Installer
+
+```yaml
+- name: Upload Signed Installer
+ ansible.windows.win_copy:
+ src: ./dist/installer_signed.exe
+ dest: C:\Test\installer.exe
+```
+
+**Purpose:** Copies the signed installer from the build host to the Windows VM.
+
+### 3. Silent Install
+
+```yaml
+- name: Install (Silent Mode)
+ ansible.windows.win_command: C:\Test\installer.exe /S
+ register: install_result
+```
+
+**Purpose:** Runs the installer in silent mode (`/S` flag).
+
+### 4. Verify Installation
+
+```yaml
+- name: Verify Executable Exists
+ ansible.windows.win_stat:
+ path: "C:\\Program Files\\MyApp\\app.exe"
+ register: installed_file
+```
+
+**Purpose:** Checks if the installed executable exists at the expected path.
+
+### 5. Assert Result
+
+```yaml
+- name: Assert Installation
+ assert:
+ that:
+ - installed_file.stat.exists
+```
+
+**Purpose:** Fails the pipeline if the executable is not found.
+
+---
+
+## Inventory Configuration
+
+### Dynamic Inventory
+
+The inventory is generated in the Forgejo workflow:
+
+```ini
+[windows_vm]
+ ansible_user=Administrator ansible_password= ansible_connection=winrm ansible_winrm_server_cert_validation=ignore
+```
+
+### Inventory Variables
+
+| Variable | Value | Purpose |
+|----------|-------|---------|
+| `ansible_user` | `Administrator` | Windows admin account |
+| `ansible_password` | From secret | WinRM password |
+| `ansible_connection` | `winrm` | Connection type |
+| `ansible_winrm_server_cert_validation` | `ignore` | Skip cert validation |
+
+---
+
+## Execution Flow
+
+```mermaid
+sequenceDiagram
+ participant Runner as Forgejo Runner
+ participant WinVM as Windows VM
+
+ Runner->>WinVM: Connect via WinRM
+ WinVM->>Runner: Connection established
+
+ Runner->>WinVM: Create C:\Test directory
+ WinVM->>Runner: Directory created
+
+ Runner->>WinVM: Upload installer_signed.exe
+ WinVM->>Runner: File uploaded
+
+ Runner->>WinVM: Execute installer.exe /S
+ WinVM->>Runner: Installation complete
+
+ Runner->>WinVM: Check app.exe exists
+ WinVM->>Runner: File found (or not)
+
+ alt File exists
+ Runner->>Runner: PASS - Continue pipeline
+ else File missing
+ Runner->>Runner: FAIL - Stop pipeline
+ end
+```
+
+---
+
+## Troubleshooting
+
+| Issue | Cause | Solution |
+|-------|-------|----------|
+| WinRM connection timeout | Firewall blocking | Disable Private firewall |
+| Credential rejected | Wrong password | Verify WIN_ADMIN_PASS |
+| File not found | Wrong path | Check installation path |
+
+---
+
+## Next Steps
+
+| Goal | Next Document |
+|------|---------------|
+| Run pipeline | [Forgejo Workflows](../06-ci-cd/forgejo-workflows.md) |
+| View Terraform | [OpenTofu Resources](../04-terraform/main.tf.md) |
+| Troubleshoot | [Troubleshooting](../07-advanced/troubleshooting.md) |
+
+---
+
+[โ Documentation Index](../index.md) | [โ Forgejo Workflows](../06-ci-cd/forgejo-workflows.md) | [โ Terraform Variables](../04-terraform/variables.md)
diff --git a/docs/06-ci-cd/forgejo-workflows.md b/docs/06-ci-cd/forgejo-workflows.md
new file mode 100644
index 0000000..433f3e0
--- /dev/null
+++ b/docs/06-ci-cd/forgejo-workflows.md
@@ -0,0 +1,288 @@
+# ๐ Forgejo Workflows
+
+[](https://forgejo.org/)
+[](.forgejo/workflows/release.yml)
+
+## Overview
+
+Forgejo Actions orchestrates the entire pipeline from code commit to verified artifact. This document details the workflow in [`.forgejo/workflows/release.yml`](../../.forgejo/workflows/release.yml).
+
+---
+
+## Workflow Structure
+
+```mermaid
+flowchart TB
+ subgraph Workflow["Forgejo Workflow"]
+ direction LR
+ Trigger[on: push] --> Job[build-sign-package]
+ Job --> Steps[6 Steps]
+ end
+
+ subgraph Steps["Job Steps"]
+ direction TB
+ Install[Install Tools] --> Checkout[Checkout] --> Compile[Cross-Compile] --> Package[Package] --> Sign[Sign] --> Provision[Provision VM] --> Verify[Verify] --> Cleanup[Cleanup]
+ end
+
+ style Workflow fill:#e3f2fd
+ style Steps fill:#e8f5e9
+```
+
+---
+
+## Full Workflow Configuration
+
+```yaml
+name: Build and Release
+on: [push]
+
+jobs:
+ build-sign-package:
+ runs-on: ubuntu-latest
+ container: archlinux:latest
+ steps:
+ - name: Install Tools
+ run: |
+ pacman -Syu --noconfirm \
+ mingw-w64-gcc \
+ nsis \
+ osslsigncode \
+ opentofu \
+ ansible \
+ python-pywinrm \
+ packer
+
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Cross-Compile (MinGW)
+ run: |
+ x86_64-w64-mingw32-gcc src/main.c -o dist/app.exe
+
+ - name: Package (NSIS)
+ run: |
+ makensis -DVERSION=${{ gitea.ref_name }} installer.nsi
+
+ - name: Code Sign (Linux Native)
+ env:
+ PFX_PASS: ${{ secrets.PFX_PASS }}
+ run: |
+ osslsigncode sign \
+ -pkcs12 cert.pfx \
+ -pass "$PFX_PASS" \
+ -t http://timestamp.digicert.com \
+ -in dist/installer.exe \
+ -out dist/installer_signed.exe
+
+ - name: Provision Windows VM (OpenTofu)
+ env:
+ PM_API_TOKEN_ID: ${{ secrets.PM_TOKEN_ID }}
+ PM_API_TOKEN_SECRET: ${{ secrets.PM_TOKEN_SECRET }}
+ TF_VAR_build_id: ${{ gitea.run_number }}
+ run: |
+ cd terraform
+ tofu init
+ tofu apply -auto-approve
+ echo "VM_IP=$(tofu output -raw vm_ip)" >> $GITHUB_ENV
+
+ - name: Verify on Windows (Ansible)
+ env:
+ ANSIBLE_USER: Administrator
+ ANSIBLE_PASSWORD: ${{ secrets.WIN_ADMIN_PASS }}
+ run: |
+ echo "[windows_vm]" > inventory.ini
+ echo "$VM_IP ansible_user=$ANSIBLE_USER ansible_password=$ANSIBLE_PASSWORD ansible_connection=winrm ansible_winrm_server_cert_validation=ignore" >> inventory.ini
+
+ ansible-playbook -i inventory.ini ansible/pipeline.yml
+
+ - name: Cleanup
+ if: always()
+ run: |
+ cd terraform
+ tofu destroy -auto-approve
+```
+
+---
+
+## Step-by-Step Breakdown
+
+### 1. Install Tools
+
+```bash
+pacman -Syu --noconfirm \
+ mingw-w64-gcc \ # MinGW cross-compiler
+ nsis \ # NSIS installer builder
+ osslsigncode \ # Code signing tool
+ opentofu \ # Infrastructure as code
+ ansible \ # Automation
+ python-pywinrm \ # Ansible WinRM support
+ packer \ # Image builder
+```
+
+### 2. Checkout
+
+```yaml
+- name: Checkout
+ uses: actions/checkout@v3
+```
+
+**Purpose:** Clones the repository to the container.
+
+### 3. Cross-Compile (MinGW)
+
+```bash
+x86_64-w64-mingw32-gcc src/main.c -o dist/app.exe
+```
+
+**Purpose:** Compiles Windows executable from Linux.
+
+### 4. Package (NSIS)
+
+```bash
+makensis -DVERSION=${{ gitea.ref_name }} installer.nsi
+```
+
+**Purpose:** Creates Windows installer from compiled executable.
+
+### 5. Code Sign
+
+```bash
+osslsigncode sign \
+ -pkcs12 cert.pfx \
+ -pass "$PFX_PASS" \
+ -t http://timestamp.digicert.com \
+ -in dist/installer.exe \
+ -out dist/installer_signed.exe
+```
+
+**Purpose:** Authenticode sign the installer with timestamp.
+
+### 6. Provision VM (OpenTofu)
+
+```bash
+cd terraform
+tofu init
+tofu apply -auto-approve
+echo "VM_IP=$(tofu output -raw vm_ip)" >> $GITHUB_ENV
+```
+
+**Purpose:** Creates ephemeral Windows VM for testing.
+
+### 7. Verify (Ansible)
+
+```bash
+echo "[windows_vm]" > inventory.ini
+echo "$VM_IP ansible_user=$ANSIBLE_USER ..." >> inventory.ini
+ansible-playbook -i inventory.ini ansible/pipeline.yml
+```
+
+**Purpose:** Tests installer on live Windows VM.
+
+### 8. Cleanup
+
+```bash
+if: always()
+tofu destroy -auto-approve
+```
+
+**Purpose:** Destroys VM regardless of test result.
+
+---
+
+## Container Configuration
+
+| Setting | Value | Description |
+|---------|-------|-------------|
+| `runs-on` | `ubuntu-latest` | Runner OS |
+| `container` | `archlinux:latest` | Build container |
+
+**Why Arch Linux?**
+- Latest packages available
+- Excellent AUR support
+- Small footprint
+- Easy package management
+
+---
+
+## Environment Variables
+
+### Set by Workflow
+
+| Variable | Source | Purpose |
+|----------|--------|---------|
+| `VM_IP` | OpenTofu output | Windows VM IP address |
+| `GITHUB_ENV` | Workflow | Store VM_IP for subsequent steps |
+
+### From Secrets
+
+| Secret | Env Var | Purpose |
+|--------|---------|---------|
+| `PFX_PASS` | `PFX_PASS` | Certificate password |
+| `PM_TOKEN_ID` | `PM_API_TOKEN_ID` | Proxmox authentication |
+| `PM_TOKEN_SECRET` | `PM_API_TOKEN_SECRET` | Proxmox authentication |
+| `WIN_ADMIN_PASS` | `ANSIBLE_PASSWORD` | WinRM connection |
+
+---
+
+## Pipeline Flow Diagram
+
+```mermaid
+flowchart TB
+ subgraph Build["Build Stage"]
+ direction LR
+ Install[Install Tools] --> Checkout[Checkout] --> Compile[Cross-Compile] --> Package[Package] --> Sign[Sign]
+ end
+
+ subgraph Deploy["Deploy Stage"]
+ Sign --> Provision[Provision VM] --> Verify[Ansible Verify]
+ end
+
+ subgraph Cleanup["Cleanup Stage"]
+ Verify --> Destroy[Destroy VM]
+ end
+
+ style Build fill:#e3f2fd
+ style Deploy fill:#e8f5e9
+ style Cleanup fill:#fff3e0
+```
+
+---
+
+## Triggering the Pipeline
+
+| Trigger | Description |
+|---------|-------------|
+| `on: push` | Runs on any push to any branch |
+| `on: [push, pull_request]` | Also run on PRs (optional) |
+
+### Manual Trigger
+
+```bash
+git commit -m "Update installer"
+git push
+```
+
+---
+
+## Troubleshooting
+
+| Issue | Cause | Solution |
+|-------|-------|----------|
+| Container missing packages | Pacman cache | Clear cache or use specific versions |
+| OpenTofu init fails | Provider issues | Run `tofu init -upgrade` |
+| Ansible connection timeout | WinRM not ready | Check Autounattend.xml |
+| Cleanup failed | VM already destroyed | Add `if: failure()` condition |
+
+---
+
+## Next Steps
+
+| Goal | Next Document |
+|------|---------------|
+| View architecture | [Architecture Overview](../01-overview/architecture.md) |
+| Troubleshoot | [Troubleshooting](../07-advanced/troubleshooting.md) |
+| Manage evaluations | [Evaluation Management](../07-advanced/evaluation.md) |
+
+---
+
+[โ Documentation Index](../index.md) | [โ Advanced Topics](../07-advanced/) | [โ Ansible Pipeline](../05-ansible/pipeline.md)
diff --git a/docs/07-advanced/evaluation.md b/docs/07-advanced/evaluation.md
new file mode 100644
index 0000000..af0f653
--- /dev/null
+++ b/docs/07-advanced/evaluation.md
@@ -0,0 +1,200 @@
+# โฐ 90-Day Evaluation Management
+
+[](https://www.microsoft.com/en-us/evalcenter/)
+
+## Overview
+
+Windows Evaluation editions expire after 90 days. This document explains the expiration mechanism and provides strategies for managing it in your automation pipeline.
+
+---
+
+## Understanding Evaluation Expiration
+
+```mermaid
+flowchart LR
+ subgraph Timeline["90-Day Timeline"]
+ Start[Install Day 0] --> Day30[Day 30] --> Day60[Day 60] --> Day90[Day 90 - Expiration]
+ end
+
+ subgraph States["System States"]
+ Active[โ
Active] --> Warning[โ ๏ธ Warning 15 days] --> Expired[โ Expired]
+ end
+
+ Timeline --> States
+
+ style Timeline fill:#e3f2fd
+ style States fill:#e8f5e9
+```
+
+| Phase | Duration | Status |
+|-------|----------|--------|
+| **Full Activation** | Days 0-89 | โ
Fully functional |
+| **Warning Period** | Days 90-104 | โ ๏ธ Countdown warnings |
+| **Grace Period** | Days 105-180 | โณ Extended grace |
+| **Expired** | Day 181+ | โ System stops |
+
+---
+
+## Expiration Methods
+
+### Method 1: Rearm (Manual/Scripted)
+
+The `slmgr /rearm` command resets the activation timer.
+
+```powershell
+# Run as Administrator
+slmgr /rearm
+
+# Reboot required
+shutdown /r /t 0
+```
+
+**Limits:**
+- Maximum 3 rearm attempts per installation
+- Each rearm resets to 90 days
+- **Total: 360 days maximum**
+
+### Method 2: Packer Rebuild (Recommended)
+
+The recommended approach is to **rebuild the golden image monthly**.
+
+```mermaid
+flowchart TB
+ subgraph Monthly["Monthly Schedule"]
+ direction LR
+ Week1[Week 1: Packer Build] --> Week2[Week 2-4: Use Template]
+ end
+
+ subgraph Process["Rebuild Process"]
+ Destroy[Destroy Old Template] --> Create[Create New Template] --> Verify[Test New Template]
+ end
+
+ Monthly --> Process
+
+ style Monthly fill:#e3f2fd
+ style Process fill:#e8f5e9
+```
+
+**Benefits:**
+- Fresh timer each month
+- Latest Windows updates baked in
+- Consistent baseline
+- No rearm limitations
+
+---
+
+## Implementation Strategy
+
+### Automated Monthly Rebuild
+
+Configure a scheduled workflow in Forgejo:
+
+```yaml
+# .forgejo/workflows/monthly-rebuild.yml
+name: Monthly Template Rebuild
+on:
+ schedule:
+ - cron: '0 0 1 * *' # First day of each month at midnight
+
+jobs:
+ rebuild-template:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Build New Template
+ run: |
+ cd packer
+ packer build -timestamp-ui windows.pkr.hcl
+
+ - name: Cleanup Old Template
+ run: |
+ # Script to remove template older than 45 days
+ ./scripts/cleanup-old-templates.sh --older-than 45d
+```
+
+### Rebarm as Backup
+
+For emergency extension:
+
+```powershell
+# emergency-rearm.ps1
+# Run via Ansible or manually
+
+if ((slmgr /dlv) -match "Remaining: 0") {
+ Write-Host "Rearming system..."
+ slmgr /rearm
+ shutdown /r /t 0
+} else {
+ Write-Host "Not yet expired, no action needed"
+}
+```
+
+---
+
+## Monitoring Expiration
+
+### Check Current Status
+
+```powershell
+# Method 1: slmgr
+slmgr /dlv
+
+# Method 2: PowerShell
+(Get-CimInstance -Query "SELECT * FROM SoftwareLicensingProduct WHERE PartialProductKey IS NOT NULL").RemainingGracePeriod
+```
+
+### Automated Monitoring Script
+
+```bash
+#!/bin/bash
+# check-expiration.sh - Run via Ansible monthly
+
+VM_ID="9000"
+PROXMOX_HOST="la-vmh-07"
+
+# Get VM's Windows activation status
+ssh root@$PROXMOX_HOST "qm agent $VM_ID exec-win32 powershell -Command '(Get-CimInstance -Query \"SELECT * FROM SoftwareLicensingProduct WHERE PartialProductKey IS NOT NULL\").RemainingGracePeriod'"
+
+# Alert if less than 7 days
+if [ $DAYS_REMAINING -lt 7 ]; then
+ echo "โ ๏ธ ALERT: Template expires in $DAYS_REMAINING days"
+ # Send notification
+fi
+```
+
+---
+
+## Best Practices
+
+| Practice | Description | Priority |
+|----------|-------------|----------|
+| **Monthly rebuild** | Schedule automatic Packer build | ๐ด High |
+| **Monitor expiration** | Check status weekly | ๐ก Medium |
+| **Test new templates** | Verify before production use | ๐ด High |
+| **Document rebuilds** | Log template versions | ๐ข Low |
+
+---
+
+## Troubleshooting
+
+| Issue | Cause | Solution |
+|-------|-------|----------|
+| Rearm failed | Already rearmed 3 times | Rebuild with Packer |
+| VM won't boot after rearm | Activation issues | Rebuild template |
+| Updates not installing | WSUS offline | Include updates in Packer build |
+
+---
+
+## Next Steps
+
+| Goal | Next Document |
+|------|---------------|
+| View troubleshooting | [Troubleshooting](troubleshooting.md) |
+| Configure pipeline | [Forgejo Workflows](../06-ci-cd/forgejo-workflows.md) |
+| View architecture | [Architecture Overview](../01-overview/architecture.md) |
+
+---
+
+[โ Documentation Index](../index.md) | [โ Troubleshooting](troubleshooting.md) | [โ Forgejo Workflows](../06-ci-cd/forgejo-workflows.md)
diff --git a/docs/07-advanced/troubleshooting.md b/docs/07-advanced/troubleshooting.md
new file mode 100644
index 0000000..756a660
--- /dev/null
+++ b/docs/07-advanced/troubleshooting.md
@@ -0,0 +1,273 @@
+# ๐ง Troubleshooting Guide
+
+[]()
+
+## Overview
+
+This guide covers common issues and their solutions for the Windows automation pipeline.
+
+---
+
+## Quick Fix Index
+
+| Issue | Phase | Quick Fix |
+|-------|-------|-----------|
+| Packer timeout | Build | Check Autounattend.xml WinRM config |
+| VM won't boot | Provision | Verify ISO paths in Packer |
+| Ansible connection | Test | Disable Windows firewall |
+| Code signing fails | Build | Verify PFX password |
+| Template expired | All | Rebuild with Packer |
+
+---
+
+## Phase 1: Packer Issues
+
+### Timeout Waiting for WinRM
+
+**Symptom:**
+```
+==> proxmox-iso.windows-11: Timeout waiting for WinRM.
+```
+
+**Cause:** Windows not fully booted or WinRM not configured.
+
+**Solution:**
+1. Verify `Autounattend.xml` has WinRM configuration
+2. Check boot command timing
+3. Increase `boot_wait` duration
+
+```hcl
+# Increase boot wait
+boot_wait = "30s"
+
+# Check boot command
+boot_command = [
+ "",
+ "",
+ ""
+]
+```
+
+---
+
+### ISO Not Found
+
+**Symptom:**
+```
+==> proxmox-iso.windows-iso: ISO file not found: local:iso/...
+```
+
+**Cause:** Wrong ISO path or storage.
+
+**Solution:**
+1. Verify ISO location on Proxmox
+2. Check storage name (local vs local-lvm)
+
+```bash
+# On Proxmox host
+ls -la /mnt/pve-07-iso-nvme/template/iso/
+qm storage
+```
+
+---
+
+## Phase 2: OpenTofu Issues
+
+### Clone Failed
+
+**Symptom:**
+```
+Error: resource is not a cloneable VM
+```
+
+**Cause:** Wrong VM ID or template not found.
+
+**Solution:**
+1. Verify template VM exists
+2. Check VM ID is correct
+
+```bash
+# On Proxmox host
+qm list | grep template
+```
+
+---
+
+### Permission Denied
+
+**Symptom:**
+```
+Error: permission denied (400)
+```
+
+**Cause:** Proxmox API token lacks privileges.
+
+**Solution:**
+1. Add VM.Admin role to token
+2. Verify token is not expired
+
+---
+
+## Phase 3: Ansible Issues
+
+### WinRM Connection Timeout
+
+**Symptom:**
+```
+fatal: [10.0.0.5]: UNREACHABLE! => {"msg": "Connection timeout"}
+```
+
+**Cause:** Firewall blocking WinRM or WinRM not configured.
+
+**Solution:**
+```yaml
+# In Autounattend.xml - disable firewall
+
+ powershell -Command "Set-NetFirewallProfile -Profile Private -Enabled False"
+ 1
+
+
+# In inventory - ignore certificate validation
+[windows_vm]
+10.0.0.5 ansible_winrm_server_cert_validation=ignore
+```
+
+---
+
+### Invalid Credentials
+
+**Symptom:**
+```
+fatal: [10.0.0.5]: UNREACHABLE! => {"msg": "Basic auth failed"}
+```
+
+**Cause:** Wrong username or password.
+
+**Solution:**
+```bash
+# Verify secrets are set
+echo $WIN_ADMIN_PASS
+
+# Test manually
+winrs -r:10.0.0.5 -u:Administrator -p:$WIN_ADMIN_PASS "hostname"
+```
+
+---
+
+## Phase 4: Code Signing Issues
+
+### Invalid Certificate
+
+**Symptom:**
+```
+Error: PKCS12_parse failed
+```
+
+**Cause:** Wrong password or corrupted PFX file.
+
+**Solution:**
+```bash
+# Verify certificate
+openssl pkcs12 -in cert.pfx -info -noout -passin pass:$PFX_PASS
+```
+
+---
+
+## Diagnostic Commands
+
+### Proxmox Diagnostics
+
+```bash
+# List VMs
+qm list
+
+# Check VM status
+qm status
+
+# View VM config
+qm config
+
+# Check storage
+pvesm status
+```
+
+### Windows Diagnostics
+
+```powershell
+# Check WinRM status
+winrm quickconfig
+Get-WinRM -Service
+
+# Check firewall
+Get-NetFirewallProfile | Select Name, Enabled
+
+# Check activation
+slmgr /dlv
+```
+
+### Ansible Diagnostics
+
+```bash
+# Test WinRM connection
+ansible windows_vm -m win_ping -i inventory.ini
+
+# Verbose output
+ansible-playbook -i inventory.ini pipeline.yml -vvvv
+```
+
+---
+
+## Log Locations
+
+| Component | Log Location |
+|-----------|--------------|
+| Packer | Console output + `packer.log` |
+| OpenTofu | Console output + `.terraform.lock.hcl` |
+| Ansible | Console output + `/var/log/ansible.log` |
+| Windows | Event Viewer โ System |
+
+---
+
+## FAQ
+
+### Q: Can I use a different Windows edition?
+
+**A:** Yes, but you need to:
+1. Update ISO in `packer/windows.pkr.hcl`
+2. Modify `Autounattend.xml` for that edition
+3. Update product key settings
+
+### Q: How do I add more software to the template?
+
+**A:** Add PowerShell provisioners:
+
+```hcl
+provisioner "powershell" {
+ inline = [
+ "choco install -y 7zip git vscode",
+ "& 'C:\\ProgramData\\Chocolatey\\bin\\choco.exe' install -y dotnetfx"
+ ]
+}
+```
+
+### Q: The VM has no IP after provisioning
+
+**Cause:** DHCP not working or VirtIO drivers missing.
+
+**Solution:**
+1. Ensure VirtIO drivers are installed in template
+2. Verify network bridge is correct
+
+---
+
+## Next Steps
+
+| Goal | Next Document |
+|------|---------------|
+| Manage evaluations | [Evaluation Management](evaluation.md) |
+| View pipeline | [Forgejo Workflows](../06-ci-cd/forgejo-workflows.md) |
+| Full documentation | [Documentation Index](../index.md) |
+
+---
+
+[โ Documentation Index](../index.md) | [โ Evaluation Management](evaluation.md) | [โ Home](../index.md)
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..5871e3d
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,258 @@
+# ๐ Documentation Index
+
+
+[](.forgejo/workflows/release.yml)
+[](https://www.microsoft.com/en-us/windows/windows-11-enterprise)
+
+## Welcome
+
+This is the comprehensive documentation index for the **Windows Automation on Proxmox** project. Use this guide to navigate through all available documentation.
+
+---
+
+## ๐๏ธ Documentation Map
+
+```
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+โ DOCUMENTATION TREE โ
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
+โ โ
+โ ๐ index.md (You are here) โ
+โ โโโ ๐ 01-overview/ โ
+โ โ โโโ ๐ architecture.md โ
+โ โ โโโ System Components โ
+โ โ โโโ Architecture Diagrams โ
+โ โ โโโ Design Decisions โ
+โ โ โ
+โ โโโ ๐ 02-prerequisites/ โ
+โ โ โโโ ๐ isos.md โ
+โ โ โ โโโ ISO Download Sources โ
+โ โ โ โโโ Storage Location โ
+โ โ โ โโโ Verification Steps โ
+โ โ โ โ
+โ โ โโโ ๐ secrets.md โ
+โ โ โโโ Forgejo Secrets โ
+โ โ โโโ Proxmox API Tokens โ
+โ โ โโโ Certificate Management โ
+โ โ โ
+โ โโโ ๐ 03-packer/ โ
+โ โ โโโ ๐ configuration.md โ
+โ โ โ โโโ Packer HCL Syntax โ
+โ โ โ โโโ Proxmox Builder Settings โ
+โ โ โ โโโ Provisioner Configuration โ
+โ โ โ โ
+โ โ โโโ ๐ autounattend.md โ
+โ โ โโโ XML Structure โ
+โ โ โโโ WinRM Configuration โ
+โ โ โโโ FirstLogonCommands โ
+โ โ โ
+โ โโโ ๐ 04-terraform/ โ
+โ โ โโโ ๐ main.tf.md โ
+โ โ โ โโโ Provider Configuration โ
+โ โ โ โโโ VM Resource Definition โ
+โ โ โ โโโ Clone Strategy โ
+โ โ โ โ
+โ โ โโโ ๐ variables.md โ
+โ โ โโโ Input Variables โ
+โ โ โโโ Variable Validation โ
+โ โ โ
+โ โโโ ๐ 05-ansible/ โ
+โ โ โโโ ๐ pipeline.md โ
+โ โ โโโ Playbook Structure โ
+โ โ โโโ WinRM Setup โ
+โ โ โโโ Verification Tasks โ
+โ โ โ
+โ โโโ ๐ 06-ci-cd/ โ
+โ โ โโโ ๐ forgejo-workflows.md โ
+โ โ โโโ Workflow Syntax โ
+โ โ โโโ Container Configuration โ
+โ โ โโโ Step-by-Step Execution โ
+โ โ โโโ Environment Variables โ
+โ โ โ
+โ โโโ ๐ 07-advanced/ โ
+โ โโโ ๐ evaluation.md โ
+โ โ โโโ 90-Day Timer Management โ
+โ โ โโโ Rearm Procedure โ
+โ โ โโโ Monthly Rebuild Strategy โ
+โ โ โ
+โ โโโ ๐ troubleshooting.md โ
+โ โโโ Common Errors โ
+โ โโโ Debug Techniques โ
+โ โโโ FAQ โ
+โ โ
+โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+```
+
+---
+
+## ๐ฏ Quick Navigation
+
+### I want to...
+
+| Goal | Start Here |
+|------|------------|
+| **Understand the system** | [Architecture Overview](01-overview/architecture.md) |
+| **Set up prerequisites** | [ISO Requirements](02-prerequisites/isos.md) |
+| **Build the golden image** | [Packer Configuration](03-packer/configuration.md) |
+| **Provision test VMs** | [OpenTofu Resources](04-terraform/main.tf.md) |
+| **Run the CI/CD pipeline** | [Forgejo Workflows](06-ci-cd/forgejo-workflows.md) |
+| **Troubleshoot issues** | [Troubleshooting Guide](07-advanced/troubleshooting.md) |
+
+---
+
+## ๐ Architecture Overview
+
+```mermaid
+graph TD
+ subgraph CI["Forgejo CI/CD"]
+ direction LR
+ Git[Git Push] --> |Triggers| WF[Workflow]
+ WF --> |Cross-Compile| MC[MinGW]
+ WF --> |Package| NS[NSIS]
+ WF --> |Sign| CS[Code Sign]
+ end
+
+ subgraph Infra["Infrastructure"]
+ CS --> |Provision| TF[OpenTofu]
+ TF --> |Clone| VM[Windows VM]
+ end
+
+ subgraph Test["Testing"]
+ VM --> |Deploy| Inst[Installer]
+ Inst --> |Verify| Ans[Ansible]
+ Ans --> |Result| Pass{โ
Pass}
+ Ans --> |Result| Fail{โ Fail}
+ end
+
+ style CI fill:#e1f5fe
+ style Infra fill:#e8f5e9
+ style Test fill:#fff3e0
+```
+
+---
+
+## ๐ Section Descriptions
+
+### 01. Overview
+- **[architecture.md](01-overview/architecture.md)** - Complete system design including:
+ - Component overview
+ - Data flow diagrams
+ - Design decisions and rationale
+ - Technology stack explanation
+
+### 02. Prerequisites
+- **[isos.md](02-prerequisites/isos.md)** - ISO image requirements:
+ - Download links for Windows ISOs
+ - VirtIO driver sources
+ - Proxmox storage configuration
+ - File verification steps
+- **[secrets.md](02-prerequisites/secrets.md)** - Credential management:
+ - Forgejo secret configuration
+ - Proxmox API token creation
+ - Code signing certificate handling
+ - Environment variable mapping
+
+### 03. Packer
+- **[configuration.md](03-packer/configuration.md)** - Packer template guide:
+ - HCL syntax reference
+ - Proxmox builder settings
+ - Hardware configuration
+ - Provisioner scripts
+- **[autounattend.md](03-packer/autounattend.md)** - Windowsๆ ไบบๅผๅฎๅฎ่ฃ
:
+ - XML structure reference
+ - WinRM enabling
+ - Firewall configuration
+ - FirstLogonCommands่ฏฆ่งฃ
+
+### 04. Terraform/OpenTofu
+- **[main.tf.md](04-terraform/main.tf.md)** - Infrastructure as code:
+ - Provider configuration
+ - VM cloning strategy
+ - Network settings
+ - IP address assignment
+- **[variables.md](04-terraform/variables.md)** - Variables reference:
+ - Input variable definitions
+ - Default values
+ - Variable validation
+ - Sensitive value handling
+
+### 05. Ansible
+- **[pipeline.md](05-ansible/pipeline.md)** - Automation playbook:
+ - WinRM connection setup
+ - File transfer tasks
+ - Silent installation
+ - Verification assertions
+ - Error handling
+
+### 06. CI/CD
+- **[forgejo-workflows.md](06-ci-cd/forgejo-workflows.md)** - Pipeline configuration:
+ - Workflow syntax
+ - Container images
+ - Step-by-step execution
+ - Artifact publishing
+ - Cleanup procedures
+
+### 07. Advanced
+- **[evaluation.md](07-advanced/evaluation.md)** - Evaluation management:
+ - 90-day expiration explained
+ - Rearm procedure
+ - Automated rebuild strategy
+ - Security considerations
+- **[troubleshooting.md](07-advanced/troubleshooting.md)** - Problem resolution:
+ - Common error messages
+ - Debug commands
+ - Log file locations
+ - FAQ section
+
+---
+
+## ๐ Cross-References
+
+This documentation is fully interlinked. Key cross-references include:
+
+| From | To | Context |
+|------|-----|---------|
+| README | docs/index.md | Documentation entry |
+| architecture.md | isos.md | Prerequisites section |
+| configuration.md | autounattend.md | Related Packer topics |
+| main.tf.md | variables.md | Terraform variables |
+| forgejo-workflows.md | pipeline.md | Ansible integration |
+| pipeline.md | main.tf.md | Infrastructure reference |
+| troubleshooting.md | All sections | Problem resolution |
+
+---
+
+## ๐ ๏ธ Tool Reference
+
+| Tool | Version | Purpose | Docs Link |
+|------|---------|---------|-----------|
+| Packer | โฅ 1.1.0 | Image building | [configuration.md](03-packer/configuration.md) |
+| OpenTofu | Latest | IaC provisioning | [main.tf.md](04-terraform/main.tf.md) |
+| Ansible | Latest | Automation | [pipeline.md](05-ansible/pipeline.md) |
+| Forgejo Actions | Latest | CI/CD | [forgejo-workflows.md](06-ci-cd/forgejo-workflows.md) |
+| MinGW | Latest | Cross-compilation | [forgejo-workflows.md](06-ci-cd/forgejo-workflows.md) |
+| NSIS | Latest | Installer creation | [forgejo-workflows.md](06-ci-cd/forgejo-workflows.md) |
+
+---
+
+## ๐ Reading Guide
+
+1. **First Time Setup:** Read in order: 01 โ 02 โ 03 โ 04 โ 05 โ 06
+2. **Specific Task:** Use the Quick Navigation table above
+3. **Deep Dive:** Follow cross-references from any section
+4. **Troubleshooting:** Start with [troubleshooting.md](07-advanced/troubleshooting.md)
+
+---
+
+## ๐ Document Version
+
+| Property | Value |
+|----------|-------|
+| Version | 1.0.0 |
+| Last Updated | February 2026 |
+| Target OS | Windows 11 LTSC 2024 |
+| Status | Active Development |
+
+---
+
+[โ Back to README](../README.md) | [โ Architecture Overview](01-overview/architecture.md)
diff --git a/installer.nsi b/installer.nsi
new file mode 100644
index 0000000..de6157f
--- /dev/null
+++ b/installer.nsi
@@ -0,0 +1,22 @@
+!define APP_NAME "MyApp"
+!define APP_VERSION ${VERSION}
+!define COMPANY_NAME "My Company"
+
+OutFile "dist\installer.exe"
+InstallDir "$PROGRAMFILES\${APP_NAME}"
+RequestExecutionLevel admin
+
+Page directory
+Page instfiles
+
+Section "MainSection"
+ SetOutPath $INSTDIR
+ File "dist\app.exe"
+ WriteUninstaller $INSTDIR\uninstall.exe
+SectionEnd
+
+Section "Uninstall"
+ Delete $INSTDIR\app.exe
+ Delete $INSTDIR\uninstall.exe
+ RMDir $INSTDIR
+SectionEnd
diff --git a/packer/Autounattend.xml b/packer/Autounattend.xml
new file mode 100644
index 0000000..df236a2
--- /dev/null
+++ b/packer/Autounattend.xml
@@ -0,0 +1,71 @@
+
+
+
+
+
+ en-US
+
+ en-US
+ en-US
+ en-US
+ en-US
+
+
+
+
+
+
+ true
+
+
+
+
+
+ *
+
+
+ en-US
+ en-US
+ en-US
+ en-US
+
+
+ false
+
+
+ false
+
+
+
+
+
+ true
+ true
+ true
+ false
+ 3
+
+
+
+ PackerPassword123!
+ true
+
+
+
+ true
+ Administrator
+ 1
+
+
+
+ powershell -Command "Set-NetFirewallProfile -Profile Private -Enabled False"
+ 1
+
+
+ powershell -Command "Invoke-WebRequest -Uri https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1 -OutFile C:\ConfigureRemotingForAnsible.ps1; C:\ConfigureRemotingForAnsible.ps1"
+ 2
+
+
+
+
+
diff --git a/packer/windows.pkr.hcl b/packer/windows.pkr.hcl
new file mode 100644
index 0000000..a8a1d87
--- /dev/null
+++ b/packer/windows.pkr.hcl
@@ -0,0 +1,70 @@
+packer {
+ required_plugins {
+ proxmox = {
+ version = ">= 1.1.0"
+ source = "github.com/hashicorp/proxmox"
+ }
+ }
+}
+
+source "proxmox-iso" "windows-11" {
+ proxmox_url = "https://proxmox-host:8006/api2/json"
+ username = "root@pam"
+ password = "secret"
+ node = "la-vmh-07"
+
+ vm_name = "win11-ltsc-template"
+ template_description = "Built with Packer on ${timestamp()}"
+ iso_file = "local:iso/CLIENT_LTSC_EVAL_x64FRE_en-us.iso"
+
+ qemu_agent = true
+ cores = 4
+ memory = 8192
+ machine = "q35"
+ bios = "ovmf"
+ efi_config {
+ efi_storage_pool = "local-lvm"
+ pre_enrolled_keys = true
+ }
+ tpm_config {
+ version = "2.0"
+ tpm_storage_pool = "local-lvm"
+ }
+
+ scsi_controller = "virtio-scsi-pci"
+ disks {
+ disk_size = "60G"
+ storage_pool = "local-lvm"
+ type = "virtio"
+ format = "raw"
+ cache_mode = "writeback"
+ }
+ additional_iso_files {
+ device = "sata1"
+ iso_file = "local:iso/virtio-win.iso"
+ }
+
+ communicator = "winrm"
+ winrm_username = "Administrator"
+ winrm_password = "PackerPassword123!"
+ winrm_insecure = true
+ winrm_use_ssl = true
+
+ boot_command = [
+ "","","",
+ "",""
+ ]
+ boot_wait = "10s"
+}
+
+build {
+ sources = ["source.proxmox-iso.windows-11"]
+
+ provisioner "powershell" {
+ inline = [
+ "pnputil /add-driver 'E:\\viostor\\w11\\amd64\\*.inf' /install",
+ "pnputil /add-driver 'E:\\NetKVM\\w11\\amd64\\*.inf' /install",
+ "& 'E:\\virtio-win-guest-tools.exe' /install /passive /norestart"
+ ]
+ }
+}
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..3920ac8
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,7 @@
+#include
+#include
+
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
+ MessageBoxA(NULL, "Hello from MyApp!", "MyApp", MB_OK | MB_ICONINFORMATION);
+ return 0;
+}
diff --git a/terraform/main.tf b/terraform/main.tf
new file mode 100644
index 0000000..315e11d
--- /dev/null
+++ b/terraform/main.tf
@@ -0,0 +1,34 @@
+terraform {
+ required_providers {
+ proxmox = {
+ source = "bpg/proxmox"
+ version = "0.46.1"
+ }
+ }
+}
+
+provider "proxmox" {
+ endpoint = "https://proxmox-host:8006/"
+}
+
+resource "proxmox_virtual_environment_vm" "build_agent" {
+ name = "ci-win-build-${var.build_id}"
+ node_name = "la-vmh-07"
+
+ clone {
+ vm_id = var.template_vm_id
+ full_clone = false
+ }
+
+ cpu { cores = 4; type = "host" }
+ memory { dedicated = 8192 }
+ network_device { bridge = "vmbr0" }
+
+ initialization {
+ ip_config {
+ ipv4 {
+ address = "dhcp"
+ }
+ }
+ }
+}
diff --git a/terraform/outputs.tf b/terraform/outputs.tf
new file mode 100644
index 0000000..b59c5c4
--- /dev/null
+++ b/terraform/outputs.tf
@@ -0,0 +1,4 @@
+output "vm_ip" {
+ description = "IP address of the provisioned VM"
+ value = proxmox_virtual_environment_vm.build_agent.ipv4_addresses[1][0]
+}
diff --git a/terraform/variables.tf b/terraform/variables.tf
new file mode 100644
index 0000000..1be0d02
--- /dev/null
+++ b/terraform/variables.tf
@@ -0,0 +1,10 @@
+variable "build_id" {
+ description = "Unique identifier for the build"
+ type = string
+}
+
+variable "template_vm_id" {
+ description = "VM ID of the Packer-built template"
+ type = number
+ default = 9000
+}