Created
June 9, 2025 18:10
-
-
Save siniradam/89b008ea24edfa6059775ab449c8bd3f to your computer and use it in GitHub Desktop.
Proxmox disk passthrough script.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# Copyright (c) 2025 | |
# Author: Atlas (siniradam) | |
# License: MIT | |
# https://gist.github.com/siniradam | |
# This package, is for passthrough of a disk to a VM on Proxmox. | |
# You can use this script to passthrough a disk to a VM just by answering a few questions. | |
# This script is intended to be run on the Proxmox host. | |
# It will not work on a VM. | |
YELLOW='\033[1;33m' | |
RED='\033[0;31m' | |
GREEN='\033[0;32m' | |
BLUE='\033[0;34m' | |
NC='\033[0m' # No Color | |
# - Ask user to if they want to continue | |
echo "" | |
echo -e "${YELLOW}This script will passthrough a disk to a VM on Proxmox.${NC}" | |
read -p "Do you want to continue? (y/n) " -n 1 -r | |
echo # (optional) move to a new line | |
if [[ ! $REPLY =~ ^[Yy]$ ]]; then | |
exit 1 | |
fi | |
# - Check if lswh is installed if not install it. | |
if ! command -v lshw &> /dev/null | |
then | |
echo -e "${BLUE}lshw could not be found, installing it now.${NC}" | |
apt-get update && apt-get install -y lshw | |
fi | |
# Find the boot disk (the root filesystem) | |
BOOT_DISK=$(lsblk -no PKNAME $(findmnt -n -o SOURCE /) | head -n1) | |
# List all non-boot disks with their serials | |
DISK_LIST=() | |
DISK_INFO=() | |
i=1 | |
while IFS= read -r line; do | |
# Extract disk path (e.g., ../../sdb or ../../nvme0n1p1) | |
disk_symlink=$(echo "$line" | awk '{print $9}') | |
real_device=$(readlink -f "$disk_symlink") | |
disk_name=$(basename "$real_device") | |
# Remove partition suffix (e.g., sda1 -> sda, nvme0n1p1 -> nvme0n1) | |
base_disk_name=$(echo "$disk_name" | sed -E 's/([a-z]+)[0-9]+$/\1/; s/(nvme[0-9]+n[0-9]+)p[0-9]+$/\1/') | |
# Exclude boot disk | |
if [[ "$base_disk_name" == "$BOOT_DISK" ]]; then | |
continue | |
fi | |
# Extract serial from by-id path (ata- or nvme-) | |
serial=$(echo "$line" | grep -oP '(ata|nvme)-[^ ]+' || echo "N/A") | |
# Get disk size in human-readable format | |
size=$(lsblk -dn -o SIZE "/dev/$base_disk_name" 2>/dev/null | head -n1) | |
DISK_LIST+=("$base_disk_name") | |
DISK_INFO+=("$i) $base_disk_name (Size: $size, Serial: $serial)") | |
((i++)) | |
done < <(find /dev/disk/by-id/ -type l | grep -E 'ata-|nvme-' | xargs -I{} ls -l {} | grep -v -E '[0-9]$' | sort -k11) | |
echo "" | |
if [ ${#DISK_LIST[@]} -eq 0 ]; then | |
echo -e "${RED}No disks found for passthrough (other than boot disk).${NC}" | |
exit 1 | |
elif [ ${#DISK_LIST[@]} -eq 1 ]; then | |
echo "Only one disk available for passthrough: ${DISK_LIST[0]}" | |
exit 1 | |
fi | |
echo "" | |
echo "Available disks for passthrough:" | |
for info in "${DISK_INFO[@]}"; do | |
echo "$info" | |
done | |
echo "" | |
read -p "Enter the number of the disk to passthrough: " disk_choice | |
PASSTHROUGH_DISK="${DISK_LIST[$((disk_choice-1))]}" | |
# Ask for VM or container ID | |
echo "" | |
echo "Here are the VMs and Containers on the system:" | |
qm list | |
pct list | |
echo "" | |
read -p "Enter the VM or Container ID you want to passthrough the disk to: " VMID | |
if ! qm status $VMID &> /dev/null && ! pct status $VMID &> /dev/null; then | |
echo "VM or Container ID $VMID does not exist. Exiting." | |
exit 1 | |
fi | |
# Confirm | |
COMMAND="qm set $VMID -scsi2 /dev/disk/by-id/$serial" | |
echo "" | |
echo -e "You are about to passthrough ${YELLOW}/dev/$PASSTHROUGH_DISK ${NC}to VM/CT ${YELLOW}$VMID${NC}." | |
echo -e "${RED}The following command will be executed to passthrough the disk:${NC}" | |
echo -e "${BLUE}$COMMAND${NC}" | |
echo "" | |
# Ask for confirmation | |
read -p "Are you sure? (y/n) " -n 1 -r | |
echo | |
if [[ ! $REPLY =~ ^[Yy]$ ]]; then | |
echo -e "${RED}Operation cancelled.${NC}" | |
exit 1 | |
fi | |
# Confirm | |
# Print the command in yellow | |
# Execute the passthrough command | |
echo -e "${BLUE}Executing command...${NC}" | |
# $COMMAND |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment