Skip to content

Packer templates for the lab domain, built from phoenix (#440) - #792

Merged
Gerrrt merged 8 commits into
mainfrom
gerrrt/github-issue-440-a85459
Oct 1, 2026
Merged

Gerrrt merged 8 commits into
mainfrom
gerrrt/github-issue-440-a85459

Conversation

@Gerrrt

@Gerrrt Gerrrt commented Oct 1, 2026 •

Copy link
Copy Markdown
Owner

What changed

This adds a top-level packer/ with four Proxmox templates: Ubuntu 26.04 (901), Kali (902, written but not built), Windows 11 Pro (911) and Server 2025 evaluation (912). They are built from phoenix through Saruman's API. scripts/packer-smoke.sh proves a template by cloning it, booting it, checking the agent's address and the hostname, and destroying the clone. scripts/lint.sh now runs packer fmt -check and packer validate -syntax-only from a pinned hashicorp/packer:1.16.1 image.

Nothing runs in the lab until the runbook is followed. No template has been built yet.

Why

#440. When LabWindowsEvaluationExpiring fires, the only answer today is build-the-lab-domain.md §1–§4 done by hand. This makes the image a command.

The commits follow this repo's usual order:

  1. ADR-0074 records the decisions. It was written as 0071. main took 0071 (A disposable investigation stack, so an incident does not touch odin's durable store #438), 0072 (Put the ISO store on smaug, and add the fifth inbound rule ADR-0016 did not write down #446) and 0073 (Buy the off-estate drive, and decide what ADR-0023 needs beyond a drive #455) while this was open, so it was renumbered twice.
    • The templates take fixed VMIDs, and guests are full clones only, so a template can be rebuilt in place with -force.
    • The token and build password stay in phoenix.env, which settles ADR-0043's deferred question.
    • sysprep /generalize is the SID fix. The issue proposed rebuilding and renaming the template, but every clone of one template still shares its SID.
  2. The Packer tree, the smoke-test script, the CI linter, and the new runbook build-the-lab-templates.md.
  3. Docs: changelog, roadmap, architecture.md, and notes in build-the-jumpbox.md and build-the-lab-domain.md §7.
  4. Cites Build tpl-kali (VMID 902) on ifrit once it exists #790, the Kali follow-up for ifrit.
  5. Two merges of main, resolving the README counts (now 74 ADRs, 39 runbooks), the architecture.md table and the changelog, each followed by a renumber.
  6. Copilot's review, addressed in 1c4b75c:
    • TLS to Saruman's API is verified, and the smoke script no longer passes -k.
    • The build password needs all four character classes.
    • A Windows clone's guest agent only starts after SetupComplete.cmd, so the smoke test proves first-boot setup finished.
    • The Kali steps name ifrit's storage, API and smoke test.
    • The ADR and packer/README.md no longer read as if a template exists.

Blast radius

None at merge. CI gains two packer lint calls, and stacks/observability/compose.yaml gains a lint-profile service that make up neither pulls nor starts.

When the runbook is followed:

  • PhoenixBuilder gains /storage/large_data and VM.GuestAgent.Audit (runbook §2).

  • phoenix's trust store gains Saruman's cluster CA, /etc/pve/pve-root-ca.pem (runbook §2). This is the public certificate, not its key. Packer and the smoke script verify the API with it, so the token is never sent to an unverified host on VLAN 30.

  • Builds create VMIDs 901, 911 and 912, and VMID 999 for each smoke test.

  • No change to network segmentation or firewall rules. Kali's build needs port 8800 on phoenix while it runs, but only on ifrit (Build tpl-kali (VMID 902) on ifrit once it exists #790).

  • No new port published to a VLAN that could not already reach the service

  • No credential added outside secrets/*.sops.yaml. Deliberately unticked. The new PKR_VAR_build_password lives in ~/.config/proxmox/phoenix.env beside the existing token, because phoenix holds no age key (ADR-0043, ADR-0074 part 4). Nothing secret is in git.

Verification

Run on a workstation without Docker:

  • scripts/lint.sh passes yamllint, markdownlint, shellcheck, packer fmt / validate -syntax-only and editorconfig-checker. actionlint was skipped (it needs Docker).

  • A full packer validate with the pinned plugin, v1.2.4, passes. The rendered Autounattend and OOBE files parse as XML, and the autoinstall seed parses as YAML.

  • check_docs.py, check_image_pins.py, check-tracked-artefacts.sh and check-sops-encrypted.sh pass, and gitleaks finds no leaks. Microsoft's public generic Windows 11 Pro install key is allowed inline with a comment.

  • pin-digests.sh confirms the hashicorp/packer digest.

  • make validate passes. Its Docker-backed checks were skipped here, and check_mounted_config.py --self-test fails only because it calls docker. CI is the real run.

  • Deployed to the lab and confirmed working. Build the lab's VM templates with Packer, so the domain's evaluation clock stops costing a day #440 stays open until runbook §4–§8 on phoenix: build, smoke-test, SID check, then rebuild with -force and smoke-test again.

  • Docs updated (docs/, service README, or docs/roadmap.md)

Refs #440, #790.

🤖 Generated with Claude Code

Gerrrt and others added 6 commits October 1, 2026 15:20
…#440)

Packer goes in a top-level packer/, not under stacks/. The templates take
VMIDs 901-912, and guests are full clones so a template can be rebuilt in
place with -force.

Every Windows build ends in sysprep /generalize, which gives each clone a
fresh SID. The issue proposed rebuilding and renaming the template, but every
clone of a rebuilt template would still share one SID.

The token and build password stay in phoenix.env. That settles ADR-0043's
deferred encrypted-in-repo question: phoenix has no age key to decrypt one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…erver 2025 (#440)

Four proxmox-iso sources, run from phoenix through Saruman's API:
- Ubuntu installs by autoinstall from a cidata disc.
- Kali installs by preseed over Packer's HTTP server. It is written but not
  built, because its consumer lives on ifrit.
- The two Windows editions install from an Autounattend disc with the VirtIO
  drivers, then sysprep /generalize /quit.

scripts/packer-smoke.sh full-clones a template, waits for the guest agent's
address, checks the hostname (and SSH for Linux), and destroys the clone.

scripts/lint.sh gains packer fmt -check and validate -syntax-only, run from
a pinned hashicorp/packer image behind the lint profile.

The new runbook, build-the-lab-templates.md, covers the build, the token's
added privileges, the SID check and the rebuild.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Changelog entry, roadmap chain, phoenix's architecture row, and pointers from
build-the-jumpbox.md (the role has grown; the token's encrypted form was
decided against) and build-the-lab-domain.md section 7 (the template is the
rebuild path when the evaluation clock runs out).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ADR, the runbook's section 5, the changelog, the roadmap, packer/README.md
and kali.pkr.hcl said "a follow-up issue". It now exists, so they name it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…40-a85459

# Conflicts:
#	README.md
#	docs/architecture.md
#	docs/changelog.md
main took 0071 for the disposable investigation guest (#438) and 0072 for
the ISO store (#446) while this branch was open. The file is renamed, and
every reference to the Packer ADR follows it. References to #438's ADR-0071
are left as they were.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 1, 2026 15:53

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Windows readiness detection, TLS verification, password validation, Kali instructions, and deployment-status documentation need correction.

Review effort: Balanced
Findings: 1 High severity · 3 Medium severity · 2 Low severity

Open (6)
What changed in this PR

Adds Packer-based Proxmox VM templates and supporting automation for the lab.

Changes:

  • Defines Ubuntu, Kali, Windows 11, and Server 2025 templates.
  • Adds template smoke testing and CI linting.
  • Documents build, rebuild, and operational procedures.
File Description
stacks/​observability/​compose.yaml Pins the Packer lint image.
scripts/​packer-smoke.sh Adds clone-based template smoke testing.
scripts/​lint.sh Runs Packer format and syntax checks.
scripts/​check_container_health.py Documents the profiled Packer service.
README.md Updates ADR and runbook counts.
packer/​windows/​unattend-oobe.xml.pkrtpl Configures clone OOBE.
packer/​windows/​scripts/​sysprep.ps1 Generalizes Windows images.
packer/​windows/​scripts/​SetupComplete.cmd Removes temporary WinRM access.
packer/​windows/​scripts/​bootstrap.ps1 Installs guest tools and enables build WinRM.
packer/​windows/​autounattend.xml.pkrtpl Automates Windows installation.
packer/​windows.pkr.hcl Defines both Windows templates.
packer/​versions.pkr.hcl Pins Packer and the Proxmox plugin.
packer/​variables.pkr.hcl Defines shared build inputs.
packer/​ubuntu/​user-data.pkrtpl Provides Ubuntu autoinstall configuration.
packer/​ubuntu.pkr.hcl Defines the Ubuntu template.
packer/​README.md Documents the template inventory.
packer/​kali/​preseed.cfg.pkrtpl Provides Kali preseed configuration.
packer/​kali.pkr.hcl Defines the deferred Kali template.
docs/​runbooks/​build-the-lab-templates.md Adds the template build runbook.
docs/​runbooks/​build-the-lab-domain.md Documents template-based rebuilds.
docs/​runbooks/​build-the-jumpbox.md Records additional Packer privileges.
docs/​roadmap.md Tracks Packer implementation status.
docs/​changelog.md Records the unbuilt template sources.
docs/​architecture.md Adds Packer to phoenix’s responsibilities.
docs/​adr/​0073-build-the-lab-templates-with-packer-from-phoenix.md Records the template architecture decision.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packer/variables.pkr.hcl Resolved
Comment thread packer/variables.pkr.hcl Resolved
Comment thread scripts/packer-smoke.sh Resolved
Comment thread packer/README.md Resolved
…40-a85459

# Conflicts:
#	README.md
#	docs/changelog.md
@Gerrrt
Gerrrt enabled auto-merge (squash) October 1, 2026 16:14
)

Review on the PR:
- TLS is verified. The token rides in a header on VLAN 30, which the attack
  VM shares, so skipping verification would hand it to any guest answering
  for 10.0.30.110. phoenix trusts the cluster CA (runbook section 2).
  packer-smoke.sh drops -k.
- build_password needs all four character classes. A password Windows
  Setup would refuse now fails validation first.
- QEMU-GA is disabled before sysprep, and SetupComplete.cmd starts it last.
  A Windows clone's first agent answer, which the smoke test waits on, now
  means first-boot Setup has finished.
- The Kali steps name ifrit's storage, API and smoke test (#790).
- The ADR and packer/README.md say which node each template is for, rather
  than "built".

Also renumbers the Packer ADR to 0074. main took 0073 for the household copy
(#455) while this was open. References to #455's ADR-0073 are untouched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Gerrrt
Gerrrt merged commit 9f9b18a into main Oct 1, 2026
8 checks passed
@Gerrrt
Gerrrt deleted the gerrrt/github-issue-440-a85459 branch October 1, 2026 16:19
Gerrrt added a commit that referenced this pull request Oct 1, 2026
…-iso (#446)

#792 merged while this branch was open. Its Packer defaults put the ISOs
on local storage (iso_storage = local, local:iso/... file names), and no
step verifies a checksum. The roadmap sentence said #440 builds from
smaug-iso, which is not true yet. It now says what moving the builds there
takes, and that the checksum step still has to come first.

Refs #446

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Gerrrt added a commit that referenced this pull request Oct 1, 2026
* docs: the ISO store is built, and Saruman mounts it (#446)

build-the-nas.md §5b, done on 2026-10-01:

- smaug: erebor/iso at recordsize 1M, owned by pippin (3003:3002), shared
  over NFSv4 to 10.0.30.110 alone with root mapped to pippin.
- morpheus: `Allow NFS from Saruman to smaug` printed directly above
  igc0.30's Block access to CasaBonita in pfctl -sr -vv.
- Saruman: the fstab mount shows the 500G quota, and smaug-iso is an active
  dir storage. A web-UI upload of virtio-win-0.1.302.iso landed owned by
  pippin, not root.
- alexander and the monitoring host are refused on 2049. The igc0.40
  tripwire reads 0 packets after 260,980 evaluations.

The rule moves from specified to created in build-the-nas.md §0.5,
network.md, security.md and stacks/media/README.md. network.md's
ImaginationLAN notes now name the block, as build-the-backup-guest.md §4
asked. The roadmap entry folds into #440's: build from smaug-iso, and
verify each ISO's checksum first.

Also recorded: the step's apt install finished a half-configured alloy
upgrade on Saruman, and /etc/default/alloy was kept.

Closes #446.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: remove the changelog's conflict markers, and count the NFS pass (#446)

The previous commit carried stash conflict markers in changelog.md. A merge
of main auto-stashed the edits, and the re-apply conflicted where #455's
entry landed on the same date. Both entries are kept and the markers are
gone, which is what failed Lint.

Review on the PR:

- network.md said "Six exist today" for the Hicks and Winterfell passes,
  but they were already seven: four, then 4533, 445 and 13378. It now says
  seven, and the NFS pass makes eight.
- stacks/media/README.md names Saruman as a fifth consumer. It also says
  the 2049 export differs from the three media ports: CasaBonita can open
  the port, but the export answers 10.0.30.110 alone.

Refs #446

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(roadmap): #440's merged templates read from local, not yet smaug-iso (#446)

#792 merged while this branch was open. Its Packer defaults put the ISOs
on local storage (iso_storage = local, local:iso/... file names), and no
step verifies a checksum. The roadmap sentence said #440 builds from
smaug-iso, which is not true yet. It now says what moving the builds there
takes, and that the checksum step still has to come first.

Refs #446

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants