feat: Add professional hierarchical documentation
Some checks are pending
Build and Release / build-sign-package (push) Waiting to run
Some checks are pending
Build and Release / build-sign-package (push) Waiting to run
- Created comprehensive README.md with Mermaid diagrams, badges, and TOC - Added docs/ directory with 7 sections and 14 markdown files - Included architecture diagrams, flowcharts, and sequence diagrams - All documentation is fully interlinked with cross-references - Added ISO storage location on Proxmox development server - Included troubleshooting guide and evaluation management docs - All config files (Packer, Terraform, Ansible, Forgejo) documented - Added icons and visual elements throughout documentation
This commit is contained in:
parent
faf04d69f8
commit
e4f03427b7
24 changed files with 3844 additions and 2 deletions
234
docs/01-overview/architecture.md
Normal file
234
docs/01-overview/architecture.md
Normal file
|
|
@ -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<br/>MinGW] --> Package[Package<br/>NSIS] --> Sign[Code Sign<br/>osslsigncode]
|
||||
end
|
||||
|
||||
subgraph Infrastructure["Proxmox Infrastructure"]
|
||||
Template[Windows Template<br/>Packer Built] --> Clone[Clone VM<br/>OpenTofu] --> TestVM[Test VM<br/>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)
|
||||
182
docs/02-prerequisites/isos.md
Normal file
182
docs/02-prerequisites/isos.md
Normal file
|
|
@ -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)
|
||||
224
docs/02-prerequisites/secrets.md
Normal file
224
docs/02-prerequisites/secrets.md
Normal file
|
|
@ -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: <YOUR_SECRET_VALUE>
|
||||
```
|
||||
|
||||
### Set Environment Variables
|
||||
|
||||
```bash
|
||||
# In Forgejo workflow or local environment
|
||||
export PM_API_TOKEN_ID="root@pam!forgejo-automation"
|
||||
export PM_API_TOKEN_SECRET="<your-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
|
||||
<UserAccounts>
|
||||
<AdministratorPassword>
|
||||
<Value>PackerPassword123!</Value>
|
||||
<PlainText>true</PlainText>
|
||||
</AdministratorPassword>
|
||||
</UserAccounts>
|
||||
```
|
||||
|
||||
### 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)
|
||||
238
docs/03-packer/autounattend.md
Normal file
238
docs/03-packer/autounattend.md
Normal file
|
|
@ -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[<unattend>] --> WindowsPE["pass='windowsPE'"] --> Specialize["pass='specialize'"]
|
||||
Specialize --> OOBE["pass='oobeSystem'"] --> UserAccounts["<UserAccounts>"]
|
||||
OOBE --> AutoLogon["<AutoLogon>"] --> FirstLogon["<FirstLogonCommands>"]
|
||||
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
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<unattend xmlns="urn:schemas-microsoft-com:unattend">
|
||||
|
||||
<!-- === Windows PE Phase === -->
|
||||
<settings pass="windowsPE">
|
||||
<component name="Microsoft-Windows-International-Core-WinPE"
|
||||
processorArchitecture="amd64"
|
||||
publicKeyToken="31bf3856ad364e35"
|
||||
language="neutral"
|
||||
versionScope="nonSxS">
|
||||
<SetupUILanguage>
|
||||
<UILanguage>en-US</UILanguage>
|
||||
</SetupUILanguage>
|
||||
<InputLocale>en-US</InputLocale>
|
||||
<SystemLocale>en-US</SystemLocale>
|
||||
<UILanguage>en-US</UILanguage>
|
||||
<UserLocale>en-US</UserLocale>
|
||||
</component>
|
||||
|
||||
<component name="Microsoft-Windows-Setup"
|
||||
processorArchitecture="amd64"
|
||||
publicKeyToken="31bf3856ad364e35"
|
||||
language="neutral"
|
||||
versionScope="nonSxS">
|
||||
<UserData>
|
||||
<ProductKey>
|
||||
<Key></Key> <!-- Evaluation version: no key needed -->
|
||||
</ProductKey>
|
||||
<AcceptEula>true</AcceptEula>
|
||||
</UserData>
|
||||
</component>
|
||||
</settings>
|
||||
|
||||
<!-- === Specialize Phase === -->
|
||||
<settings pass="specialize">
|
||||
<component name="Microsoft-Windows-Shell-Setup"
|
||||
processorArchitecture="amd64"
|
||||
publicKeyToken="31bf3856ad364e35"
|
||||
language="neutral"
|
||||
versionScope="nonSxS">
|
||||
<ComputerName>*</ComputerName> <!-- Auto-generate name -->
|
||||
</component>
|
||||
|
||||
<component name="Microsoft-Windows-International-Core"
|
||||
processorArchitecture="amd64"
|
||||
publicKeyToken="31bf3856ad364e35"
|
||||
language="neutral"
|
||||
versionScope="nonSxS">
|
||||
<InputLocale>en-US</InputLocale>
|
||||
<SystemLocale>en-US</SystemLocale>
|
||||
<UILanguage>en-US</UILanguage>
|
||||
<UserLocale>en-US</UserLocale>
|
||||
</component>
|
||||
|
||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager"
|
||||
processorArchitecture="amd64"
|
||||
publicKeyToken="31bf3856ad364e35"
|
||||
language="neutral"
|
||||
versionScope="nonSxS">
|
||||
<fDenyTSConnections>false</fDenyTSConnections>
|
||||
</component>
|
||||
</settings>
|
||||
|
||||
<!-- === OOBE System Phase === -->
|
||||
<settings pass="oobeSystem">
|
||||
<component name="Microsoft-Windows-Shell-Setup"
|
||||
processorArchitecture="amd64"
|
||||
publicKeyToken="31bf3856ad364e35"
|
||||
language="neutral"
|
||||
versionScope="nonSxS">
|
||||
<OOBE>
|
||||
<HideEULAPage>true</HideEULAPage>
|
||||
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
|
||||
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
|
||||
<HideLocalAccountScreen>false</HideLocalAccountScreen>
|
||||
<ProtectYourPC>3</ProtectYourPC>
|
||||
</OOBE>
|
||||
|
||||
<!-- Administrator Password -->
|
||||
<UserAccounts>
|
||||
<AdministratorPassword>
|
||||
<Value>PackerPassword123!</Value>
|
||||
<PlainText>true</PlainText>
|
||||
</AdministratorPassword>
|
||||
</UserAccounts>
|
||||
|
||||
<!-- Auto-login (Count=1 = login once) -->
|
||||
<AutoLogon>
|
||||
<Enabled>true</Enabled>
|
||||
<Username>Administrator</Username>
|
||||
<LogonCount>1</LogonCount>
|
||||
</AutoLogon>
|
||||
|
||||
<!-- First Logon Commands -->
|
||||
<FirstLogonCommands>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>powershell -Command "Set-NetFirewallProfile -Profile Private -Enabled False"</CommandLine>
|
||||
<Order>1</Order>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>powershell -Command "Invoke-WebRequest -Uri https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1 -OutFile C:\ConfigureRemotingForAnsible.ps1; C:\ConfigureRemotingForAnsible.ps1"</CommandLine>
|
||||
<Order>2</Order>
|
||||
</SynchronousCommand>
|
||||
</FirstLogonCommands>
|
||||
</component>
|
||||
</settings>
|
||||
|
||||
</unattend>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Critical Settings
|
||||
|
||||
### ⚠️ Auto-Login Configuration
|
||||
|
||||
```xml
|
||||
<AutoLogon>
|
||||
<Enabled>true</Enabled>
|
||||
<Username>Administrator</Username>
|
||||
<LogonCount>1</LogonCount> <!-- Login once, then stay logged in -->
|
||||
</AutoLogon>
|
||||
```
|
||||
|
||||
**Why?** Packer needs to connect via WinRM after the OS is installed. Auto-login allows WinRM to be configured and accessed.
|
||||
|
||||
### ⚠️ Firewall Configuration
|
||||
|
||||
```xml
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>powershell -Command "Set-NetFirewallProfile -Profile Private -Enabled False"</CommandLine>
|
||||
<Order>1</Order>
|
||||
</SynchronousCommand>
|
||||
```
|
||||
|
||||
**Why?** Ansible connects via WinRM on the Private network profile. If the firewall blocks WinRM, connection fails.
|
||||
|
||||
### ⚠️ WinRM Enablement
|
||||
|
||||
```xml
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>powershell -Command "Invoke-WebRequest -Uri https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1 -OutFile C:\ConfigureRemotingForAnsible.ps1; C:\ConfigureRemotingForAnsible.ps1"</CommandLine>
|
||||
<Order>2</Order>
|
||||
</SynchronousCommand>
|
||||
```
|
||||
|
||||
**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<br/>Pre-installation] --> Spec[specialize<br/>Specialize] --> OOBE[oobeSystem<br/>OOBE] --> Desktop[Desktop<br/>Ready]
|
||||
end
|
||||
|
||||
subgraph Actions["Key Actions"]
|
||||
PE[Load drivers<br/>Setup language] --> Spec[Computer name<br/>Timezone] --> OOBE[Create accounts<br/>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)
|
||||
218
docs/03-packer/configuration.md
Normal file
218
docs/03-packer/configuration.md
Normal file
|
|
@ -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 = [
|
||||
"<wait><wait><wait>", "<enter><wait>", "<enter><wait>",
|
||||
"<enter><wait>", "<enter>"
|
||||
]
|
||||
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><wait><wait>", # Wait 30 seconds
|
||||
"<enter><wait>", # Press Enter (handle "Press any key")
|
||||
"<enter><wait>", # Confirm boot
|
||||
"<enter><wait>", # Continue installation
|
||||
"<enter>" # 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)
|
||||
223
docs/04-terraform/main.tf.md
Normal file
223
docs/04-terraform/main.tf.md
Normal file
|
|
@ -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)
|
||||
158
docs/04-terraform/variables.md
Normal file
158
docs/04-terraform/variables.md
Normal file
|
|
@ -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)
|
||||
195
docs/05-ansible/pipeline.md
Normal file
195
docs/05-ansible/pipeline.md
Normal file
|
|
@ -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]
|
||||
<VM_IP> ansible_user=Administrator ansible_password=<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)
|
||||
288
docs/06-ci-cd/forgejo-workflows.md
Normal file
288
docs/06-ci-cd/forgejo-workflows.md
Normal file
|
|
@ -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)
|
||||
200
docs/07-advanced/evaluation.md
Normal file
200
docs/07-advanced/evaluation.md
Normal file
|
|
@ -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)
|
||||
273
docs/07-advanced/troubleshooting.md
Normal file
273
docs/07-advanced/troubleshooting.md
Normal file
|
|
@ -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 = [
|
||||
"<wait><wait><wait><wait><wait>",
|
||||
"<enter><wait><wait>",
|
||||
"<enter>"
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 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
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>powershell -Command "Set-NetFirewallProfile -Profile Private -Enabled False"</CommandLine>
|
||||
<Order>1</Order>
|
||||
</SynchronousCommand>
|
||||
|
||||
# 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 <VM_ID>
|
||||
|
||||
# View VM config
|
||||
qm config <VM_ID>
|
||||
|
||||
# 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)
|
||||
258
docs/index.md
Normal file
258
docs/index.md
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
# 📖 Documentation Index
|
||||
|
||||
<!-- Badges -->
|
||||
[](.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)
|
||||
Loading…
Add table
Add a link
Reference in a new issue