From 005213ac7f03342ba2b0568ab56262b61cb44f5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Domagoj=20Andri=C4=87?= Date: Wed, 15 Apr 2026 15:31:29 +0200 Subject: [PATCH] Add Debian templates for Worldskills VMs --- common/template/debian13-gui/debian.pkr.hcl | 291 +++++++++++++++++ .../debian13-gui/debian.pkrvars.hcl.example | 34 ++ common/template/debian13-gui/http/preseed.cfg | 141 +++++++++ common/template/debian13/debian.pkr.hcl | 298 ++++++++++++++++++ .../debian13/debian.pkrvars.hcl.example | 34 ++ common/template/debian13/http/preseed.cfg | 142 +++++++++ 6 files changed, 940 insertions(+) create mode 100644 common/template/debian13-gui/debian.pkr.hcl create mode 100644 common/template/debian13-gui/debian.pkrvars.hcl.example create mode 100644 common/template/debian13-gui/http/preseed.cfg create mode 100644 common/template/debian13/debian.pkr.hcl create mode 100644 common/template/debian13/debian.pkrvars.hcl.example create mode 100644 common/template/debian13/http/preseed.cfg diff --git a/common/template/debian13-gui/debian.pkr.hcl b/common/template/debian13-gui/debian.pkr.hcl new file mode 100644 index 0000000..8934739 --- /dev/null +++ b/common/template/debian13-gui/debian.pkr.hcl @@ -0,0 +1,291 @@ +packer { + required_version = ">= 1.9.0" + required_plugins { + vsphere = { + source = "github.com/hashicorp/vsphere" + version = "~> 1" + } + } +} + +# ── vCenter connection ─────────────────────────────────────────────────────── + +variable "vcenter_server" { + type = string + description = "vCenter server hostname or IP address" +} + +variable "vcenter_username" { + type = string + description = "vCenter username (e.g. administrator@vsphere.local)" +} + +variable "vcenter_password" { + type = string + description = "vCenter password" + sensitive = true +} + +variable "vcenter_insecure_connection" { + type = bool + description = "Skip TLS certificate verification (set false in production)" + default = true +} + +# ── vSphere placement ──────────────────────────────────────────────────────── + +variable "datacenter" { + type = string + description = "vSphere datacenter name" +} + +variable "cluster" { + type = string + description = "vSphere cluster or standalone ESXi host name" +} + +variable "datastore" { + type = string + description = "Datastore name where the VM will be stored" +} + +variable "network" { + type = string + description = "Port group / network name (used for Packer SSH — not saved in template)" +} + +variable "vm_folder" { + type = string + description = "VM inventory folder path (empty = root datacenter folder)" + default = "" +} + +# ── VM hardware ────────────────────────────────────────────────────────────── + +variable "vm_name" { + type = string + description = "Name of the resulting VM template" + default = "debian-13-gui-template" +} + +variable "vm_cpus" { + type = number + description = "Number of vCPUs" + default = 2 +} + +variable "vm_memory_mb" { + type = number + description = "RAM in MB" + default = 2048 +} + +variable "vm_disk_size_mb" { + type = number + description = "System disk size in MB" + default = 40960 # 40 GB +} + +# ── ISO paths on the vSphere datastore ────────────────────────────────────── +# Format: "[] " +# All five BDs are mounted simultaneously so apt can resolve packages from any +# disc without manual disc swapping. BD-1 is the only bootable disc. + +variable "iso_bd1" { + type = string + description = "Datastore path to debian-13-amd64-BD-1.iso (bootable installer)" +} + +variable "iso_bd2" { + type = string + description = "Datastore path to debian-13-amd64-BD-2.iso" +} + +variable "iso_bd3" { + type = string + description = "Datastore path to debian-13-amd64-BD-3.iso" +} + +variable "iso_bd4" { + type = string + description = "Datastore path to debian-13-amd64-BD-4.iso" +} + +variable "iso_bd5" { + type = string + description = "Datastore path to debian-13-amd64-BD-5.iso" +} + +variable "iso_bd6" { + type = string + description = "Datastore path to debian-13-amd64-BD-6.iso" +} + + +# ── Preseed / SSH credentials ──────────────────────────────────────────────── +# Must match the values in http/preseed.cfg + +variable "ssh_username" { + type = string + default = "root" +} + +variable "ssh_password" { + type = string + sensitive = true + default = "packer" +} + +# ── Source definition ──────────────────────────────────────────────────────── + +source "vsphere-iso" "debian" { + # vCenter + vcenter_server = var.vcenter_server + username = var.vcenter_username + password = var.vcenter_password + insecure_connection = var.vcenter_insecure_connection + datacenter = var.datacenter + cluster = var.cluster + datastore = var.datastore + folder = var.vm_folder + + # VM identity + vm_name = var.vm_name + guest_os_type = "debian10_64Guest" # highest Debian guest ID recognised by ESXi 6.5 + notes = "Debian 13 (Trixie) — built with Packer on ${formatdate("YYYY-MM-DD", timestamp())}" + + firmware = "efi" + + # CPU / RAM + CPUs = var.vm_cpus + RAM = var.vm_memory_mb + RAM_reserve_all = false + + # Disk — thin-provisioned on a PVSCSI controller (best practice for vSphere) + disk_controller_type = ["pvscsi"] + storage { + disk_size = var.vm_disk_size_mb + disk_thin_provisioned = true + disk_controller_index = 0 + } + + # Network adapter — needed only so Packer can SSH in after install. + # The preseed does not write any persistent network configuration. + network_adapters { + network = var.network + network_card = "vmxnet3" + } + + # SATA CD-ROM drives — SATA supports up to 30 slots, avoiding the 4-device + # IDE limit. All five BD ISOs are mounted simultaneously so apt-cdrom can + # scan every disc without manual swapping. + cdrom_type = "sata" + iso_paths = [ + var.iso_bd1, # CD-ROM 0 — bootable installer disc + var.iso_bd2, # CD-ROM 1 + var.iso_bd3, # CD-ROM 2 + var.iso_bd4, # CD-ROM 3 + var.iso_bd5, # CD-ROM 4 + var.iso_bd6, # CD-ROM 5 + ] + + # Packer starts a local HTTP server to serve the preseed file. + http_directory = "${path.root}/http" + http_port_min = 8100 + http_port_max = 8199 + + # Boot sequence (UEFI / GRUB edit mode): + # 1. Wait for the GRUB menu to appear. + # 2. Press down once — default is "Graphical install"; one down selects + # the plain "Install" (TUI) entry. + # 3. Press 'e' to open the entry editor. + # 4. Navigate down to the linux kernel line (3rd line in the entry) and + # jump to its end, then append preseed parameters. + # 5. Press Ctrl+X to boot. + boot_wait = "10s" + boot_command = [ + "", + "e", + "", + " auto=true priority=critical", + " locale=en_US.UTF-8", + " keymap=us", + " keyboard-configuration/xkb-keymap=us", + " keyboard-configuration/layoutcode=us", + " preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg", + "x" + ] + + # SSH communicator — Packer waits here until the VM finishes installing, + # reboots, and becomes reachable (open-vm-tools reports the DHCP address). + communicator = "ssh" + ssh_username = var.ssh_username + ssh_password = var.ssh_password + ssh_timeout = "120m" + ssh_handshake_attempts = 100 + + # Keep the five CD-ROM drives in the template so the discs can be remounted + # later (e.g. to install additional packages on cloned VMs). + # ISOs remain attached; disconnect them in the vSphere UI if not needed. + remove_cdrom = false + + # Power off and convert to template once the build completes + convert_to_template = false + create_snapshot = true + snapshot_name = "Start" +} + +# ── Build ───────────────────────────────────────────────────────────────────── + +build { + name = "debian-13-gui-template" + sources = ["source.vsphere-iso.debian"] + + # Generalise the VM so every clone starts with a clean identity + provisioner "shell" { + inline = [ + # Remove SSH host keys — regenerated on first boot of each clone + "sudo rm -f /etc/ssh/ssh_host_*", + + # Generate root SSH key + "sudo mkdir -p /root/.ssh", + "sudo chmod 700 /root/.ssh", + "sudo ssh-keygen -t ed25519 -N '' -f /root/.ssh/id_ed25519", + "sudo chmod 600 /root/.ssh/id_ed25519", + "sudo chmod 644 /root/.ssh/id_ed25519.pub", + "sudo cp /root/.ssh/id_ed25519.pub /root/.ssh/authorized_keys", + "sudo chmod 600 /root/.ssh/authorized_keys", + + # Clear machine-id — systemd and DHCP clients use it as a unique identifier + "sudo truncate -s0 /etc/machine-id", + "sudo rm -f /var/lib/dbus/machine-id", + "sudo ln -s /etc/machine-id /var/lib/dbus/machine-id", + + # Network left as DHCP — no wipe needed for GUI template + "sudo rm -f /etc/udev/rules.d/70-persistent-net.rules", + "sudo truncate -s0 /etc/hostname", + + # ── cloud-init ────────────────────────────────────────────────────────── + # Set VMware as the preferred datasource (open-vm-tools is installed) + "echo 'datasource_list: [VMware, NoCloud, None]' | sudo tee /etc/cloud/cloud.cfg.d/99-datasource.cfg", + + # Remove any cloud-init state so it runs fresh on first boot of each clone + # Services are enabled automatically by the package — no explicit enable needed + "sudo cloud-init clean --logs", + + # ── Cleanup ───────────────────────────────────────────────────────────── + # Clean apt package cache + "sudo apt-get clean -y", + "sudo apt-get autoremove --purge -y", + + # Truncate log files (keep the files so rsyslog doesn't complain) + "sudo find /var/log -type f | sudo xargs truncate -s0", + "sudo truncate -s0 /var/log/wtmp", + "sudo truncate -s0 /var/log/lastlog", + + # Clear shell histories + "sudo truncate -s0 /root/.bash_history", + "truncate -s0 ~/.bash_history", + ] + } +} diff --git a/common/template/debian13-gui/debian.pkrvars.hcl.example b/common/template/debian13-gui/debian.pkrvars.hcl.example new file mode 100644 index 0000000..358027c --- /dev/null +++ b/common/template/debian13-gui/debian.pkrvars.hcl.example @@ -0,0 +1,34 @@ +# Copy this file to debian.pkrvars.hcl and fill in the values for your +# environment. Never commit the real file — it contains credentials. +# +# Usage: +# packer init . +# packer build -var-file=debian.pkrvars.hcl . + +vcenter_server = "vcsa.example.local" +vcenter_username = "administrator@vsphere.local" +vcenter_password = "Password!" + +# Set to false if your vCenter has a valid CA-signed certificate +vcenter_insecure_connection = true + +datacenter = "" +cluster = "" # standalone ESXi host +datastore = "datastore1" +network = "VM Network" # port group used during build (DHCP required) +vm_folder = "Templates" + +vm_name = "debian-13-template" +vm_cpus = 2 +vm_memory_mb = 2048 +vm_disk_size_mb = 30720 + +iso_bd1 = "[datastore1] ISOs/debian-13.4.0-amd64-BD-1.iso" +iso_bd2 = "[datastore1] ISOs/debian-13.4.0-amd64-BD-2.iso" +iso_bd3 = "[datastore1] ISOs/debian-13.4.0-amd64-BD-3.iso" +iso_bd4 = "[datastore1] ISOs/debian-13.4.0-amd64-BD-4.iso" +iso_bd5 = "[datastore1] ISOs/debian-13.4.0-amd64-BD-5.iso" +iso_bd6 = "[datastore1] ISOs/debian-13.4.0-amd64-BD-6.iso" + +ssh_username = "root" +ssh_password = "Passw0rd!" diff --git a/common/template/debian13-gui/http/preseed.cfg b/common/template/debian13-gui/http/preseed.cfg new file mode 100644 index 0000000..c87561d --- /dev/null +++ b/common/template/debian13-gui/http/preseed.cfg @@ -0,0 +1,141 @@ +# Debian 13 (Trixie) — fully automated preseed for vSphere template builds +# All packages are resolved from the six mounted BD ISOs; no internet access +# is required during installation. + +# ── Locale & keyboard ──────────────────────────────────────────────────────── +d-i debian-installer/locale string en_US.UTF-8 +d-i localechooser/supported-locales multiselect en_US.UTF-8 +d-i keyboard-configuration/model string pc105 +d-i keyboard-configuration/layoutcode string us +d-i keyboard-configuration/variantcode string +d-i keyboard-configuration/xkb-keymap select us +d-i keyboard-configuration/options string +d-i console-setup/ask_detect boolean false +d-i console-setup/layoutcode string us +d-i console-setup/variantcode string + +# ── Network ────────────────────────────────────────────────────────────────── +# DHCP is used during installation so Packer can reach the VM over SSH. +# No static IP, hostname, or domain is written to the installed system — +# each clone from the template configures its own network on first boot. +d-i netcfg/choose_interface select auto +d-i netcfg/get_hostname string debian +d-i netcfg/get_domain string local +d-i netcfg/hostname string debian +d-i netcfg/wireless_wep string + +# ── Mirror / apt sources ────────────────────────────────────────────────────── +# Disable network mirror entirely. All packages come from the six BD ISOs +# that are mounted as CD-ROM drives. The installer scans every optical drive +# automatically and registers them as apt sources. +d-i apt-setup/use_mirror boolean false +d-i apt-setup/no_mirror boolean true +d-i apt-setup/cdrom/set-first boolean true +d-i apt-setup/cdrom/set-next boolean true +d-i apt-setup/cdrom/set-failed boolean true +d-i apt-setup/services-select multiselect + +# ── Clock ───────────────────────────────────────────────────────────────────── +d-i clock-setup/utc boolean true +d-i time/zone string UTC +d-i clock-setup/ntp boolean false + +# ── Partitioning ────────────────────────────────────────────────────────────── +# GPT layout required for UEFI. Three partitions: +# 1. EFI System Partition — 512 MB fat32 +# 2. Swap — 2 GB +# 3. Root — remainder of disk, xfs +d-i partman-auto/disk string /dev/sda +d-i partman-auto/method string regular +d-i partman-partitioning/choose_label string gpt +d-i partman-partitioning/default_label string gpt +d-i partman-lvm/device_remove_lvm boolean true +d-i partman-md/device_remove_md boolean true +d-i partman-lvm/confirm boolean true +d-i partman-lvm/confirm_nooverwrite boolean true +d-i partman/default_filesystem string xfs + +d-i partman-auto/choose_recipe select boot-root +d-i partman-auto/expert_recipe string \ + boot-root :: \ + 512 512 512 fat32 \ + $primary{ } \ + method{ efi } \ + format{ } \ + . \ + 2048 2048 2048 linux-swap \ + $primary{ } \ + method{ swap } \ + format{ } \ + . \ + 1000 30000 -1 xfs \ + $primary{ } \ + method{ format } \ + format{ } \ + use_filesystem{ } \ + filesystem{ xfs } \ + mountpoint{ / } \ + . + +d-i partman-partitioning/confirm_write_new_label boolean true +d-i partman/choose_partition select finish +d-i partman/confirm boolean true +d-i partman/confirm_nooverwrite boolean true + +# ── Users ───────────────────────────────────────────────────────────────────── +# Root only — no regular user created; cloud-init handles user provisioning. +d-i passwd/root-login boolean true +d-i passwd/root-password password Passw0rd! +d-i passwd/root-password-again password Passw0rd! +d-i passwd/make-user boolean false + +# ── Package selection ───────────────────────────────────────────────────────── +tasksel tasksel/first multiselect standard, xfce-desktop +d-i pkgsel/include string \ + sudo \ + openssh-server \ + open-vm-tools \ + open-vm-tools-desktop \ + cloud-init \ + smbclient \ + curl \ + lynx \ + dnsutils \ + ldap-utils \ + ftp \ + lftp \ + wget \ + nfs-common \ + rsync \ + telnet \ + traceroute \ + tcptraceroute \ + tcpdump \ + net-tools \ + cifs-utils \ + resolvconf \ + nmap \ + vim + +d-i pkgsel/upgrade select full-upgrade +popularity-contest popularity-contest/participate boolean false + +# ── Boot loader ─────────────────────────────────────────────────────────────── +# On UEFI, grub-efi installs to the EFI System Partition automatically — +# do not specify bootdev or it will conflict with EFI installation. +d-i grub-installer/only_debian boolean true +d-i grub-installer/with_other_os boolean false + +# ── Late command ────────────────────────────────────────────────────────────── +# Runs inside the installed system (chroot) just before the first reboot. +# 1. Configure SSH to allow root login and password authentication. +# 2. Enable the SSH service. +# 3. Configure LightDM to auto-login as root so Xfce setup completes on boot. +d-i preseed/late_command string \ + in-target sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config; \ + in-target sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config; \ + in-target systemctl enable ssh; \ + in-target sh -c 'printf "[SeatDefaults]\nautologin-user=root\nautologin-user-timeout=0\n" >> /etc/lightdm/lightdm.conf' + +# ── Finish ──────────────────────────────────────────────────────────────────── +d-i finish-install/reboot_in_progress note diff --git a/common/template/debian13/debian.pkr.hcl b/common/template/debian13/debian.pkr.hcl new file mode 100644 index 0000000..9657883 --- /dev/null +++ b/common/template/debian13/debian.pkr.hcl @@ -0,0 +1,298 @@ +packer { + required_version = ">= 1.9.0" + required_plugins { + vsphere = { + source = "github.com/hashicorp/vsphere" + version = "~> 1" + } + } +} + +# ── vCenter connection ─────────────────────────────────────────────────────── + +variable "vcenter_server" { + type = string + description = "vCenter server hostname or IP address" +} + +variable "vcenter_username" { + type = string + description = "vCenter username (e.g. administrator@vsphere.local)" +} + +variable "vcenter_password" { + type = string + description = "vCenter password" + sensitive = true +} + +variable "vcenter_insecure_connection" { + type = bool + description = "Skip TLS certificate verification (set false in production)" + default = true +} + +# ── vSphere placement ──────────────────────────────────────────────────────── + +variable "datacenter" { + type = string + description = "vSphere datacenter name" +} + +variable "cluster" { + type = string + description = "vSphere cluster or standalone ESXi host name" +} + +variable "datastore" { + type = string + description = "Datastore name where the VM will be stored" +} + +variable "network" { + type = string + description = "Port group / network name (used for Packer SSH — not saved in template)" +} + +variable "vm_folder" { + type = string + description = "VM inventory folder path (empty = root datacenter folder)" + default = "" +} + +# ── VM hardware ────────────────────────────────────────────────────────────── + +variable "vm_name" { + type = string + description = "Name of the resulting VM template" + default = "debian-13-template" +} + +variable "vm_cpus" { + type = number + description = "Number of vCPUs" + default = 2 +} + +variable "vm_memory_mb" { + type = number + description = "RAM in MB" + default = 2048 +} + +variable "vm_disk_size_mb" { + type = number + description = "System disk size in MB" + default = 40960 # 40 GB +} + +# ── ISO paths on the vSphere datastore ────────────────────────────────────── +# Format: "[] " +# All five BDs are mounted simultaneously so apt can resolve packages from any +# disc without manual disc swapping. BD-1 is the only bootable disc. + +variable "iso_bd1" { + type = string + description = "Datastore path to debian-13-amd64-BD-1.iso (bootable installer)" +} + +variable "iso_bd2" { + type = string + description = "Datastore path to debian-13-amd64-BD-2.iso" +} + +variable "iso_bd3" { + type = string + description = "Datastore path to debian-13-amd64-BD-3.iso" +} + +variable "iso_bd4" { + type = string + description = "Datastore path to debian-13-amd64-BD-4.iso" +} + +variable "iso_bd5" { + type = string + description = "Datastore path to debian-13-amd64-BD-5.iso" +} + +variable "iso_bd6" { + type = string + description = "Datastore path to debian-13-amd64-BD-6.iso" +} + + +# ── Preseed / SSH credentials ──────────────────────────────────────────────── +# Must match the values in http/preseed.cfg + +variable "ssh_username" { + type = string + default = "root" +} + +variable "ssh_password" { + type = string + sensitive = true + default = "packer" +} + +# ── Source definition ──────────────────────────────────────────────────────── + +source "vsphere-iso" "debian" { + # vCenter + vcenter_server = var.vcenter_server + username = var.vcenter_username + password = var.vcenter_password + insecure_connection = var.vcenter_insecure_connection + datacenter = var.datacenter + cluster = var.cluster + datastore = var.datastore + folder = var.vm_folder + + # VM identity + vm_name = var.vm_name + guest_os_type = "debian10_64Guest" # highest Debian guest ID recognised by ESXi 6.5 + notes = "Debian 13 (Trixie) — built with Packer on ${formatdate("YYYY-MM-DD", timestamp())}" + + firmware = "efi" + + # CPU / RAM + CPUs = var.vm_cpus + RAM = var.vm_memory_mb + RAM_reserve_all = false + + # Disk — thin-provisioned on a PVSCSI controller (best practice for vSphere) + disk_controller_type = ["pvscsi"] + storage { + disk_size = var.vm_disk_size_mb + disk_thin_provisioned = true + disk_controller_index = 0 + } + + # Network adapter — needed only so Packer can SSH in after install. + # The preseed does not write any persistent network configuration. + network_adapters { + network = var.network + network_card = "vmxnet3" + } + + # SATA CD-ROM drives — SATA supports up to 30 slots, avoiding the 4-device + # IDE limit. All five BD ISOs are mounted simultaneously so apt-cdrom can + # scan every disc without manual swapping. + cdrom_type = "sata" + iso_paths = [ + var.iso_bd1, # CD-ROM 0 — bootable installer disc + var.iso_bd2, # CD-ROM 1 + var.iso_bd3, # CD-ROM 2 + var.iso_bd4, # CD-ROM 3 + var.iso_bd5, # CD-ROM 4 + var.iso_bd6, # CD-ROM 5 + ] + + # Packer starts a local HTTP server to serve the preseed file. + http_directory = "${path.root}/http" + http_port_min = 8100 + http_port_max = 8199 + + # Boot sequence (UEFI / GRUB edit mode): + # 1. Wait for the GRUB menu to appear. + # 2. Press down once — default is "Graphical install"; one down selects + # the plain "Install" (TUI) entry. + # 3. Press 'e' to open the entry editor. + # 4. Navigate down to the linux kernel line (3rd line in the entry) and + # jump to its end, then append preseed parameters. + # 5. Press Ctrl+X to boot. + boot_wait = "10s" + boot_command = [ + "", + "e", + "", + " auto=true priority=critical", + " locale=en_US.UTF-8", + " keymap=us", + " keyboard-configuration/xkb-keymap=us", + " keyboard-configuration/layoutcode=us", + " preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg", + "x" + ] + + # SSH communicator — Packer waits here until the VM finishes installing, + # reboots, and becomes reachable (open-vm-tools reports the DHCP address). + communicator = "ssh" + ssh_username = var.ssh_username + ssh_password = var.ssh_password + ssh_timeout = "120m" + ssh_handshake_attempts = 100 + + # Keep the five CD-ROM drives in the template so the discs can be remounted + # later (e.g. to install additional packages on cloned VMs). + # ISOs remain attached; disconnect them in the vSphere UI if not needed. + remove_cdrom = false + + # Power off and snapshot once the build completes + convert_to_template = false + create_snapshot = true + snapshot_name = "Start" +} + +# ── Build ───────────────────────────────────────────────────────────────────── + +build { + name = "debian-13-template" + sources = ["source.vsphere-iso.debian"] + + # Generalise the VM so every clone starts with a clean identity + provisioner "shell" { + inline = [ + # Remove SSH host keys — regenerated on first boot of each clone + "sudo rm -f /etc/ssh/ssh_host_*", + + # Generate root SSH key + "sudo mkdir -p /root/.ssh", + "sudo chmod 700 /root/.ssh", + "sudo ssh-keygen -t ed25519 -N '' -f /root/.ssh/id_ed25519", + "sudo chmod 600 /root/.ssh/id_ed25519", + "sudo chmod 644 /root/.ssh/id_ed25519.pub", + "sudo cp /root/.ssh/id_ed25519.pub /root/.ssh/authorized_keys", + "sudo chmod 600 /root/.ssh/authorized_keys", + + # Clear machine-id — systemd and DHCP clients use it as a unique identifier + "sudo truncate -s0 /etc/machine-id", + "sudo rm -f /var/lib/dbus/machine-id", + "sudo ln -s /etc/machine-id /var/lib/dbus/machine-id", + + # ── Network config wipe ───────────────────────────────────────────────── + # Remove persistent interface naming rules + "sudo rm -f /etc/udev/rules.d/70-persistent-net.rules", + + # Blank ifupdown config — Debian server uses this exclusively + "echo '' | sudo tee /etc/network/interfaces", + + # Clear hostname and DHCP leases + "sudo truncate -s0 /etc/hostname", + "sudo rm -f /var/lib/dhcp/*.leases", + + # ── cloud-init ────────────────────────────────────────────────────────── + # Set VMware as the preferred datasource (open-vm-tools is installed) + "echo 'datasource_list: [VMware, NoCloud, None]' | sudo tee /etc/cloud/cloud.cfg.d/99-datasource.cfg", + + # Remove any cloud-init state so it runs fresh on first boot of each clone + # Services are enabled automatically by the package — no explicit enable needed + "sudo cloud-init clean --logs", + + # ── Cleanup ───────────────────────────────────────────────────────────── + # Clean apt package cache + "sudo apt-get clean -y", + "sudo apt-get autoremove --purge -y", + + # Truncate log files (keep the files so rsyslog doesn't complain) + "sudo find /var/log -type f | sudo xargs truncate -s0", + "sudo truncate -s0 /var/log/wtmp", + "sudo truncate -s0 /var/log/lastlog", + + # Clear shell histories + "sudo truncate -s0 /root/.bash_history", + "truncate -s0 ~/.bash_history", + ] + } +} diff --git a/common/template/debian13/debian.pkrvars.hcl.example b/common/template/debian13/debian.pkrvars.hcl.example new file mode 100644 index 0000000..358027c --- /dev/null +++ b/common/template/debian13/debian.pkrvars.hcl.example @@ -0,0 +1,34 @@ +# Copy this file to debian.pkrvars.hcl and fill in the values for your +# environment. Never commit the real file — it contains credentials. +# +# Usage: +# packer init . +# packer build -var-file=debian.pkrvars.hcl . + +vcenter_server = "vcsa.example.local" +vcenter_username = "administrator@vsphere.local" +vcenter_password = "Password!" + +# Set to false if your vCenter has a valid CA-signed certificate +vcenter_insecure_connection = true + +datacenter = "" +cluster = "" # standalone ESXi host +datastore = "datastore1" +network = "VM Network" # port group used during build (DHCP required) +vm_folder = "Templates" + +vm_name = "debian-13-template" +vm_cpus = 2 +vm_memory_mb = 2048 +vm_disk_size_mb = 30720 + +iso_bd1 = "[datastore1] ISOs/debian-13.4.0-amd64-BD-1.iso" +iso_bd2 = "[datastore1] ISOs/debian-13.4.0-amd64-BD-2.iso" +iso_bd3 = "[datastore1] ISOs/debian-13.4.0-amd64-BD-3.iso" +iso_bd4 = "[datastore1] ISOs/debian-13.4.0-amd64-BD-4.iso" +iso_bd5 = "[datastore1] ISOs/debian-13.4.0-amd64-BD-5.iso" +iso_bd6 = "[datastore1] ISOs/debian-13.4.0-amd64-BD-6.iso" + +ssh_username = "root" +ssh_password = "Passw0rd!" diff --git a/common/template/debian13/http/preseed.cfg b/common/template/debian13/http/preseed.cfg new file mode 100644 index 0000000..a91f308 --- /dev/null +++ b/common/template/debian13/http/preseed.cfg @@ -0,0 +1,142 @@ +# Debian 13 (Trixie) — fully automated preseed for vSphere template builds +# All packages are resolved from the six mounted BD ISOs; no internet access +# is required during installation. + +# ── Locale & keyboard ──────────────────────────────────────────────────────── +d-i debian-installer/locale string en_US.UTF-8 +d-i localechooser/supported-locales multiselect en_US.UTF-8 +d-i keyboard-configuration/model string pc105 +d-i keyboard-configuration/layoutcode string us +d-i keyboard-configuration/variantcode string +d-i keyboard-configuration/xkb-keymap select us +d-i keyboard-configuration/options string +d-i console-setup/ask_detect boolean false +d-i console-setup/layoutcode string us +d-i console-setup/variantcode string + +# ── Network ────────────────────────────────────────────────────────────────── +# DHCP is used during installation so Packer can reach the VM over SSH. +# No static IP, hostname, or domain is written to the installed system — +# each clone from the template configures its own network on first boot. +d-i netcfg/choose_interface select auto +d-i netcfg/get_hostname string debian +d-i netcfg/get_domain string local +d-i netcfg/hostname string debian +d-i netcfg/wireless_wep string + +# ── Mirror / apt sources ────────────────────────────────────────────────────── +# Disable network mirror entirely. All packages come from the six BD ISOs +# that are mounted as CD-ROM drives. The installer scans every optical drive +# automatically and registers them as apt sources. +d-i apt-setup/use_mirror boolean false +d-i apt-setup/no_mirror boolean true +d-i apt-setup/cdrom/set-first boolean true +d-i apt-setup/cdrom/set-next boolean true +d-i apt-setup/cdrom/set-failed boolean true +d-i apt-setup/services-select multiselect + +# ── Clock ───────────────────────────────────────────────────────────────────── +d-i clock-setup/utc boolean true +d-i time/zone string UTC +d-i clock-setup/ntp boolean false + +# ── Partitioning ────────────────────────────────────────────────────────────── +# GPT layout required for UEFI. Three partitions: +# 1. EFI System Partition — 512 MB fat32 +# 2. Swap — 2 GB +# 3. Root — remainder of disk, xfs +d-i partman-auto/disk string /dev/sda +d-i partman-auto/method string regular +d-i partman-partitioning/choose_label string gpt +d-i partman-partitioning/default_label string gpt +d-i partman-lvm/device_remove_lvm boolean true +d-i partman-md/device_remove_md boolean true +d-i partman-lvm/confirm boolean true +d-i partman-lvm/confirm_nooverwrite boolean true +d-i partman/default_filesystem string xfs + +d-i partman-auto/choose_recipe select boot-root +d-i partman-auto/expert_recipe string \ + boot-root :: \ + 512 512 512 fat32 \ + $primary{ } \ + method{ efi } \ + format{ } \ + . \ + 2048 2048 2048 linux-swap \ + $primary{ } \ + method{ swap } \ + format{ } \ + . \ + 1000 30000 -1 xfs \ + $primary{ } \ + method{ format } \ + format{ } \ + use_filesystem{ } \ + filesystem{ xfs } \ + mountpoint{ / } \ + . + +d-i partman-partitioning/confirm_write_new_label boolean true +d-i partman/choose_partition select finish +d-i partman/confirm boolean true +d-i partman/confirm_nooverwrite boolean true + +# ── Users ───────────────────────────────────────────────────────────────────── +# Root only — no regular user created; cloud-init handles user provisioning. +d-i passwd/root-login boolean true +d-i passwd/root-password password Passw0rd! +d-i passwd/root-password-again password Passw0rd! +d-i passwd/make-user boolean false + +# ── Package selection ───────────────────────────────────────────────────────── +tasksel tasksel/first multiselect standard +d-i pkgsel/include string \ + sudo \ + openssh-server \ + open-vm-tools \ + cloud-init \ + smbclient \ + curl \ + lynx \ + dnsutils \ + ldap-utils \ + ftp \ + lftp \ + wget \ + nfs-common \ + rsync \ + telnet \ + traceroute \ + tcptraceroute \ + tcpdump \ + net-tools \ + cifs-utils \ + resolvconf \ + nmap \ + vim + +d-i pkgsel/upgrade select full-upgrade +popularity-contest popularity-contest/participate boolean false + +# ── Boot loader ─────────────────────────────────────────────────────────────── +# On UEFI, grub-efi installs to the EFI System Partition automatically — +# do not specify bootdev or it will conflict with EFI installation. +d-i grub-installer/only_debian boolean true +d-i grub-installer/with_other_os boolean false + +# ── Late command ────────────────────────────────────────────────────────────── +# Runs inside the installed system (chroot) just before the first reboot. +# 1. Configure SSH to allow root login and password authentication. +# 2. Enable the SSH service. +# 3. Remove any DHCP lease files so the template has no saved network state. +d-i preseed/late_command string \ + in-target sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config; \ + in-target sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config; \ + in-target systemctl enable ssh; \ + rm -f /target/var/lib/dhcp/*.leases; \ + rm -f /target/etc/resolv.conf; \ + in-target ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf + +# ── Finish ──────────────────────────────────────────────────────────────────── +d-i finish-install/reboot_in_progress note