From 96c1e2d1f8c21b961956966d01d9a9c8bae2f7c5 Mon Sep 17 00:00:00 2001 From: phg Date: Sat, 24 Jan 2026 00:59:25 +0100 Subject: [PATCH] initial commit --- .gitignore | 109 ++++++++++++++ README.md | 48 +++++++ debian/13-trixie/credentials.auto.pkrvars.hcl | 1 + debian/13-trixie/debian-trixie.pkr.hcl | 133 ++++++++++++++++++ debian/13-trixie/files/99-pve.cfg | 1 + debian/13-trixie/files/debian.sources | 17 +++ debian/13-trixie/http/ks.cfg | 78 ++++++++++ debian/13-trixie/http/meta-data | 0 debian/13-trixie/http/user-data | 32 +++++ debian/13-trixie/variables-common.pkr.hcl | 1 + debian/13-trixie/variables.pkr.hcl | 76 ++++++++++ mise.toml | 42 ++++++ template-credentials.pkrvars.hcl | 2 + variables-common.pkr.hcl | 11 ++ 14 files changed, 551 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 120000 debian/13-trixie/credentials.auto.pkrvars.hcl create mode 100644 debian/13-trixie/debian-trixie.pkr.hcl create mode 100644 debian/13-trixie/files/99-pve.cfg create mode 100644 debian/13-trixie/files/debian.sources create mode 100644 debian/13-trixie/http/ks.cfg create mode 100644 debian/13-trixie/http/meta-data create mode 100644 debian/13-trixie/http/user-data create mode 120000 debian/13-trixie/variables-common.pkr.hcl create mode 100644 debian/13-trixie/variables.pkr.hcl create mode 100644 mise.toml create mode 100644 template-credentials.pkrvars.hcl create mode 100644 variables-common.pkr.hcl diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1c4192b --- /dev/null +++ b/.gitignore @@ -0,0 +1,109 @@ +# Project +/credentials.auto.pkrvars.hcl +/downloaded_iso_path + +# Linux +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# Metadata left by Dolphin file manager, which comes with KDE Plasma +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +# Log files created by default by the nohup command +nohup.out + +# macOS +# General +.DS_Store +__MACOSX/ +.AppleDouble +.LSOverride +Icon[ +] + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Windows +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets +!*.code-workspace + +# Built Visual Studio Code Extensions +*.vsix + +# vim +# Swap +[._]*.s[a-v][a-z] +# comment out the next line if you don't need vector files +!*.svg +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim +Sessionx.vim + +# Temporary +.netrwhist +*~ +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ diff --git a/README.md b/README.md new file mode 100644 index 0000000..158edf7 --- /dev/null +++ b/README.md @@ -0,0 +1,48 @@ +# Packer based PVE image templates + +## Table of Contents + +[[_TOC_]] + +## Initial Setup + +### Create Token + +1. Copy `template-credentials.pkr.hcl` to `credentials.auto.pkrvars.hcl` +2. Open your Proxmox VE web interface & Login. +3. Navigate to: `Datacenter` -> `Permissions` -> `API Tokens` +4. **Click:** Add +5. **Configure in the dialog:** + 1. **User:** `root@pam` (or the user you like, but It needs administrative permissions) + 2. **Token ID:** `packer` + 3. **Privilege Separation:** false +6. **Click:** Add +7. Copy the displayed Token ID and Token Secret to `credentials.auto.pkrvars.hcl` + +### Initialize Packer + +Run `packer init` to initialize Packer according to a HCL template +configuration. It's downloads and installs the required Plugins according to +the required_plugins block in Packer templates. + +```shell +mise run init +``` + +## Build + +To build a template run: + +```shell +mise run build +``` + +## Setup new templates + +Run: + +```shell +mise run setup +``` + +E.g. `mise run setup debian 13-trixie` or `mise run setup nixos 25.11`. diff --git a/debian/13-trixie/credentials.auto.pkrvars.hcl b/debian/13-trixie/credentials.auto.pkrvars.hcl new file mode 120000 index 0000000..2704ed7 --- /dev/null +++ b/debian/13-trixie/credentials.auto.pkrvars.hcl @@ -0,0 +1 @@ +../../credentials.auto.pkrvars.hcl \ No newline at end of file diff --git a/debian/13-trixie/debian-trixie.pkr.hcl b/debian/13-trixie/debian-trixie.pkr.hcl new file mode 100644 index 0000000..6d63ffd --- /dev/null +++ b/debian/13-trixie/debian-trixie.pkr.hcl @@ -0,0 +1,133 @@ +packer { + required_plugins { + proxmox = { + version = "~> 1" + source = "github.com/hashicorp/proxmox" + } + } +} + +source "proxmox-iso" "debian-13-trixie" { + # Proxmox Connection Settings + proxmox_url = "${var.proxmox_api_url}" + username = "${var.proxmox_api_token_id}" + token = "${var.proxmox_api_token_secret}" + + # Skip TLS Verification + insecure_skip_tls_verify = "${var.proxmox_skip_tls_verify}" + + # VM General Settings + node = "${var.proxmox_node}" + vm_id = "${var.template_vm_id}" + vm_name = "debian-13-trixie-${local.timestamp}" + template_description = "Debian 13 Trixie, built with Packer on ${local.timestamp}" + os = "l26" + qemu_agent = true + + # VM Hardware Settings + machine = "q35" + cpu_type = "${var.template_cpu_type}" + cores = 2 + memory = 2048 + bios = "ovmf" + scsi_controller = "virtio-scsi-pci" + disks { + disk_size = "20G" + format = "qcow2" + storage_pool = "${var.disk_storage_pool}" + type = "virtio" + } + + efi_config { + efi_storage_pool = "${var.disk_storage_pool}" + pre_enrolled_keys = true + efi_format = "raw" + efi_type = "4m" + } + + # Download ISO + boot_iso { + type = "scsi" + iso_url = "${var.iso_url}" + unmount = true + iso_storage_pool = "${var.iso_storage_pool}" + iso_checksum = "${var.iso_checksum}" + } + + # VM Network Settings + network_adapters { + model = "virtio" + mac_address = "${var.mac_address}" + bridge = "${var.network_bridge}" + firewall = "false" + } + + # VM Cloud-Init Settings + cloud_init = true + cloud_init_storage_pool = "${var.disk_storage_pool}" + cloud_init_disk_type = "scsi" + + # PACKER Boot Commands + boot = "order=virtio0;scsi0" + boot_wait = "10s" + communicator = "ssh" + boot_command = [ + "c", + "linux /install.amd/vmlinuz auto-install/enable=true priority=critical ", + "DEBIAN_FRONTEND=text preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ks.cfg noprompt", + "initrd /install.amd/initrd.gz", + "DEBCONF_DEBUG=5", + "boot" + ] + + # PACKER Autoinstall Settings + http_directory = "debian/13-trixie/http" + + # SSH Settings + ssh_username = "root" + ssh_password = "packer" + ssh_timeout = "20m" + ssh_pty = true +} + +build { + name = "debian-13-trixie-image" + sources = ["source.proxmox-iso.debian-13-trixie"] + + # Provisioning the VM Template for Cloud-Init Integration in Proxmox #1 + provisioner "shell" { + inline = [ + "rm /etc/ssh/ssh_host_*", + "truncate -s 0 /etc/machine-id", + "apt -y autoremove --purge 2> /dev/null", + "apt -y clean 2> /dev/null", + "apt -y autoclean 2> /dev/null", + "cloud-init clean", + "rm -f /etc/cloud/cloud.cfg.d/subiquity-disable-cloudinit-networking.cfg", + "rm -rf /var/cache/apt/archives /var/lib/apt/lists/*", + "sync" + ] + } + + # Provisioning the VM Template for Cloud-Init Integration in Proxmox #2 + provisioner "file" { + source = "debian/13-trixie/files/99-pve.cfg" + destination = "/tmp/99-pve.cfg" + } + + # Provisioning the VM Template for Cloud-Init Integration in Proxmox #3 + provisioner "shell" { + inline = ["sudo cp /tmp/99-pve.cfg /etc/cloud/cloud.cfg.d/99-pve.cfg"] + } + + # Remove CD-ROM entries from APT sources list + provisioner "shell" { + inline = ["sed -i '/cdrom/d' /etc/apt/sources.list"] + } + + # Add custom APT sources list + provisioner "file" { + source = "debian/13-trixie/files/debian.sources" + destination = "/etc/apt/sources.list.d/debian.sources" + } +} diff --git a/debian/13-trixie/files/99-pve.cfg b/debian/13-trixie/files/99-pve.cfg new file mode 100644 index 0000000..a78672c --- /dev/null +++ b/debian/13-trixie/files/99-pve.cfg @@ -0,0 +1 @@ +datasource_list: [ConfigDrive, NoCloud] \ No newline at end of file diff --git a/debian/13-trixie/files/debian.sources b/debian/13-trixie/files/debian.sources new file mode 100644 index 0000000..95cb2db --- /dev/null +++ b/debian/13-trixie/files/debian.sources @@ -0,0 +1,17 @@ +Types: deb +URIs: http://ftp.de.debian.org/debian/ +Suites: trixie +Components: main contrib non-free non-free-firmware +Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg + +Types: deb +URIs: http://ftp.de.debian.org/debian/ +Suites: trixie-updates +Components: main contrib non-free non-free-firmware +Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg + +Types: deb +URIs: http://security.debian.org/ +Suites: trixie-security +Components: main contrib non-free non-free-firmware +Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg diff --git a/debian/13-trixie/http/ks.cfg b/debian/13-trixie/http/ks.cfg new file mode 100644 index 0000000..f938dbe --- /dev/null +++ b/debian/13-trixie/http/ks.cfg @@ -0,0 +1,78 @@ +# Language +d-i debian-installer/locale string en_US.UTF-8 + +# Keyboard +d-i keyboard-configuration/xkb-keymap select us + +d-i auto-install/enable boolean true +d-i debian-installer/framebuffer boolean false + +# Network +d-i netcfg/choose_interface select ens18 +d-i netcfg/get_hostname string debian_foobar +d-i netcfg/get_domain string +d-i netcfg/wireless_wep string +d-i netcfg/disable_dhcp boolean false + +# Root Password +d-i passwd/make-user boolean false +d-i passwd/root-password password packer +d-i passwd/root-password-again password packer + +# Turn CD Off +d-i apt-setup/cdrom/set-first boolean false +d-i apt-setup/cdrom/set-next boolean false +d-i apt-setup/cdrom/set-failed boolean false + +d-i apt-setup/local0/repository string http://deb.debian.org/debian/ trixie main contrib non-free +popularity-contest popularity-contest/participate boolean false + +### Mirror settings +d-i mirror/country string manual +d-i mirror/http/hostname string http.us.debian.org +d-i mirror/http/directory string /debian +d-i mirror/http/proxy string + +# Timezone +d-i clock-setup/utc boolean true +d-i time/zone string UTC +d-i clock-setup/ntp boolean true + +# Storage +d-i partman-auto/method string lvm +d-i partman-auto-lvm/guided_size string max +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-auto/choose_recipe select atomic +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 + +# Software +d-i debconf debconf/frontend select noninteractive +tasksel tasksel/first multiselect standard, ssh-server + +d-i apt-setup/contrib boolean true +d-i apt-setup/non-free boolean true +d-i apt-setup/security_host string security.debian.org +d-i apt-setup/services-select multiselect security, updates + + +d-i pkgsel/include string qemu-guest-agent cloud-init curl vim +d-i pkgsel/upgrade select full-upgrade +d-i pkgsel/update-policy select none +d-i pkgsel/updatedb boolean true + +d-i preseed/late_command string \ + in-target sed -e 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' -i /etc/ssh/sshd_config + +# Bootloader +d-i grub-installer/only_debian boolean true +d-i grub-installer/with_other_os boolean true +d-i grub-installer/bootdev string default + +# Finish +d-i finish-install/reboot_in_progress note diff --git a/debian/13-trixie/http/meta-data b/debian/13-trixie/http/meta-data new file mode 100644 index 0000000..e69de29 diff --git a/debian/13-trixie/http/user-data b/debian/13-trixie/http/user-data new file mode 100644 index 0000000..2d3a7be --- /dev/null +++ b/debian/13-trixie/http/user-data @@ -0,0 +1,32 @@ +#cloud-config +autoinstall: + version: 1 + locale: en_US + keyboard: + layout: us + ssh: + install-server: true + allow-pw: true + disable_root: true + ssh_quiet_keygen: true + allow_public_ssh_keys: true + apt: + preserve_sources_list: false + packages: + - qemu-guest-agent + - sudo + storage: + layout: + name: direct + swap: + size: 0 + user-data: + package_upgrade: false + timezone: UTC + users: + - name: root + groups: [adm, sudo] + lock-passwd: false + sudo: ALL=(ALL) NOPASSWD:ALL + shell: /bin/bash + passwd: packer diff --git a/debian/13-trixie/variables-common.pkr.hcl b/debian/13-trixie/variables-common.pkr.hcl new file mode 120000 index 0000000..f97f3d6 --- /dev/null +++ b/debian/13-trixie/variables-common.pkr.hcl @@ -0,0 +1 @@ +../../variables-common.pkr.hcl \ No newline at end of file diff --git a/debian/13-trixie/variables.pkr.hcl b/debian/13-trixie/variables.pkr.hcl new file mode 100644 index 0000000..427a80a --- /dev/null +++ b/debian/13-trixie/variables.pkr.hcl @@ -0,0 +1,76 @@ +# Secrets +variable "proxmox_api_token_id" { + type = string + sensitive = true + description = "Proxmox API token ID in the format 'username@realm!tokenname'" +} + +variable "proxmox_api_token_secret" { + type = string + sensitive = true + description = "Proxmox API token secret" +} + + + +# Variables +variable "template_vm_id" { + type = string + default = "65000" + description = "The VM ID of the Proxmox template to use for building the image" +} + +variable "mac_address" { + type = string + default = "BC:24:11:00:13:37" + description = "The MAC address to assign to the VM's network adapter" +} + +variable "iso_url" { + type = string + default = "https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-13.3.0-amd64-netinst.iso" + description = "The URL to download the Debian 13 Trixie ISO" +} + +variable "iso_checksum" { + type = string + default = "file:https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA256SUMS" + description = "ISO checksum (SHA256 or checksum file URL)" +} + +variable "disk_storage_pool" { + type = string + default = "ceph-pool" + description = "The Proxmox storage pool to use for the VM disk" +} + +variable "iso_storage_pool" { + type = string + default = "cephfs" + description = "The Proxmox storage pool to use for the ISO" +} + +variable "template_cpu_type" { + type = string + default = "host" + description = "The CPU type for the Proxmox template" +} + +variable "network_bridge" { + type = string + default = "vmbr9" + description = "The network bridge to attach the VM to" +} + +variable "proxmox_node" { + type = string + default = "sbx0pve02" + description = "The Proxmox node to use for building the image" +} + + + +# local values +local "timestamp" { + expression = formatdate("YYYYMMDD-hhMMss-ZZZ", timestamp()) +} diff --git a/mise.toml b/mise.toml new file mode 100644 index 0000000..46c619a --- /dev/null +++ b/mise.toml @@ -0,0 +1,42 @@ + +[tasks.lint] +usage = ''' +arg "" help="Directory containing the Packer template to lint e.g. debian/13-trixie" +''' +run = ''' +packer fmt --recursive --check ${usage_dir?} \ + && packer validate ${usage_dir?} +''' + +[tasks.fmt] +usage = ''' +arg "" help="Directory containing the Packer template to format e.g. debian/13-trixie" default="." +''' +run = "packer fmt --recursive ${usage_dir?}" + +[tasks.build] +usage = ''' +arg "" help="Directory containing the Packer template to build e.g. debian/13-trixie" +''' +run = ''' +mise run lint ${usage_dir?} \ + && packer build ${usage_dir?} +''' + +[tasks.init] +usage = ''' +arg "" help="Directory containing the Packer template to initialize e.g. debian/13-trixie" +''' +run = "packer init ${usage_dir?}" + +[tasks.setup] +usage = ''' +arg "" help="The Linux distribution name (e.g. debian)" +arg "" help="The Linux distribution version (e.g. 13-trixie)" +''' +run = ''' +mkdir -p ${usage_distribution?}/${usage_version?} \ + && ln -s ../../credentials.auto.pkrvars.hcl ${usage_distribution?}/${usage_version?}/credentials.auto.pkrvars.hcl \ + && ln -s ../../variables-common.pkr.hcl ${usage_distribution?}/${usage_version?}/variables-common.pkr.hcl \ + && touch ${usage_distribution?}/${usage_version?}/${usage_distribution?}-${usage_version?}.pkr.hcl +''' diff --git a/template-credentials.pkrvars.hcl b/template-credentials.pkrvars.hcl new file mode 100644 index 0000000..ba7c7cd --- /dev/null +++ b/template-credentials.pkrvars.hcl @@ -0,0 +1,2 @@ +proxmox_api_token_id = "" +proxmox_api_token_secret = "" diff --git a/variables-common.pkr.hcl b/variables-common.pkr.hcl new file mode 100644 index 0000000..ad0edd8 --- /dev/null +++ b/variables-common.pkr.hcl @@ -0,0 +1,11 @@ +variable "proxmox_api_url" { + type = string + default = "https://sbx0pve00.int.r3w.de:8006/api2/json" + description = "Proxmox VE API URL" +} + +variable "proxmox_skip_tls_verify" { + type = bool + default = false + description = "Whether to skip TLS verification for Proxmox API" +}