Collection of scripts to manage Proxmox environments.
Please read section Using Docker on LXC if you are planning to use Docker with Linux Containers (LXC).
To migrate an existing Windows VM from Hyper-V to Proxmox see this other project (for Windows) first.
To download all scripts into a temporary folder:
source <(curl -Ls https://bit.ly/p-v-a)This will download and execute bootstrap.sh. It will also install unzip apt package.
- download-cloud-image
- download-cloud-template
- download-verified-file
- download-virtio-image
- new-ct
- new-vm
- new-vm-windows
- import-vm-windows
- remove-windows-iso-prompt
- remove-nag-subscription
- setup-pbs
- setup-pve
Usage: ./download-cloud-image.sh <url> [OPTIONS]
<url> Url of image to download.
--no-clobber, -nc Doesn't overwrite an existing image.
--help, -h Display this help message.
Downloads an image from given url into /var/lib/vz/template/iso/ folder.
If the image already exists it will not be downloaded again.
If the file is compressed with gz, xz or zip it will also uncompress it.
Returns the full path of downloaded image.
# Download Debian 12 image
DEBIAN_URL='https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2'
./download-cloud-image.sh $DEBIAN_URLUsage: ./download-cloud-template.sh <url> [OPTIONS]
<url> Url of template to download.
--filename, -f Renames the downloaded file.
--no-clobber, -nc Doesn't overwrite an existing template.
--help, -h Display this help message.
Downloads a LXC template from given url into /var/lib/vz/template/cache/ folder.
You can use --filename to rename the resulting file.
If the template already exists it will not be downloaded again.
Please note that this script DOES NOT uncompress the resulting file. LXCs templates can be used in compressed format.
Returns the full path of downloaded template.
# Download OpenWRT template
OPENWRT_URL='https://images.linuxcontainers.org/images/openwrt/23.05/amd64/default/20241109_11:57/rootfs.tar.xz'
OPENWRT_TEMPLATE_NAME='openwrt-23.05-amd64-default-20241109.tar.xz'
./download-cloud-template.sh $OPENWRT_URL --filename $OPENWRT_TEMPLATE_NAMEUsage: ./download-verified-file.sh <url> <sha256> [target_directory] [OPTIONS]
<url> Url of file to download.
<sha256> Expected SHA-256 hash of the file.
[target_directory] Directory to save the file (default: /tmp).
--help, -h Display this help message.
Downloads a file from given url into the specified directory (defaults to /tmp) and verifies its SHA-256 hash.
If the file already exists and its hash matches, it will not be downloaded again.
If the file exists but the hash does not match, it will be re-downloaded and overwritten.
Returns the full path of downloaded file.
# Download Windows Server 2022 (Evaluation) with hash verification
WIN_SERVER_URL='https://software-download.microsoft.com/download/sg/20348.169.210806-2348.fe_release_svc_refresh_SERVER_EVAL_x64FRE_en-us.iso'
WIN_SERVER_SHA256='4f1457c4fe14ce48c9b2324924f33ca4f0470475e6da851b39ccbf98f44e7852'
./download-verified-file.sh $WIN_SERVER_URL $WIN_SERVER_SHA256
# Download to a specific directory
./download-verified-file.sh $WIN_SERVER_URL $WIN_SERVER_SHA256 /var/lib/vz/template/isoUsage: ./download-virtio-image.sh [output_path] [OPTIONS]
output_path Path to save the ISO (directory or full file path). Defaults to /var/lib/vz/template/iso/.
--no-clobber, -nc Doesn't overwrite an existing ISO.
--help, -h Display this help message.
Downloads the VirtIO drivers ISO from Fedora's repository into the specified folder or path.
If the ISO already exists it will not be downloaded again unless --no-clobber is not used.
Returns the full path of downloaded ISO.
# Download VirtIO drivers ISO to default location
./download-virtio-image.sh
# Download to a custom directory
./download-virtio-image.sh /tmp/Usage: ./new-ct.sh <ctid> --ostemplate <file> --hostname <name> --password <password> [OPTIONS]
<ctid> Proxmox unique ID of the CT.
--ostemplate The OS template or backup file.
--hostname Set a host name for the container.
--password Sets root password inside container.
--sshkey[s] Setup public SSH keys (one key per line, OpenSSH format).
Additional options:
--ostype OS type (default = ubuntu).
--cores Number of cores per socket (default = unlimited).
--memory Amount of RAM for the VM in MB (default = 2048).
--rootfs Use volume as container root (default = local-zfs:120).
--privileged Makes the container run as privileged user (default = unprivileged).
--bridge Use bridge for container networking (default = vmbr0).
--hwaddr MAC address for eth0 interface.
--vlan VLAN tag ID for the network interface.
--install-docker Install docker and docker-compose.
--no-start Do not start the container after creation.
--help, -h Display this help message.
Creates a LXC container (CT).
Additionally, you can use --install-docker to also install docker into container (currently implemented only for Ubuntu, Debian and Alpine). In this case, please see section Using Docker on LXC for more information.
Any additional arguments are passed to pct create command. Please see pct command documentation for more information about the options.
# Download Ubuntu 24.04 LTS image
UBUNTU_IMAGE='ubuntu-24.04-standard_24.04-2_amd64.tar.zst'
UBUNTU_TEMPLATE="local:vztmpl/$UBUNTU_IMAGE"
pveam download local $UBUNTU_IMAGE
# Creates an Ubuntu LXC container with a 120G storage, "id_rsa.pub" ssh key and Docker installed.
CT_ID=310
CT_NAME='ct-ubuntu'
./new-ct.sh $CT_ID \
--memory 1024 \
--ostemplate $UBUNTU_TEMPLATE \
--hostname $CT_NAME \
--sshkey ~/.ssh/id_rsa.pub \
--rootfs local-zfs:120 \
--install-docker# Download OpenWRT image
OPENWRT_URL='https://images.linuxcontainers.org/images/openwrt/23.05/amd64/default/20241109_11:57/rootfs.tar.xz'
OPENWRT_TEMPLATE_NAME='openwrt-23.05-amd64-default-20241109.tar.xz'
OPENWRT_TEMPLATE=$(./download-cloud-template.sh $OPENWRT_URL --filename $OPENWRT_TEMPLATE_NAME)
# Creates an OpenWRT privileged LXC container with a 8G storage, two named network interfaces and sets root password.
CT_ID=311
CT_NAME='ct-openwrt'
CT_PASSWORD='uns@f3'
CT_LAN_IFNAME='lan'
CT_LAN_BRIDGE='vmbrloc0' # Do NOT use your LAN here! (will start a DHCP server on it).
CT_WAN_IFNAME='wan'
CT_WAN_BRIDGE='vmbr0'
./new-ct.sh $CT_ID \
--ostype unmanaged \
--arch amd64 \
--memory 1024 \
--ostemplate $OPENWRT_TEMPLATE \
--hostname $CT_NAME \
--password $CT_PASSWORD \
--rootfs local-zfs:8 \
--privileged \
--no-start \
--net0 name=$CT_LAN_IFNAME,bridge=$CT_LAN_BRIDGE \
--net1 name=$CT_WAN_IFNAME,bridge=$CT_WAN_BRIDGE,ip=dhcp,ip6=auto
# Load initial OpenWRT configuration
CT_ROOT_MOUNTPOINT="/rpool/data/subvol-$CT_ID-disk-0"
cat > "$CT_ROOT_MOUNTPOINT/etc/uci-defaults/80-init" << OUTER_EOF
#!/bin/sh
# System
uci batch << EOF
set system.@system[0].hostname='{{ openwrt.hostname }}'
commit system
EOF
# Network interfaces
uci batch << EOF
set network.lan=interface
set network.lan.ifname='$CT_LAN_IFNAME'
set network.lan.proto='static'
set network.lan.ipaddr='192.168.1.1'
set network.lan.netmask='255.255.255.0'
set network.wan=interface
set network.wan.ifname='$CT_WAN_IFNAME'
set network.wan.proto='dhcp'
set network.wan.zone='wan'
commit network
EOF
OUTER_EOF
# Set passwd for LUCI
cat > "$CT_ROOT_MOUNTPOINT/etc/uci-defaults/81-passwd" << OUTER_EOF
#!/bin/sh
passwd << EOF
$CT_PASSWORD
$CT_PASSWORD
EOF
OUTER_EOF
# Start the LXC Container
pct start $CT_IDOpenWRT offers extensive configuration options through the UCI system.
More information about the uci-defaults folder can be found here.
Usage: ./new-vm.sh <vmid> --image <file> --name <name> [--cipassword <password>] | [--sshkey[s] <filepath>] [OPTIONS]
<vmid> Proxmox unique ID of the VM.
--image Path to image file.
--name A name for the VM.
--cipassword Password to assign the user. Using this is generally not recommended. Use ssh keys instead.
--sshkey[s] Setup public SSH keys (one key per line, OpenSSH format).
Additional options:
--ostype Guest OS type (default = l26).
--cores Number of cores per socket (default = 2).
--memory Amount of RAM for the VM in MB (default = 2048).
--disksize Size of VM main disk (default = 120G).
--balloon Amount of target RAM for the VM in MB. Using zero (default) disables the ballon driver.
--hwaddr MAC address for the network interface.
--vlan VLAN tag ID for the network interface.
--install-docker Install docker and docker-compose.
--help, -h Display this help message.
Creates a VM from a cloud image.
You can use any image containing cloud-init and qemu-guest-agent installed.
Additionally, you can use --install-docker to also install docker into virtual machine (currently implemented only for Ubuntu).
Any additional arguments are passed to qm create command. Please see qm command documentation for more information about the options.
# Download Ubuntu 24.04 LTS image
UBUNTU_URL='https://cloud-images.ubuntu.com/releases/noble/release/ubuntu-24.04-server-cloudimg-amd64.img'
UBUNTU_IMAGE_FILE=$(./download-cloud-image.sh $UBUNTU_URL --no-clobber)
# Creates an Ubuntu VM with "id_rsa.pub" ssh key and Docker installed.
VM_ID=401
./new-vm.sh $VM_ID --image $UBUNTU_IMAGE_FILE --name 'vm-ubuntu' --sshkey ~/.ssh/id_rsa.pub --install-docker# Download Debian 12 image
DEBIAN_URL='https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2'
DEBIAN_IMAGE_FILE=$(./download-cloud-image.sh $DEBIAN_URL --no-clobber)
# Creates a Debian VM with "id_rsa.pub" ssh key and Docker installed.
VM_ID=402
./new-vm.sh $VM_ID --image $DEBIAN_IMAGE_FILE --name 'vm-debian' --sshkey '~/.ssh/id_rsa.pub' --install-dockerUsage: ./new-vm-windows.sh <vmid> --iso <file> --name <name> --cipassword <password> [OPTIONS]
<vmid> Proxmox unique ID of the VM.
--iso Path to Windows ISO file.
--name A name for the VM (hostname).
--cipassword Password for the Administrator account.
Additional options:
--ostype Guest OS type (default = win11).
--cores Number of cores per socket (default = 2).
--memory Amount of RAM for the VM in MB (default = 4096).
--storage Storage to use for VM disks (default = local-zfs).
--disksize Size of VM main disk (default = 120G).
--image-index Windows image index to install (default = 1).
--virtio-iso Path to VirtIO drivers ISO (default = /var/lib/vz/template/iso/virtio-win.iso).
--hwaddr MAC address for the network interface.
--vlan VLAN tag ID for the network interface.
--no-start Do not start the VM after creation.
--no-guest Do not wait for QEMU Guest Agent after start.
--help, -h Display this help message.
Creates a Windows VM from a Windows installation ISO with automated unattended installation.
The script automatically:
- Installs VirtIO drivers for optimal performance
- Installs QEMU Guest Agent during setup
- Configures the Administrator password and other options passed by Proxmox cloud-init configuration.
- This script uses the
PSCloudInit.ps1script during the VM’s first run. You can learn more about it here.
- This script uses the
Requires the VirtIO drivers ISO. Download it with ./download-virtio-image.sh.
Any additional arguments are passed to qm create command. Please see qm command documentation for more information about the options.
# Download VirtIO drivers ISO (required)
./download-virtio-image.sh
# Create Windows Server 2022 VM
VM_ID=501
WINDOWS_ISO='/var/lib/vz/template/iso/windows-server-2022.iso'
./new-vm-windows.sh $VM_ID \
--iso $WINDOWS_ISO \
--name 'win-server-2022' \
--cipassword 'YourP@ssw0rd!' \
--memory 8192 \
--cores 4 \
--disksize 200G# Create Windows 11 VM with custom settings
VM_ID=502
WINDOWS_ISO='/var/lib/vz/template/iso/windows-11.iso'
./new-vm-windows.sh $VM_ID \
--iso $WINDOWS_ISO \
--name 'win11-desktop' \
--cipassword 'YourP@ssw0rd!' \
--ostype win11 \
--memory 8192 \
--cores 4 \
--image-index 1Note: The --image-index parameter selects which Windows edition to install from the ISO (e.g., 1 for Standard, 2 for Datacenter). Use dism /Get-ImageInfo /ImageFile:X:\sources\install.wim on Windows to see available indices in your ISO.
Usage: ./import-vm-windows.sh <vmid> --image <file> --name <name> [OPTIONS]
<vmid> Proxmox unique ID of the VM.
--image Source image to import (.vhdx | .qcow2).
--name A name for the VM.
Additional options:
--ostype Guest OS type (default = win11).
--cores Number of cores per socket (default = 2).
--memory Amount of RAM for the VM in MB (default = 2048).
--no-start Do not start the VM after creation.
--no-guest Do not wait for QEMU Guest Agent after start.
--help, -h Display this help message.
Creates a VM from a vhdx image. For Generation 2 (UEFI) types only.
The image will be imported as a raw image format. The original vhdx file remains unaltered.
Any additional arguments are passed to qm create command. Please see qm command documentation for more information about the options.
After creation, the script will start the VM and wait for the QEMU Guest Agent to be responsive. These actions can be skipped using the --no-start and --no-guest options, respectively.
It's recommended that the vhdx includes the following:
- Windows VirtIO Drivers (recommended)
- QEMU Guest Agent (recommended)
Please refer to Hyper-V Automation project for more information.
Creates a Windows VM from a previously prepared vhdx of an existing Hyper-V VM.
VM_ID=104
./import-vm-windows.sh $VM_ID --image '/tmp/TstWindows.vhdx' --name 'TstWindows'
# Query ipv4 addresses
qm guest cmd $VM_ID network-get-interfaces | \
jq -r '.[] | .["ip-addresses"][] | select(.["ip-address-type"]=="ipv4") | .["ip-address"]'Usage: ./remove-windows-iso-prompt.sh <iso_file> [output_file] [OPTIONS]
<iso_file> Path to Windows ISO file.
[output_file] Path for modified ISO (default: <iso_file>.noprompt.iso).
--help, -h Display this help message.
Rebuilds a Windows ISO to use the no-prompt EFI boot image.
This script modifies a Windows installation ISO to automatically boot without requiring a "Press any key to boot from CD/DVD" prompt. It replaces the standard efisys.bin with the efisys_noprompt.bin version included in official Windows ISOs.
The script requires genisoimage and isoinfo packages to be installed. If not available, install with: apt-get install genisoimage.
# Create a no-prompt version of Windows Server 2025 ISO
./remove-windows-iso-prompt.sh /var/lib/vz/template/iso/windows-server-2025.iso
# Specify custom output path
./remove-windows-iso-prompt.sh /var/lib/vz/template/iso/windows-11.iso /tmp/windows-11-noprompt.isoUsage: ./remove-nag-subscription.sh
Removes Proxmox VE / Proxmox Backup Server nag dialog from web UI.
Usage: ./setup-pbs.sh
First-time setup for Proxmox Backup Server.
Remove enterprise (subscription-only) sources and adds pbs-no-subscription repository provided by proxmox.com. NOT recommended for production use.
This script must be run only once.
Usage: ./setup-pve.sh
First-time setup for Proxmox VE.
Remove enterprise (subscription-only) sources and adds pve-no-subscription repository provided by proxmox.com. NOT recommended for production use.
This script must be run only once.
The following is a compilation about the subject I found around the net. Please read if you wish to follow this path.
Using Docker on LXC is not recommended by Proxmox team. However, certain features of LXC like reduced memory usage and bind mount points between containers and host may be an incentive to go against this recommendation.
Two discussions about the pros and cons of each alternative may be found here and here.
Backups (both to local storage and to Proxmox Backup Server) work fine.
However, please note that the contents of /var/lib/docker will be included in backups by default. This is probably NOT what you want.
This folder often grows in size very quickly. And its contents (except for Docker volumes, see below) may easily be downloaded or rebuilt.
To avoid this, you may use a .pxarexclude file to exclude its contents from the backup archive.
cat > /.pxarexclude <<EOF
/var/lib/docker/
EOFPlease note that in this case you SHOULD NOT use Docker volumes to store any persistent data which is important since they are kept at this location (and, again, will not be included in backups).
Instead you should use Docker bind mounts which mounts a file or directory from the Docker host (LXC, in our case) into a Docker container. All files from LXC filesystem will be included into backups.
Proxmox VE 8.1 uses ZFS 2.2 which finally supports overlay2 out of the box.
All previous workarounds should be considered deprecated.
Starting with Proxmox VE 8.1 the new-ct.sh script will always assume --no-docker-volume, never creating the workaround volume needed for previous Proxmox VE versions.