Skip to content

trfore/proxmox-template-scripts

Repository files navigation

Creating Proxmox Templates with cloud-init

Collection of example cloud-init config files and shell scripts to download cloud-images and create Proxmox templates.

Blog post: Golden Images and Proxmox Templates with cloud-init

Cloud-init Files

Shell Scripts

  • build-template: Create a proxmox template.
    • For systems using ZFS storage, a script with local-zfs defaults is available: build-template (ZFS).
  • image-update: Check for an updated image and download the latest or missing image.
    • Works with centos, debian, fedora and ubuntu cloud images.
    • Requires curl
    • Note: This script will change the file extension to *.img for visibility in the Proxmox GUI, qm disk import will automatically convert disk image.

Systemd Templates

Use

  • Create or copy vendor-data.yaml into your snippets storage location, e.g. /var/lib/vz/snippets/ (default directory for the script):

    wget -P /var/lib/vz/snippets/ https://raw.githubusercontent.com/trfore/proxmox-template-scripts/refs/heads/main/cloud-init/vendor-data.yaml
  • Copy the scripts into /usr/local/bin on your Proxmox node(s):

    • For Systems using LVM Storage (Default) - scripts

      wget -P /usr/local/bin/ https://raw.githubusercontent.com/trfore/proxmox-template-scripts/refs/heads/main/scripts/{build-template,image-update}
    • For Systems using ZFS Storage - scripts-zfs

      wget -P /usr/local/bin/ https://raw.githubusercontent.com/trfore/proxmox-template-scripts/refs/heads/main/scripts/{image-update}
      wget -P /usr/local/bin/ https://raw.githubusercontent.com/trfore/proxmox-template-scripts/refs/heads/main/scripts-zfs/{build-template}
  • Change the scripts ownership and permissions:

    chown root:root /usr/local/bin/{build-template,image-update}
    chmod +x /usr/local/bin/{build-template,image-update}
  • Confirm /usr/local/bin is added to PATH:

    root@pve:~$ echo $PATH
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    
    # test using tab-completion
    image[TAB] -> image-update

Image Download / Update Script

# SSH into your Proxmox host
user@desktop:~$ ssh root@pve

# usage
root@pve:~$ image-update -d <DISTRO_NAME> -r <RELEASE_NAME> [ARGS]
Code Examples
image-update -d centos -r 9
image-update -d debian -r 12
image-update -d fedora -r 42
image-update -d ubuntu -r 24
Alternative Usage
# usage
image-update <DISTRO_NAME>-<RELEASE_NAME> [ARGS]
# example
image-update ubuntu-24 --remove
CLI Flags Description Default Required
--distro, -d Specify the distribution name, e.g. ubuntu. Yes
--release, -r Specify the release name, e.g. focal or 20. Yes
--backup, -b Backup the existing image before updating. Not compatible with --remove false No
--date Append the date to the image name, e.g. ubuntu*-$DATE.img false No
--remove Remove image and backups before updating. Not compatible with --backup false No
--storage, -s Specify the image storage path /var/lib/vz/template/iso No

Adding the --backup flag will backup existing images for the set distribution and release before downloading the latest image, using the naming scheme: IMAGE_NAME.backup.img.

Adding the --date flag will append the release date to name in YYYY-MM-DD or YYYY-MMM-DD format, e.g. ubuntu-24.04-server-cloudimg-amd64-YYYY-MM-DD.img. The format is not configurable as it is pulled from the distribution's release page.

Automatically Check for Updates Using Cron

The majority of images are updated every 1 to 2 months, so be considerate and don't check more than once a month for new cloud images. Note: Consider staggering cron jobs to different minute (0), hour (2), and day (10) across distributions and releases.

0 2 10 * * /usr/local/bin/image-update -d <distro_name> -r <release_name>

Example:

# create/edit crontab
crontab -e

# create a job
10 3 15 * * /usr/local/bin/image-update -d ubuntu -r focal

Automatically Check for Updates Using Systemd Timers

Note on Distro Release Frequency

Please consider the typical release frequency when creating timers, as there is little advantage to creating daily or weekly timers.

  • Centos: monthly, at the end of the month.
  • Debian: bi-weekly to monthly.
  • Fedora: single release, no reason to create a timer for any version.
  • Ubuntu: bi-weekly, typically during the 2nd and 4th week of a month.

The image-update script can also parse a single argument for distribution and release, image-update ubuntu-24, which is useful in creating systemd timers. You can still pass the --remove and --storage flags as well, however, --distro and --release are overridden when using this approach.

To use systemd timers, add the template files to the /etc/systemd/system directory and start at step 3. Or create a service and timer template, as follows:

  1. Create a service, [email protected], in the /etc/systemd/system directory. Add additional script flags to ExecStart= after %i.

    [Unit]
    After=network-online.target
    Description= Check for updated cloud image %i
    Documentation=https://github.com/trfore/proxmox-template-scripts
    
    [Service]
    Type=oneshot
    ExecStart=/usr/local/bin/image-update %i --remove
  2. Create a timer, [email protected], in the /etc/systemd/system directory. Note: Change the day and time this script runs on, OnCalendar=*-*-10 02:00:00. To prevent multiple timers from triggering simultaneously, RandomizedDelaySec=3h will randomly select a time within a 3-hour window and AccuracySec=1us will prevent systemd from grouping the timers.

    [Unit]
    Description=Check for updated cloud image %i
    Documentation=https://github.com/trfore/proxmox-template-scripts
    
    [Timer]
    OnCalendar=*-*-10 02:00:00
    AccuracySec=1us
    RandomizedDelaySec=3h
    Persistent=true
    
    [Install]
    WantedBy=timers.target
  3. Reload the systemd configuration

    systemctl daemon-reload
  4. Create a Timer, using the format image-update@<DISTRO>-<RELEASE>.timer

    # enable and start a timer
    systemctl enable [email protected] --now

Additional commands:

# view all timers
systemctl list-timers --all

# view timer status
systemctl status [email protected]

# disable a timer
systemctl disable [email protected]

# view script update logs
systemctl status [email protected]

Proxmox Template Script

build-template: A wrapper script around qm to build Proxmox templates. This script assumes the use of cloud-init vendor data file located at local:snippets/vendor-data.yaml. Detailed usage available on the blog post: Golden Images and Proxmox Templates with cloud-init, and example file: cloud-init/vendor-data-minimal.yaml.

# usage
build-template -i <vm_id> -n <vm_name> --img <vm_image> [ARGS]

Example:

build-template -i 9000 -n ubuntu24 --img /var/lib/vz/template/iso/ubuntu-24.04-server-cloudimg-amd64.img
CLI Flags Description Default Required
--id, -i Specify the VM ID (1-999999999) 9000 Yes
--name, -n Specify the VM name template Yes
--image, --img Specify the VM image (path), ex: /PATH/TO/image.{img,iso,qcow2} Yes
--bios, -b Specify the VM bios, seabios or ovmf seabios No
--machine Specify the VM machine type, q35 or pc for i440 q35 No
--memory, -m Specify the VM memory 1024 No
--net-bridge Specify the VM network bridge vmbr0 No
--net-type Specify the VM network type virtio No
--net-vlan Specify the VM network vlan tag 1 No
--os Specify the VM OS l26 No
--resize Increase the VM boot disk size 1G No
--storage, -s Specify the VM storage local-lvm No
--scsihw Specify the VM storage controller virtio-scsi-pci No
--vendor-file Specify the cloud-init vendor file vendor-data.yaml No

Maintainers & License

Taylor Fore (https://github.com/trfore)

See LICENSE File

References

Blog Post:

Linux Cloud Images:

Proxmox: