#!/bin/bash #proxmox arm64 iso builder script_path=$(readlink -f "\$0") script_dir=$(dirname "$script_path") extra_pkg="ceph-common ceph-fuse" #if you want install other package hostarch=`arch` # This scripts only allow the same arch build. codename="bookworm" # proxmox version. bookworm->pve8 ,bullseye->pve7 targetdir="/tmp/targetdir" # tmpdir modules="hfs hfsplus cdrom sd_mod sr_mod loop squashfs iso9660 drm overlay uas hibmc-drm dw_drm_dsi kirin_drm amdgpu nouveau ast radeon virtio-gpu mgag200" # iso info source $script_dir/.cd-info # Handling of different architectures if [ "$hostarch" == "aarch64" ];then target_arch="arm64"; grub_prefix="arm64" grub_file="BOOTAA64.EFI" grub_pkg="grub-common grub-efi-arm64-bin systemd-boot grub-efi-arm64-signed shim-signed grub-efi-arm64 grub2-common" elif [ "$hostarch" == "x86_64" ];then target_arch="amd64" grub_prefix="x86_64" grub_file="BOOTX64.EFI" grub_pkg="grub-common grub-pc-bin grub-efi-amd64-bin systemd-boot grub-efi-amd64-signed shim-signed grub-efi-amd64 grub2-common" main_kernel="proxmox-kernel-6.8" elif [ "$hostarch" == "loongarch64" ];then target_arch="loong64" grub_prefix="loongarch64" grub_file="BOOTLOONGARCH64.EFI" grub_pkg="grub-common grub-efi-loong64-bin grub-efi-loong64 grub2-common" codename="sid" portmirrors="https://mirrors.lierfang.com/proxmox/debian" if [ "$PRODUCT" == "pbs" ];then main_kernel="pve-kernel-6.12-4k-pve" #pbs need 4k kernel else main_kernel="pve-kernel-6.12-pve" #for loongarch kernel 6.12 works fine fi extra_kernel="" elif [ "$hostarch" == "riscv64" ];then target_arch="riscv64" grub_prefix="riscv64" grub_file="BOOTRISCV64.EFI" grub_pkg="grub-common grub-efi-riscv64-bin grub-efi-riscv64 grub2-common" codename="sid" fi errlog(){ if [ $? != 0 ];then echo $1 umount_proc exit 1 fi } # Create isofs isofs(){ if [ ! -f "$targetdir/.isofs.lock" ];then rm $targetdir/iso/ -rf mkdir $targetdir/iso/boot/ -p mkdir $targetdir/iso/{.installer,.base,.installer-mp,.workdir} -p cp $script_dir/.cd-info $script_dir/Release.txt $script_dir/COPYING $script_dir/COPYRIGHT $script_dir/EULA $targetdir/iso/ ||errlog "do copy elua to iso dir failed" cp -r $script_dir/proxmox $targetdir/iso/ ||errlog "do proxmox dir to iso dir failed" echo "" > $targetdir/iso/auto-installer-capable touch $targetdir/.isofs.lock fi } # Crate Proxmox VE iso info isoinfo(){ echo $pveuuid > $targetdir/iso/.pve-cd-id.txt } mount_proc(){ mount -t proc /proc $targetdir/rootfs/proc mount -t sysfs /sys $targetdir/rootfs/sys mount -o bind /dev $targetdir/rootfs/dev mount -o bind /dev/pts $targetdir/dev/pts } umount_proc(){ umount $targetdir/rootfs/proc umount $targetdir/rootfs/sys umount $targetdir/rootfs/dev umount $targetdir/dev/rootfs/pts umount -l $targetdir/overlay/mount umount -l $targetdir/overlay/base } # Create proxmox installer initrd hook initramfs_hook(){ cp $targetdir/iso/.pve-cd-id.txt $targetdir/rootfs/ || errlog "copy .pve-cd-id.txt failed" cp $targetdir/iso/.cd-info $targetdir/rootfs/ || errlog "copy .cd-info failed" cp $script_dir/init $targetdir/rootfs/usr/share/initramfs-tools || errlog "copy initpve failed" cp $script_dir/pve_init_hook $targetdir/rootfs/usr/share/initramfs-tools/hooks/ || errlog "copy pve_init_hook failed" for module in $modules; do echo "$module" >> $targetdir/rootfs/etc/initramfs-tools/modules done chmod +x $targetdir/rootfs/usr/share/initramfs-tools/hooks/pve_init_hook } debconfig_set(){ echo "locales locales/default_environment_locale select en_US.UTF-8" > $targetdir/overlay/mount/tmp/debconfig.txt echo "locales locales/locales_to_be_generated select en_US.UTF-8 UTF-8" >> $targetdir/overlay/mount/tmp/debconfig.txt } debconfig_write(){ chroot $targetdir/overlay/mount/ debconf-set-selections /tmp/debconfig.txt chroot $targetdir/overlay/mount/ rm /tmp/debconfig.txt } fix_console_setup(){ cat > $targetdir/overlay/mount/etc/default/console-setup << 'EOF' # CONFIGURATION FILE FOR SETUPCON # Consult the console-setup(5) manual page. ACTIVE_CONSOLES="/dev/tty[1-6]" CHARMAP="UTF-8" CODESET="Lat15" FONTFACE="Fixed" FONTSIZE="8x16" VIDEOMODE= # The following is an example how to use a braille font # FONT='lat9w-08.psf.gz brl-8x8.psf' EOF } # Create pve-installer.squashfs overlayfs(){ if [ ! -f "$targetdir/.overlay.lock" ];then rm $targetdir/overlay/ -rf mkdir $targetdir/overlay/{base,upper,work,mount} -p mount -t squashfs -o ro $targetdir/pve-base.squashfs $targetdir/overlay/base || errlog "mount pve-base.squashfs filesystem failed" mount -t overlay -o lowerdir=$targetdir/overlay/base,upperdir=$targetdir/overlay/upper,workdir=$targetdir/overlay/work none $targetdir/overlay/mount || errlog "mount squashfs filesystem failed" if [ "$target_arch" == "amd64" ];then curl -L $pvemirrors/proxmox-release-$codename.gpg -o $targetdir/overlay/mount/etc/apt/trusted.gpg.d/proxmox-release-$codename.gpg echo "deb $pvemirrors/$PRODUCT $codename $PRODUCT-no-subscription " > $targetdir/overlay/mount/etc/apt/sources.list.d/pveport.list ||errlog "create apt mirrors failed" else curl -L $portmirrors/pveport.gpg -o $targetdir/overlay/mount/etc/apt/trusted.gpg.d/pveport.gpg ||errlog "download apt key failed" echo "deb $portmirrors/$PRODUCT $codename port" > $targetdir/overlay/mount/etc/apt/sources.list.d/pveport.list ||errlog "create apt mirrors failed" fi chroot $targetdir/overlay/mount apt update || errlog "apt update failed" debconfig_set debconfig_write LC_ALL=C DEBIAN_FRONTEND=noninteractive chroot $targetdir/overlay/mount apt -o DPkg::Options::="--force-confnew" install $grub_pkg openssh-client locales locales-all traceroute squashfs-tools spice-vdagent pci.ids pciutils gettext-base fonts-liberation eject ethtool efibootmgr dmeventd dnsutils lvm2 libstring-shellquote-perl console-setup wget curl vim iputils-* locales busybox initramfs-tools xorg openbox proxmox-installer pve-firmware zfsutils-linux zfs-zed spl btrfs-progs gdisk bash-completion zfs-initramfs dosfstools -y || errlog "install pveinstaller failed" fix_console_setup mkdir $targetdir/overlay/mount/usr/lib/modules/ cp -r $targetdir/rootfs/lib/modules/* $targetdir/overlay/mount/usr/lib/modules/ chroot $targetdir/overlay/mount/ apt clean rm -rf $targetdir/overlay/mount/var/cache/apt/archives/ umount $targetdir/overlay/mount || errlog "umount overlayfs failed" umount $targetdir/overlay/base || errlog "umount pvebase overlayfs failed" touch $targetdir/.overlay.lock fi rm -rf $targetdir/overlay/upper/tmp/ $targetdir/pve-installer.squashfs cp $targetdir/iso/.pve-cd-id.txt $targetdir/overlay/upper/ || errlog "copy .pve-cd-id.txt failed" cp $targetdir/iso/.cd-info $targetdir/overlay/upper/ || errlog "copy .cd-info failed" mkdir $targetdir/overlay/upper/cdrom -p mksquashfs $targetdir/overlay/upper/ $targetdir/pve-installer.squashfs || errlog "create pve-installer.squashfs failed" touch $targetdir/.pve-installer.lock } copy_squ(){ cp $targetdir/pve-installer.squashfs $targetdir/iso/pve-installer.squashfs cp $targetdir/pve-base.squashfs $targetdir/iso/pve-base.squashfs } generate_uuid() { local N B T for (( N=0; N < 8; N++ )); do B=$(( RANDOM%16 )) printf '%x' $B done printf '-' for (( N=0; N < 3; N++ )); do for (( i=0; i < 4; i++ )); do B=$(( RANDOM%16 )) printf '%x' $B done printf '-' done printf '4' for (( N=0; N < 3; N++ )); do B=$(( RANDOM%16 )) printf '%x' $B done T=$(( RANDOM%4+8 )) printf '%x' $T for (( N=0; N < 3; N++ )); do B=$(( RANDOM%16 )) printf '%x' $B done } # Check env env_test(){ if [ "$EUID" -ne 0 ]; then errlog "This script must be run as root." fi test -f "/usr/sbin/debootstrap" || errlog "debootstrap not found, use 'apt install debootstrap' to install" test -f "/usr/bin/mksquashfs" || errlog "squasfs-tools not found, use 'apt install squashfs-tools' to install" test -f "/usr/bin/xorriso" || errlog "xorriso not found, use 'apt install xorriso' to install" } # Build pve-base.squashfs buildroot(){ if [ ! -f "$targetdir/pve-base.squashfs" ];then if [ "$hostarch" == "loongarch64" ];then debootstrap --arch=$target_arch --include=debian-ports-archive-keyring --exclude="exim4,exim4-base,usr-is-merged" --include="usrmerge,perl" --no-check-gpg $codename $targetdir/rootfs https://mirrors.lierfang.com/debian-ports/debian || errlog "debootstrap failed" chroot $targetdir/rootfs apt install usr-is-merged -y echo 'APT { Get { AllowUnauthenticated "1"; }; };' > $targetdir/rootfs/etc/apt/apt.conf.d/99allow_unauth chroot $targetdir/rootfs apt clean else debootstrap --arch=$target_arch $codename $targetdir/rootfs $mirrors/debian || errlog "debootstrap failed" echo "deb $mirrors/debian/ $codename main contrib non-free non-free-firmware" > $targetdir/rootfs/etc/apt/sources.list echo "deb $mirrors/debian/ "$codename"-updates main contrib non-free non-free-firmware" >> $targetdir/rootfs/etc/apt/sources.list echo "deb $mirrors/debian/ "$codename"-backports main contrib non-free non-free-firmware" >> $targetdir/rootfs/etc/apt/sources.list echo "deb $mirrors/debian-security "$codename"-security main contrib non-free non-free-firmware" >> $targetdir/rootfs/etc/apt/sources.list fi mksquashfs $targetdir/rootfs $targetdir/pve-base.squashfs fi } # Download Proxmox VE Packages create_pkg(){ mount_proc if [ ! -f "$targetdir/.package.lock" ];then if [ "$target_arch" == "amd64" ];then curl -L $pvemirrors/proxmox-release-$codename.gpg -o $targetdir/rootfs/etc/apt/trusted.gpg.d/proxmox-release-$codename.gpg echo "deb $pvemirrors/$PRODUCT $codename $PRODUCT-no-subscription " > $targetdir/rootfs/etc/apt/sources.list.d/pveport.list ||errlog "create apt mirrors failed" else curl -L $portmirrors/pveport.gpg -o $targetdir/rootfs/etc/apt/trusted.gpg.d/pveport.gpg ||errlog "download apt key failed" echo "deb $portmirrors/$PRODUCT $codename port pvetest" > $targetdir/rootfs/etc/apt/sources.list.d/pveport.list ||errlog "create apt mirrors failed" fi chroot $targetdir/rootfs apt clean rm -rf $targetdir/rootfs/var/cache/apt/archives/ chroot $targetdir/rootfs apt update ||errlog "do apt update failed" if [ "$PRODUCT" == "pve" ];then main_pkg="proxmox-ve" else main_pkg="proxmox-backup-server" fi if [ -f "proxmox/$PRODUCT-packages.list.line" ];then main_pkg=`cat proxmox/$PRODUCT-packages.list.line` fi chroot $targetdir/rootfs apt --download-only install -y $main_pkg postfix squashfs-tools traceroute net-tools pci.ids pciutils efibootmgr xfsprogs fonts-liberation dnsutils $extra_pkg $grub_pkg gettext-base sosreport ethtool dmeventd eject chrony locales locales-all systemd rsyslog ifupdown2 ksmtuned zfsutils-linux zfs-zed spl btrfs-progs gdisk bash-completion zfs-initramfs dosfstools||errlog "download proxmox-ve package failed" if [ ! -z "$extra_kernel" ] && [ "$PRODUCT" != "pbs" ] ;then if [ "$target_arch" == "arm64" ] || [ "$target_arch" == "loong64" ] ;then chroot $targetdir/rootfs apt --download-only install -y $extra_kernel ||errlog "kernel installed failed" fi fi if [ "$target_arch" != "amd64" ];then chroot $targetdir/rootfs apt --download-only install -y $main_kernel ||errlog "kernel installed failed" fi mkdir $targetdir/iso/proxmox/packages/ -p cp -r $targetdir/rootfs/var/cache/apt/archives/*.deb $targetdir/iso/proxmox/packages/ ||errlog "do copy pkg failed" touch $targetdir/.package.lock fi if [ ! -f "$targetdir/.mainkernel.lock" ];then chroot $targetdir/rootfs apt install initramfs-tools -y initramfs_hook chroot $targetdir/rootfs apt install pve-firmware $main_kernel -y ||errlog "kernel installed failed" echo "copy main kernel" cp $targetdir/rootfs/boot/initrd.img-* $targetdir/iso/boot/initrd.img ||errlog "do copy initrd failed" cp $targetdir/rootfs/boot/vmlinuz-* $targetdir/iso/boot/linux26 ||errlog "do copy kernel failed" touch $targetdir/.mainkernel.lock fi if [ ! -z "$extra_kernel" ] && [ "$target_arch" != "amd64" ] ;then chroot $targetdir/rootfs apt install $extra_kernel -y ||errlog "Extra kernel installed failed" if [[ "$extra_kernel" =~ "openeuler" ]];then cp $targetdir/rootfs/boot/initrd.img-*-openeuler $targetdir/iso/boot/initrd.img-openeuler ||errlog "do copy initrd failed" cp $targetdir/rootfs/boot/vmlinuz-*-openeuler $targetdir/iso/boot/linux26-openeuler ||errlog "do copy kernel failed" fi if [[ "$extra_kernel" =~ -pve ]]; then cp $targetdir/rootfs/boot/initrd.img-*-pve $targetdir/iso/boot/initrd.img-pve ||errlog "do copy initrd failed" cp $targetdir/rootfs/boot/vmlinuz-*-pve $targetdir/iso/boot/linux26-pve ||errlog "do copy kernel failed" fi if [[ "$extra_kernel" =~ -generic ]]; then cp $targetdir/rootfs/boot/initrd.img-*-generic $targetdir/iso/boot/initrd.img-generic ||errlog "do copy initrd failed" cp $targetdir/rootfs/boot/vmlinuz-*-generic $targetdir/iso/boot/linux26-generic ||errlog "do copy kernel failed" fi if [[ "$extra_kernel" =~ phytium ]]; then cp $targetdir/rootfs/boot/initrd.img-*-phytium $targetdir/iso/boot/initrd.img-phytium ||errlog "do copy initrd failed" cp $targetdir/rootfs/boot/vmlinuz-*-phytium $targetdir/iso/boot/linux26-phytium ||errlog "do copy kernel failed" fi fi if [ "$target_arch" == "amd64" ];then echo "copy x86_64 init" cp $targetdir/rootfs/boot/initrd.img* $targetdir/iso/boot/initrd.img ||errlog "do copy initrd failed" cp $targetdir/rootfs/boot/vmlinuz* $targetdir/iso/boot/linux26 ||errlog "do copy kernel failed" fi umount_proc } # Build iso for !amd64 build_iso(){ rm $targetdir/iso/*.iso -rf isodate2=`echo $isodate|sed "s/-//g"` cd $targetdir/iso/ xorriso -as mkisofs -r -V 'PVE' \ --modification-date=$isodate2 \ -o $targetdir/$ISONAME-$RELEASE-$ISORELEASE-$target_arch-$isodate2.iso \ -R -cache-inodes \ -iso-level 3 \ -e boot/grub/efi.img \ -no-emul-boot \ -append_partition 2 0xef boot/grub/efi.img \ -partition_cyl_align all \ -isohybrid-gpt-basdat -isohybrid-apm-hfsplus \ . cd $script_dir } # Build iso for amd64 build_amd64_iso(){ rm $targetdir/iso/*.iso -rf isodate2=`echo $isodate|sed "s/-//g"` cd $targetdir/iso/ cp $script_dir/boot.cat $targetdir/iso/boot ||errlog "do copy boot.cat failed" cp $script_dir/iso.mbr $targetdir/iso/boot ||errlog "do copy iso.mbr failed" cp $script_dir/eltorito.img $targetdir/iso/boot ||errlog "do copy eltorito failed" xorriso -as mkisofs \ -V 'PVE' \ -o $targetdir/$ISONAME-$RELEASE-$ISORELEASE-$target_arch-$isodate2.iso \ --grub2-mbr --interval:local_fs:0s-15s:zero_mbrpt,zero_gpt,zero_apm:'./boot/iso.mbr' \ --modification-date=$isodate2 \ -partition_cyl_align off \ -partition_offset 0 \ -partition_hd_cyl 67 \ -partition_sec_hd 32 \ -apm-block-size 2048 \ -hfsplus \ -efi-boot-part --efi-boot-image \ -c '/boot/boot.cat' \ -b '/boot/eltorito.img' \ -no-emul-boot \ -boot-load-size 4 \ -boot-info-table \ --grub2-boot-info \ -eltorito-alt-boot \ -e '/boot/grub/efi.img' \ -no-emul-boot \ -boot-load-size 16384 \ . } # Create efi.img mkefi_img(){ dd if=/dev/zero of=$targetdir/iso/boot/grub/efi.img bs=512 count=20480 mkfs.fat -F 16 -n 'EFI' $targetdir/iso/boot/grub/efi.img rm /tmp/efi -rf mkdir /tmp/efi/ mount $targetdir/iso/boot/grub/efi.img /tmp/efi cp -r $targetdir/iso/EFI /tmp/efi ||errlog "do EFI file failed" umount -l /tmp/efi } # Install ISO Grub grub_install(){ if [ ! -f "$targetdir/.grub.lock" ];then rm $targetdir/iso/boot/grub/ -rf rm $targetdir/iso/EFI -rf mkdir $targetdir/iso/EFI/BOOT/ -p mkdir $targetdir/iso/boot/grub -p echo "do grub install" grub-mkimage -o $targetdir/iso/EFI/BOOT/$grub_file -O $grub_prefix-efi -p /EFI/BOOT/ \ boot linux chain normal configfile \ part_gpt part_msdos fat iso9660 udf \ test true keystatus loopback regexp probe \ efi_gop all_video gfxterm font \ echo read help ls cat halt reboot lvm ext2 xfs hfsplus hfs \ acpi search_label search search_fs_file search_fs_uuid \ serial terminfo terminal zfs btrfs efifwsetup cp -r /boot/grub/ $targetdir/iso/boot/ ||errlog "do grub dir failed" cp $script_dir/grub.cfg $targetdir/iso/boot/grub/ ||errlog "do copy grub cfg failed" cp -r $script_dir/pvetheme $targetdir/iso/boot/grub/ ||errlog "do copy grub pvethem failed" touch $targetdir/.grub.lock fi cat > $targetdir/iso/EFI/BOOT/grub.cfg << EOF search --fs-uuid --set=root $isodate set prefix=(\${root})/boot/grub source \${prefix}/grub.cfg insmod part_acorn insmod part_amiga insmod part_apple insmod part_bsd insmod part_dfly insmod part_dvh insmod part_gpt insmod part_msdos insmod part_plan insmod part_sun insmod part_sunpc EOF } # Main Start umount_proc if [ "$1" == "clean" ];then rm $targetdir -rf mkdir $targetdir/rootfs -p fi pveuuid=$(generate_uuid) isodate=`date +"%Y-%m-%d-%H-%M-%S-00"` env_test isofs isoinfo buildroot create_pkg grub_install mkefi_img overlayfs copy_squ build_amd64_iso