Packer Templates Examples¶
Ubuntu 16.04.2 LTS¶
Simple example for Ubuntu using the qemu
builder and outputs a qcow2 image.
While booting the ISO, packer
will enter the template's boot command which contains the path to a unattended configuration file (like kickstart/preseed).
Once the installation finishes, the VM is rebooted and is ready to be provisioned by, e.g., an ansible playbook (more on that later).
To support ansible "out of the box", both openssh-server
and ansible
are installed during the unattended install phase.
Here a sample packer template file for Ubuntu 16.04:
{ "builders": [{ "type": "qemu", "iso_url": "http://releases.ubuntu.com/16.04/ubuntu-16.04.2-server-amd64.iso", "iso_checksum": "737ae7041212c628de5751d15c3016058b0e833fdc32e7420209b76ca3d0a535", "iso_checksum_type": "sha256", "output_directory": "output-ubuntu-16.04-amd64-{{build_type}}", "vm_name": "packer-ubuntu-16.04-amd64", "disk_size": "40000", "format": "qcow2", "headless": "true", "http_directory": "http", "boot_wait": "5s", "boot_command": [ "<enter><wait>", "<f6><esc>", "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>", "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>", "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>", "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>", "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>", "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>", "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>", "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>", "<bs><bs><bs>", "/install/vmlinuz ", "initrd=/install/initrd.gz ", "auto-install/enable=true ", "debconf/priority=critical ", "preseed/url=http://{{.HTTPIP}}:{{.HTTPPort}}/ubuntu-preseed.cfg ", "<enter>" ], "ssh_timeout": "10m", "ssh_username": "root", "ssh_password": "s0m3p4ss", "shutdown_command": "systemctl poweroff" }] }
... and the preseed file for the debian-installer:
d-i debian-installer/locale string en_US d-i time/zone string UTC d-i keyboard-configuration/xkb-keymap select de d-i partman-basicfilesystems/choose_label string gpt d-i partman-basicfilesystems/default_label string gpt d-i partman-basicfilesystems/no_swap boolean false d-i partman-partitioning/choose_label string gpt d-i partman-partitioning/default_label string gpt d-i partman/choose_label string gpt d-i partman/default_label string gpt d-i partman-auto/method string regular d-i partman-auto/expert_recipe string \ scheme :: \ 32 32 32 free \ $gptonly{ } \ $primary{ } \ $bios_boot{ } \ method{ biosgrub } . \ 1 0 -1 ext4 \ $gptonly{ } \ $primary{ } \ method{ format } \ format{ } \ use_filesystem{ } \ filesystem{ ext4 } \ label{ SLX_SYS } \ 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 d-i base-installer/excludes string laptop-detect d-i passwd/make-user boolean false d-i passwd/root-login boolean true d-i passwd/root-password-crypted password $6$6yzbOJJy5auuBh9$XUAtAt/ErLkz6.1t8J4UpyZPPUbKjGO1uATaZaxmG02IhJbOwnJMqI6MTJw.SzbBvy8THCmmoia1tVMfXhGVJ1 d-i pkgsel/include string openssh-server ansible d-i finish-install/reboot_in_progress note
CentOS 7.3¶
Slighty more complex example showing how to support multiple builders, here virtualbox, vmware and qemu.
This also shows the use of variables shared accross mutliple builders.
{ "builders": [{ "type": "qemu", "iso_url": "{{user `mirror`}}/7/isos/x86_64/CentOS-7-x86_64-NetInstall-1611.iso", "iso_checksum": "{{user `iso_checksum`}}", "iso_checksum_type": "{{user `iso_checksum_type`}}", "output_directory": "output-centos-7.3-x86_64-{{build_type}}", "vm_name": "packer-centos-7.3-x86_64", "format": "qcow2", "disk_size": "{{user `disk_size`}}", "disk_interface": "virtio-scsi", "headless": "{{user `headless`}}", "http_directory": "http", "boot_wait": "5s", "boot_command": [ "<esc>", "<wait>", "linux inst.gpt inst.ks=http://{{.HTTPIP}}:{{.HTTPPort}}/anaconda-ks.cfg biosdevname=0 net.ifnames=0", "<enter>" ], "ssh_timeout": "{{user `ssh_timeout`}}", "ssh_username": "{{user `ssh_username`}}", "ssh_password": "{{user `ssh_password`}}", "shutdown_command": "sudo systemctl poweroff", "qemuargs": [ ["-m", "{{user `memory`}}"], ["-smp", "{{user `cpus`}}"] ] }, { "type": "virtualbox-iso", "guest_os_type": "RedHat_64", "iso_url": "{{user `mirror`}}/7/isos/x86_64/CentOS-7-x86_64-NetInstall-1611.iso", "iso_checksum": "{{user `iso_checksum`}}", "iso_checksum_type": "{{user `iso_checksum_type`}}", "output_directory": "output-centos-7.3-x86_64-{{build_type}}", "vm_name": "packer-centos-7.3-x86_64", "disk_size": "40000", "headless": "true", "http_directory": "http", "boot_wait": "5s", "boot_command": [ "<esc>", "<wait>", "linux inst.gpt inst.ks=http://{{.HTTPIP}}:{{.HTTPPort}}/centos-7.3/anaconda-ks.cfg biosdevname=0 net.ifnames=0", "<enter>" ], "ssh_timeout": "{{user `ssh_timeout`}}", "ssh_username": "{{user `ssh_username`}}", "ssh_password": "{{user `ssh_password`}}", "shutdown_command": "systemctl poweroff", "vboxmanage": [ ["modifyvm", "{{.Name}}", "--memory", "{{user `memory`}}"], ["modifyvm", "{{.Name}}", "--cpus", "{{user `cpus`}}"] ] }, { "type": "vmware-iso", "guest_os_type": "centos-64", "iso_url": "{{user `mirror`}}/7/isos/x86_64/CentOS-7-x86_64-NetInstall-1611.iso", "iso_checksum": "{{user `iso_checksum`}}", "iso_checksum_type": "{{user `iso_checksum_type`}}", "output_directory": "output-centos-7.3-x86_64-{{build_type}}", "vm_name": "packer-centos-7.3-x86_64", "disk_size": "{{user `disk_size`}}", "headless": "{{user `headless`}}", "http_directory": "http", "boot_wait": "5s", "boot_command": [ "<esc>", "<wait>", "linux inst.gpt inst.ks=http://{{.HTTPIP}}:{{.HTTPPort}}/centos-7.3/anaconda-ks.cfg biosdevname=0 net.ifnames=0", "<enter>" ], "ssh_timeout": "{{user `ssh_timeout`}}", "ssh_username": "{{user `ssh_username`}}", "ssh_password": "{{user `ssh_password`}}", "tools_upload_flavor": "linux", "shutdown_command": "systemctl poweroff", "vmx_data": { "memsize": "{{user `memory`}}", "numvcpus": "{{user `cpus`}}" } }], "variables": { "cpus": "1", "disk_size": "40000", "headless": "false", "iso_checksum": "f2f7367deb90a25822947660c71638333ca0eceeabecc2d631be6cd508c24494", "iso_checksum_type": "sha256", "memory": "1024", "mirror": "http://mirrors.kernel.org/centos", "ssh_timeout": "60m", "ssh_username": "root", "ssh_password": "s0m3p4ss" } }
... and the kickstart file:
install text reboot url --mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os lang en_US.UTF-8 keyboard --vckeymap=de-nodeadkeys --xlayouts='de (nodeadkeys)' timezone Europe/Berlin --isUtc --nontp auth --enableshadow --passalgo=sha512 rootpw --iscrypted $6$6yzbOJJy5auuBh9$XUAtAt/ErLkz6.1t8J4UpyZPPUbKjGO1uATaZaxmG02IhJbOwnJMqI6MTJw.SzbBvy8THCmmoia1tVMfXhGVJ1 clearpart --none --initlabel bootloader --location=mbr --boot-drive=sda part biosboot --fstype="biosboot" --ondisk=sda --size=1 part / --fstype="ext4" --ondisk=sda --grow --label=SLX_SYS %packages @^minimal @core kexec-tools %end %post --erroronfail yum -y update yum -y install wget wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm rpm -ivh epel-release-latest-7.noarch.rpm yum -y install ansible # allow root login for ansible sed 's,^[[:blank:]]*#*PermitRootLogin.*,PermitRootLogin yes,g' /etc/ssh/sshd_config # instruct the VM to do DHCP on reboot ln -s /dev/null /etc/udev/rules.d/80-net-name-slot.rules cat > /etc/sysconfig/network-scripts/ifcfg-eth0 <<EOF DEVICE="eth0" BOOTPROTO="dhcp" ONBOOT="yes" TYPE="Ethernet" EOF %end
Note that this kickstart sets up the EPEL repo needed to install ansible and, more interestingly, triggers an update to (hopefully) get the latest kernel.
Without an update during the initial installation phase, the VM's kernel might be outdated.
Thus, one would need to update packages and reboot the VM to make sure the latest kernel is running.
Since a package update is mandatory anyway, it makes sense to trigger it as early as possible to avoid unnecessary reboots.
Password management¶
The naive way of specifying the password in cleartext is suboptimal for obvious reasons.
Since both preseed and kickstart support hashed passwords, these should be used whenever possible!
Packer requires the password in cleartext in its templates to be able to connect to the VMs after starting them.
Instead of using static passwords in the templates saved on the repo (requiring the users to change them before building them), the password can be given per environment variable and evaluated within a packer template with:
(...) "ssh_password":"{{ env `ROOTPW` }}" (...)
Preseed¶
For distros supporting preseed, it can be specified directly in the kernel command line with passwd/root-password
:
(...) "passwd/root-password={{ user `ssh_password` }} ", "passwd/root-password-again={{ user `ssh_password` }} ", (...)
Kickstart¶
Kickstart has no way (that I know of) to configure the root password via kernel command line.
Still, the password can be passed by packer via boot command (here as rootpw
) and post-processed by a script:
(...) %pre --interpreter=/usr/bin/python import shlex, crypt arg = 'rootpw=' with open('/proc/cmdline', 'r') as f: kcl = f.read().split() # extract the password passwords = [x[len(arg):] for x in kcl if x.startswith(arg)] if len(passwords) == 1: kclpass = passwords[0] # generate SHA512 hash hash = crypt.crypt(kclpass, crypt.mksalt(crypt.METHOD_SHA512)) with open('/tmp/setup-root-pass', 'w') as f: f.write('rootpw --iscrypted ' + hash) %end # include the created password file %include /tmp/setup-root-pass
The trick is to create an include file with a call of the rootpw
directive with a generated SHA-512 hash of the given password.
Including the generated file (/tmp/setup-root-pass
) would then instruct kickstart to use the given password as root password.
Updated by Jonathan Bauer about 7 years ago · 3 revisions