Compare commits

..

No commits in common. "master" and "4.9.8" have entirely different histories.

20 changed files with 448 additions and 1530 deletions

View File

@ -16,6 +16,6 @@ jobs:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: DeterminateSystems/nix-installer-action@v22
- uses: DeterminateSystems/nix-installer-action@v21
- uses: DeterminateSystems/magic-nix-cache-action@v9
- uses: DeterminateSystems/flake-checker-action@v12

View File

@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: DeterminateSystems/nix-installer-action@v22
- uses: DeterminateSystems/nix-installer-action@v21
- uses: DeterminateSystems/magic-nix-cache-action@v9
- uses: DeterminateSystems/update-flake-lock@v28
with:

View File

@ -106,7 +106,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Import gpg key 🔑"
uses: crazy-max/ghaction-import-gpg@v7
uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.PPA_GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.PPA_GPG_PASSPHRASE }}

View File

@ -53,7 +53,7 @@ jobs:
- name: "Checkout 🥡"
uses: "actions/checkout@v6"
- name: "Install Nix ❄️"
uses: "DeterminateSystems/nix-installer-action@v22"
uses: "DeterminateSystems/nix-installer-action@v21"
- name: "Enable Magic Nix Cache 🪄"
uses: "DeterminateSystems/magic-nix-cache-action@v9"
- name: "Build & Test .nix ❄️"

View File

@ -50,7 +50,7 @@ jobs:
id: check
run: |
mkdir -p results
./quickget --check-all-arch "${{ matrix.distro }}" | tee results/check.txt
./quickget --check "${{ matrix.distro }}" | tee results/check.txt
# Count results (use wc -l to avoid grep exit code issues)
PASSED=$(grep '^PASS' results/check.txt | wc -l | tr -d ' ')
@ -83,7 +83,7 @@ jobs:
cat result/result.json
- name: "Upload result artifact 📤"
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v4
with:
name: result-${{ matrix.distro }}
path: result/
@ -101,7 +101,7 @@ jobs:
if: always()
steps:
- name: "Download all result artifacts 📥"
uses: actions/download-artifact@v8
uses: actions/download-artifact@v4
with:
pattern: result-*
path: results

View File

@ -27,8 +27,6 @@ The devshell patches `quickemu` to use Nix store paths for OVMF and Samba, writi
- Lint scripts: `shellcheck quickemu quickget quickreport chunkcheck`
- Test quickget URLs: `./quickget --check <os> [release] [edition]`
- Test ARM64 downloads: `./quickget --arch arm64 --check <os> [release] [edition]`
- Test all architectures: `./quickget --check-all-arch <os> [release] [edition]`
- List all supported OSes: `./quickget --list`
- Run VM: `./quickemu --vm <name>.conf`
@ -55,8 +53,7 @@ Follow the [guide in the wiki](https://github.com/quickemu-project/quickemu/wiki
1. Entry in `os_info()` case statement
2. `releases_<os>()` function returning available versions
3. `editions_<os>()` function if multiple editions exist
4. `arch_<os>()` function if ARM64 is supported (defaults to amd64 only if omitted)
5. Download URL construction logic
4. Download URL construction logic
## Commit message format
@ -99,13 +96,10 @@ fix(quickget): remove Athena OS (no longer getting updates)
## Platform support
- Host: Linux (x86_64, aarch64), macOS (x86_64, aarch64)
- Guest: x86_64 (default), aarch64 (set `arch="aarch64"` in VM config)
- ARM64 guests use AAVMF firmware and `virt` machine type
- Cross-arch emulation uses TCG (no KVM acceleration)
- OVMF/UEFI firmware: Linux only
- Bash 4.0+ required (explicit version check at runtime)
## Key dependencies
Runtime: qemu, cdrtools, curl, jq, spice-gtk, swtpm, samba, zsync
Linux-specific: OVMF (x86_64 guests), AAVMF (aarch64 guests), usbutils, mesa-demos
Linux-specific: OVMF, usbutils, mesa-demos

View File

@ -41,7 +41,6 @@ required to run the virtual machines.
- **macOS** Sequoia, Sonoma, Ventura, Monterey, Big Sur, Catalina & Mojave
- **Windows** 10 and 11 including TPM 2.0
- **Windows Server** 2022 2019 2016
- **ARM64 guest support** for running aarch64 VMs (native on ARM hosts, emulated on x86_64)
- [Ubuntu](https://ubuntu.com/desktop) and all the **[official Ubuntu
flavours](https://ubuntu.com/download/flavours)**
- **Nearly 1000 operating system editions are supported!**

@ -1 +1 @@
Subproject commit f9582c397c8ac9f1fc6ab2d6882d5ef51dc5efda
Subproject commit c5907eae9c0bd9364b4a91a3f449f1d1dbbc58c9

View File

@ -30,7 +30,7 @@ mkShell {
xorg.xrandr
zsync
]
++ lib.optionals stdenv.hostPlatform.isLinux [
++ lib.optionals stdenv.isLinux [
mesa-demos
usbutils
xdg-user-dirs
@ -52,14 +52,10 @@ mkShell {
sed \
${
lib.optionalString (OVMF != null && OVMFFull != null) ''
-e '/OVMF_CODE_4M.secboot.fd/s|ovmfs=(|ovmfs=("${OVMFFull.firmware}","${OVMFFull.variablesMs}" |' \
-e '/OVMF_CODE_4M.secboot.fd/s|ovmfs=(|ovmfs=("${OVMFFull.firmware}","${OVMFFull.variables}" |' \
-e '/OVMF_CODE_4M.fd/s|ovmfs=(|ovmfs=("${OVMF.firmware}","${OVMF.variables}" |' \
''
}${lib.optionalString stdenv.hostPlatform.isDarwin ''
-e 's|ovmfs=("[$][{]SHARE_PATH}/OVMF/OVMF_CODE_4M.secboot.fd"|ovmfs=("${pkgs.qemu_full}/share/qemu/edk2-x86_64-secure-code.fd","${pkgs.qemu_full}/share/qemu/edk2-i386-vars.fd" "''${SHARE_PATH}/OVMF/OVMF_CODE_4M.secboot.fd"|' \
-e 's|ovmfs=("[$][{]SHARE_PATH}/OVMF/OVMF_CODE_4M.fd"|ovmfs=("${pkgs.qemu_full}/share/qemu/edk2-x86_64-code.fd","${pkgs.qemu_full}/share/qemu/edk2-i386-vars.fd" "''${SHARE_PATH}/OVMF/OVMF_CODE_4M.fd"|' \
-e 's|ovmfs=("/usr/share/AAVMF/AAVMF_CODE.fd"|ovmfs=("${pkgs.qemu_full}/share/qemu/edk2-aarch64-code.fd","${pkgs.qemu_full}/share/qemu/edk2-arm-vars.fd" "/usr/share/AAVMF/AAVMF_CODE.fd"|' \
''} \
} \
-e '/cp "''${VARS_IN}" "''${VARS_OUT}"/a chmod +w "''${VARS_OUT}"' \
-e 's,\$(command -v smbd),${pkgs.samba}/bin/smbd,' \
quickemu > $PWD/.direnv/bin/quickemu

View File

@ -1,6 +1,6 @@
.\" Automatically generated by Pandoc 3.8.3
.\" Automatically generated by Pandoc 3.7.0.2
.\"
.TH "QUICKEMU" "1" "February 2, 2026" "quickemu" "Quickemu User Manual"
.TH "QUICKEMU" "1" "July 31, 2025" "quickemu" "Quickemu User Manual"
.SH NAME
quickemu \- A quick VM builder and manager
.SH SYNOPSIS
@ -31,8 +31,8 @@ Delete the entire VM and its configuration
.TP
\f[B]\-\-display\f[R]
Select display backend.
\(aqgtk\(aq (default), \(aqsdl\(aq, \(aqcocoa\(aq, \(aqnone\(aq,
\(aqspice\(aq or \(aqspice\-app\(aq
\(aqsdl\(aq (default), \(aqgtk\(aq, \(aqnone\(aq, \(aqspice\(aq or
\(aqspice\-app\(aq
.TP
\f[B]\-\-fullscreen\f[R]
Starts VM in full screen mode (Ctl+Alt+f to exit)
@ -191,9 +191,6 @@ Mojave
.IP \(bu 2
\f[B]Windows Server\f[R] 2022 2019 2016
.IP \(bu 2
\f[B]ARM64 guest support\f[R] for running aarch64 VMs (native on ARM
hosts, emulated on x86_64)
.IP \(bu 2
\c
.UR https://ubuntu.com/desktop
Ubuntu
@ -573,23 +570,18 @@ wiki
You can also use \f[CR]quickget\f[R] with advanced options :
.IP
.EX
\-\-arch <arch> : Set architecture (arm64, aarch64, amd64, x86_64)
\-\-download <os> <release> [edition] : Download image; no VM configuration
\-\-create\-config <os> [path/url] [flags] : Create VM config for an OS image
\-\-open\-homepage <os> : Open homepage for the OS
\-\-show [os] : Show OS information
\-\-version : Show version
\-\-help : Show this help message
\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- Flags \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
\-\-create\-config:
\-\-disable\-unattended : Force quickget not to set up an unattended installation
\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- For testing & development \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
\-\-url [os] [release] [edition] : Show image URL(s)
\-\-check [os] [release] [edition] : Check image URL(s)
\-\-check\-all\-arch [os] [release] [edition] : Check downloads for all architectures (amd64 and arm64)
\-\-list : List all supported systems
\-\-list\-csv : List everything in csv format
\-\-list\-json : List everything in json format
\-\-download <os> <release> [edition] : Download image; no VM configuration
\-\-create\-config <os> [path/url] [flags] : Create VM config for an OS image
\-\-open\-homepage <os> : Open homepage for the OS
\-\-show [os] : Show OS information
\-\-version : Show version
\-\-help : Show this help message
\-\-disable\-unattended : Force quickget not to set up an unattended installation
\-\-url [os] [release] [edition] : Show image URL(s)
\-\-check [os] [release] [edition] : Check image URL(s)
\-\-list : List all supported systems
\-\-list\-csv : List everything in csv format
\-\-list\-json : List everything in json format
.EE
.PP
Here are some typical uses
@ -630,7 +622,7 @@ wiki
.IP \(bu 2
\f[CR]artixlinux\f[R] (Artix Linux)
.IP \(bu 2
\f[CR]azurelinux\f[R] (Azure Linux)
\f[CR]athenaos\f[R] (Athena OS)
.IP \(bu 2
\f[CR]batocera\f[R] (Batocera)
.IP \(bu 2
@ -686,6 +678,8 @@ wiki
.IP \(bu 2
\f[CR]haiku\f[R] (Haiku)
.IP \(bu 2
\f[CR]holoiso\f[R] (HoloISO)
.IP \(bu 2
\f[CR]kali\f[R] (Kali)
.IP \(bu 2
\f[CR]kdeneon\f[R] (KDE Neon)
@ -758,15 +752,17 @@ wiki
.IP \(bu 2
\f[CR]solus\f[R] (Solus)
.IP \(bu 2
\f[CR]sparkylinux\f[R] (SparkyLinux)
.IP \(bu 2
\f[CR]spirallinux\f[R] (SpiralLinux)
.IP \(bu 2
\f[CR]tails\f[R] (Tails)
.IP \(bu 2
\f[CR]tinycore\f[R] (Tiny Core Linux)
.IP \(bu 2
\f[CR]trisquel\f[R] (Trisquel)
\f[CR]trisquel\f[R] (Trisquel\-)
.IP \(bu 2
\f[CR]truenas\-core\f[R] (TrueNAS Core)
.IP \(bu 2
\f[CR]truenas\-scale\f[R] (TrueNAS Scale)
.IP \(bu 2
\f[CR]tuxedo\-os\f[R] (Tuxedo OS)
.IP \(bu 2
@ -774,6 +770,8 @@ wiki
.IP \(bu 2
\f[CR]void\f[R] (Void Linux)
.IP \(bu 2
\f[CR]vxlinux\f[R] (VX Linux)
.IP \(bu 2
\f[CR]zorin\f[R] (Zorin OS)
.SS \c
.UR https://github.com/quickemu-project/quickemu/wiki/02-Create-Linux-virtual-machines#manually-create-linux-guests
@ -829,17 +827,6 @@ check the Discussions
.PP
\f[CR]quickget\f[R] automatically downloads a macOS recovery image and
creates a virtual machine configuration.
.PP
Note: Some VPN users may need to \c
.UR https://github.com/quickemu-project/quickemu/issues/1391#issuecomment-3506845235
turn off their VPN
.UE \c
\ in order to download a recovery image.
Some other users may find \c
.UR https://github.com/quickemu-project/quickemu/issues/1391#issuecomment-2429146013
using a VPN
.UE \c
\ necessary in order to download a recovery image.
.IP
.EX
quickget macos big\-sur
@ -944,16 +931,16 @@ The default macOS configuration looks like this:
.IP
.EX
guest_os=\(dqmacos\(dq
img=\(dqmacos\-big\-sur/RecoveryImage.img\(dq
disk_img=\(dqmacos\-big\-sur/disk.qcow2\(dq
macos_release=\(dqbig\-sur\(dq
img=\(dqmacos\- big\-sur/RecoveryImage.img\(dq
disk_img=\(dqmacos\- big\-sur/disk.qcow2\(dq
macos_release=\(dq big\-sur\(dq
.EE
.IP \(bu 2
\f[CR]guest_os=\(dqmacos\(dq\f[R] instructs Quickemu to optimise for
macOS.
.IP \(bu 2
\f[CR]macos_release=\(dqbig\-sur\(dq\f[R] instructs Quickemu to optimise
for a particular macOS release.
\f[CR]macos_release=\(dq big\-sur\(dq\f[R] instructs Quickemu to
optimise for a particular macOS release.
.RS 2
.IP \(bu 2
For example VirtIO Network and Memory Ballooning are available in Big
@ -1157,13 +1144,11 @@ Usage
Arguments
\-\-access : Enable remote spice access support. \(aqlocal\(aq (default), \(aqremote\(aq, \(aqclientipaddress\(aq
\-\-braille : Enable braille support. Requires SDL.
\-\-cpu\-pinning : Choose which host cores correspond to which guest cores.
\-\-delete\-disk : Delete the disk image and EFI variables
\-\-delete\-vm : Delete the entire VM and its configuration
\-\-display : Select display backend. \(aqgtk\(aq (default), \(aqsdl\(aq, \(aqcocoa\(aq, \(aqnone\(aq, \(aqspice\(aq or \(aqspice\-app\(aq
\-\-display : Select display backend. \(aqsdl\(aq (default), \(aqcocoa\(aq, \(aqgtk\(aq, \(aqnone\(aq, \(aqspice\(aq or \(aqspice\-app\(aq
\-\-fullscreen : Starts VM in full screen mode (Ctl+Alt+f to exit)
\-\-ignore\-msrs\-always : Configure KVM to always ignore unhandled machine\-specific registers
\-\-ignore\-tsc\-warning : Skip TSC stability warning for macOS VMs on AMD
\-\-kill : Kill the VM process if it is running
\-\-offline : Override all network settings and start the VM offline
\-\-shortcut : Create a desktop shortcut
@ -1189,7 +1174,7 @@ Arguments
\-\-keyboard_layout <layout> : Set keyboard layout: \(aqen\-us\(aq (default)
\-\-mouse <type> : Set mouse. \(atOptions: \(aqtablet\(aq (default), \(aqps2\(aq, \(aqusb\(aq, \(aqvirtio\(aq
\-\-usb\-controller <type> : Set usb\-controller. \(atOptions: \(aqehci\(aq (default), \(aqxhci\(aq, \(aqnone\(aq
\-\-sound\-card <type> : Set sound card. \(atOptions: \(aqintel\-hda\(aq (default), \(aqac97\(aq, \(aqes1370\(aq, \(aqsb16\(aq, \(aqusb\-audio\(aq, \(aqvirtio\-sound\-pci\(aq, \(aqnone\(aq
\-\-sound\-card <type> : Set sound card. \(atOptions: \(aqintel\-hda\(aq (default), \(aqac97\(aq, \(aqes1370\(aq, \(aqsb16\(aq, \(aqusb\-audio\(aq, \(aqnone\(aq
\-\-sound\-duplex <type> : Set sound card duplex. \(atOptions: \(aqhda\-micro\(aq (default: speaker/mic), \(aqhda\-duplex\(aq (line\-in/line\-out), \(aqhda\-output\(aq (output\-only)
\-\-extra_args <arguments> : Pass additional arguments to qemu
\-\-version : Print version

View File

@ -1,6 +1,6 @@
---
author: Martin Wimpress
date: February 2, 2026
date: July 31, 2025
footer: quickemu
header: Quickemu User Manual
section: 1
@ -41,8 +41,8 @@ You can also pass optional parameters
: Delete the entire VM and its configuration
**--display**
: Select display backend. 'gtk' (default), 'sdl', 'cocoa', 'none',
'spice' or 'spice-app'
: Select display backend. 'sdl' (default), 'gtk', 'none', 'spice' or
'spice-app'
**--fullscreen**
: Starts VM in full screen mode (Ctl+Alt+f to exit)
@ -177,8 +177,6 @@ Haiku, KolibriOS, OpenIndiana, ReactOS, and more.
Mojave
- **Windows** 10 and 11 including TPM 2.0
- **Windows Server** 2022 2019 2016
- **ARM64 guest support** for running aarch64 VMs (native on ARM hosts,
emulated on x86_64)
- [Ubuntu](https://ubuntu.com/desktop) and all the **[official Ubuntu
flavours](https://ubuntu.com/download/flavours)**
- **Nearly 1000 operating system editions are supported!**
@ -399,23 +397,18 @@ may have further information.
You can also use `quickget` with advanced options :
``` text
--arch <arch> : Set architecture (arm64, aarch64, amd64, x86_64)
--download <os> <release> [edition] : Download image; no VM configuration
--create-config <os> [path/url] [flags] : Create VM config for an OS image
--open-homepage <os> : Open homepage for the OS
--show [os] : Show OS information
--version : Show version
--help : Show this help message
------------------------------------ Flags -------------------------------------
--create-config:
--disable-unattended : Force quickget not to set up an unattended installation
-------------------------- For testing & development ---------------------------
--url [os] [release] [edition] : Show image URL(s)
--check [os] [release] [edition] : Check image URL(s)
--check-all-arch [os] [release] [edition] : Check downloads for all architectures (amd64 and arm64)
--list : List all supported systems
--list-csv : List everything in csv format
--list-json : List everything in json format
--download <os> <release> [edition] : Download image; no VM configuration
--create-config <os> [path/url] [flags] : Create VM config for an OS image
--open-homepage <os> : Open homepage for the OS
--show [os] : Show OS information
--version : Show version
--help : Show this help message
--disable-unattended : Force quickget not to set up an unattended installation
--url [os] [release] [edition] : Show image URL(s)
--check [os] [release] [edition] : Check image URL(s)
--list : List all supported systems
--list-csv : List everything in csv format
--list-json : List everything in json format
```
Here are some typical uses
@ -448,7 +441,7 @@ Further information is available from the project
- `archcraft` (Archcraft)
- `archlinux` (Arch Linux)
- `artixlinux` (Artix Linux)
- `azurelinux` (Azure Linux)
- `athenaos` (Athena OS)
- `batocera` (Batocera)
- `bazzite` (Bazzite)
- `biglinux` (BigLinux)
@ -476,6 +469,7 @@ Further information is available from the project
- `gnomeos` (GNOME OS)
- `guix` (Guix)
- `haiku` (Haiku)
- `holoiso` (HoloISO)
- `kali` (Kali)
- `kdeneon` (KDE Neon)
- `kolibrios` (KolibriOS)
@ -512,14 +506,16 @@ Further information is available from the project
- `slint` (Slint)
- `slitaz` (SliTaz)
- `solus` (Solus)
- `sparkylinux` (SparkyLinux)
- `spirallinux` (SpiralLinux)
- `tails` (Tails)
- `tinycore` (Tiny Core Linux)
- `trisquel` (Trisquel)
- `trisquel` (Trisquel-)
- `truenas-core` (TrueNAS Core)
- `truenas-scale` (TrueNAS Scale)
- `tuxedo-os` (Tuxedo OS)
- `vanillaos` (Vanilla OS)
- `void` (Void Linux)
- `vxlinux` (VX Linux)
- `zorin` (Zorin OS)
### [Custom Linux guests](https://github.com/quickemu-project/quickemu/wiki/02-Create-Linux-virtual-machines#manually-create-linux-guests)
@ -565,13 +561,6 @@ for solutions or ask for help there** 🛟
`quickget` automatically downloads a macOS recovery image and creates a
virtual machine configuration.
Note: Some VPN users may need to [turn off their
VPN](https://github.com/quickemu-project/quickemu/issues/1391#issuecomment-3506845235)
in order to download a recovery image. Some other users may find [using
a
VPN](https://github.com/quickemu-project/quickemu/issues/1391#issuecomment-2429146013)
necessary in order to download a recovery image.
``` shell
quickget macos big-sur
quickemu --vm macos-big-sur.conf
@ -646,13 +635,13 @@ The default macOS configuration looks like this:
``` shell
guest_os="macos"
img="macos-big-sur/RecoveryImage.img"
disk_img="macos-big-sur/disk.qcow2"
macos_release="big-sur"
img="macos- big-sur/RecoveryImage.img"
disk_img="macos- big-sur/disk.qcow2"
macos_release=" big-sur"
```
- `guest_os="macos"` instructs Quickemu to optimise for macOS.
- `macos_release="big-sur"` instructs Quickemu to optimise for a
- `macos_release=" big-sur"` instructs Quickemu to optimise for a
particular macOS release.
- For example VirtIO Network and Memory Ballooning are available in
Big Sur and newer, but not previous releases.
@ -769,13 +758,11 @@ Usage
Arguments
--access : Enable remote spice access support. 'local' (default), 'remote', 'clientipaddress'
--braille : Enable braille support. Requires SDL.
--cpu-pinning : Choose which host cores correspond to which guest cores.
--delete-disk : Delete the disk image and EFI variables
--delete-vm : Delete the entire VM and its configuration
--display : Select display backend. 'gtk' (default), 'sdl', 'cocoa', 'none', 'spice' or 'spice-app'
--display : Select display backend. 'sdl' (default), 'cocoa', 'gtk', 'none', 'spice' or 'spice-app'
--fullscreen : Starts VM in full screen mode (Ctl+Alt+f to exit)
--ignore-msrs-always : Configure KVM to always ignore unhandled machine-specific registers
--ignore-tsc-warning : Skip TSC stability warning for macOS VMs on AMD
--kill : Kill the VM process if it is running
--offline : Override all network settings and start the VM offline
--shortcut : Create a desktop shortcut
@ -801,7 +788,7 @@ Arguments
--keyboard_layout <layout> : Set keyboard layout: 'en-us' (default)
--mouse <type> : Set mouse. @Options: 'tablet' (default), 'ps2', 'usb', 'virtio'
--usb-controller <type> : Set usb-controller. @Options: 'ehci' (default), 'xhci', 'none'
--sound-card <type> : Set sound card. @Options: 'intel-hda' (default), 'ac97', 'es1370', 'sb16', 'usb-audio', 'virtio-sound-pci', 'none'
--sound-card <type> : Set sound card. @Options: 'intel-hda' (default), 'ac97', 'es1370', 'sb16', 'usb-audio', 'none'
--sound-duplex <type> : Set sound card duplex. @Options: 'hda-micro' (default: speaker/mic), 'hda-duplex' (line-in/line-out), 'hda-output' (output-only)
--extra_args <arguments> : Pass additional arguments to qemu
--version : Print version

View File

@ -1,6 +1,6 @@
.\" Automatically generated by Pandoc 3.8.3
.\" Automatically generated by Pandoc 3.7.0.2
.\"
.TH "QUICKEMU_CONF" "5" "February 2, 2026" "quickemu_conf" "Quickemu Configuration Manual"
.TH "QUICKEMU_CONF" "5" "July 31, 2025" "quickemu_conf" "Quickemu Configuration Manual"
.SH NAME
quickemu_conf \- Options and parameters in the quickemu <vm>.conf
.SH DESCRIPTION

View File

@ -1,6 +1,6 @@
---
author: Martin Wimpress
date: February 2, 2026
date: July 31, 2025
footer: quickemu_conf
header: Quickemu Configuration Manual
section: 5

View File

@ -1,6 +1,6 @@
.\" Automatically generated by Pandoc 3.8.3
.\" Automatically generated by Pandoc 3.7.0.2
.\"
.TH "QUICKGET" "1" "February 2, 2026" "quickget" "Quickget User Manual"
.TH "QUICKGET" "1" "July 31, 2025" "quickget" "Quickget User Manual"
.SH NAME
quickget \- download and prepare materials for building a quickemu VM
.SH SYNOPSIS
@ -128,23 +128,18 @@ wiki
You can also use \f[CR]quickget\f[R] with advanced options :
.IP
.EX
\-\-arch <arch> : Set architecture (arm64, aarch64, amd64, x86_64)
\-\-download <os> <release> [edition] : Download image; no VM configuration
\-\-create\-config <os> [path/url] [flags] : Create VM config for an OS image
\-\-open\-homepage <os> : Open homepage for the OS
\-\-show [os] : Show OS information
\-\-version : Show version
\-\-help : Show this help message
\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- Flags \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
\-\-create\-config:
\-\-disable\-unattended : Force quickget not to set up an unattended installation
\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- For testing & development \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
\-\-url [os] [release] [edition] : Show image URL(s)
\-\-check [os] [release] [edition] : Check image URL(s)
\-\-check\-all\-arch [os] [release] [edition] : Check downloads for all architectures (amd64 and arm64)
\-\-list : List all supported systems
\-\-list\-csv : List everything in csv format
\-\-list\-json : List everything in json format
\-\-download <os> <release> [edition] : Download image; no VM configuration
\-\-create\-config <os> [path/url] [flags] : Create VM config for an OS image
\-\-open\-homepage <os> : Open homepage for the OS
\-\-show [os] : Show OS information
\-\-version : Show version
\-\-help : Show this help message
\-\-disable\-unattended : Force quickget not to set up an unattended installation
\-\-url [os] [release] [edition] : Show image URL(s)
\-\-check [os] [release] [edition] : Check image URL(s)
\-\-list : List all supported systems
\-\-list\-csv : List everything in csv format
\-\-list\-json : List everything in json format
.EE
.PP
Here are some typical uses
@ -185,7 +180,7 @@ wiki
.IP \(bu 2
\f[CR]artixlinux\f[R] (Artix Linux)
.IP \(bu 2
\f[CR]azurelinux\f[R] (Azure Linux)
\f[CR]athenaos\f[R] (Athena OS)
.IP \(bu 2
\f[CR]batocera\f[R] (Batocera)
.IP \(bu 2
@ -241,6 +236,8 @@ wiki
.IP \(bu 2
\f[CR]haiku\f[R] (Haiku)
.IP \(bu 2
\f[CR]holoiso\f[R] (HoloISO)
.IP \(bu 2
\f[CR]kali\f[R] (Kali)
.IP \(bu 2
\f[CR]kdeneon\f[R] (KDE Neon)
@ -313,15 +310,17 @@ wiki
.IP \(bu 2
\f[CR]solus\f[R] (Solus)
.IP \(bu 2
\f[CR]sparkylinux\f[R] (SparkyLinux)
.IP \(bu 2
\f[CR]spirallinux\f[R] (SpiralLinux)
.IP \(bu 2
\f[CR]tails\f[R] (Tails)
.IP \(bu 2
\f[CR]tinycore\f[R] (Tiny Core Linux)
.IP \(bu 2
\f[CR]trisquel\f[R] (Trisquel)
\f[CR]trisquel\f[R] (Trisquel\-)
.IP \(bu 2
\f[CR]truenas\-core\f[R] (TrueNAS Core)
.IP \(bu 2
\f[CR]truenas\-scale\f[R] (TrueNAS Scale)
.IP \(bu 2
\f[CR]tuxedo\-os\f[R] (Tuxedo OS)
.IP \(bu 2
@ -329,6 +328,8 @@ wiki
.IP \(bu 2
\f[CR]void\f[R] (Void Linux)
.IP \(bu 2
\f[CR]vxlinux\f[R] (VX Linux)
.IP \(bu 2
\f[CR]zorin\f[R] (Zorin OS)
.SS \c
.UR https://github.com/quickemu-project/quickemu/wiki/02-Create-Linux-virtual-machines#manually-create-linux-guests
@ -384,17 +385,6 @@ check the Discussions
.PP
\f[CR]quickget\f[R] automatically downloads a macOS recovery image and
creates a virtual machine configuration.
.PP
Note: Some VPN users may need to \c
.UR https://github.com/quickemu-project/quickemu/issues/1391#issuecomment-3506845235
turn off their VPN
.UE \c
\ in order to download a recovery image.
Some other users may find \c
.UR https://github.com/quickemu-project/quickemu/issues/1391#issuecomment-2429146013
using a VPN
.UE \c
\ necessary in order to download a recovery image.
.IP
.EX
quickget macos big\-sur
@ -507,8 +497,8 @@ macos_release=\(dqbig\-sur\(dq
\f[CR]guest_os=\(dqmacos\(dq\f[R] instructs Quickemu to optimise for
macOS.
.IP \(bu 2
\f[CR]macos_release=\(dqbig\-sur\(dq\f[R] instructs Quickemu to optimise
for a particular macOS release.
\f[CR]macos_release=\(dq big\-sur\(dq\f[R] instructs Quickemu to
optimise for a particular macOS release.
.RS 2
.IP \(bu 2
For example VirtIO Network and Memory Ballooning are available in Big

View File

@ -1,6 +1,6 @@
---
author: Martin Wimpress
date: February 2, 2026
date: July 31, 2025
footer: quickget
header: Quickget User Manual
section: 1
@ -123,23 +123,18 @@ may have further information.
You can also use `quickget` with advanced options :
``` text
--arch <arch> : Set architecture (arm64, aarch64, amd64, x86_64)
--download <os> <release> [edition] : Download image; no VM configuration
--create-config <os> [path/url] [flags] : Create VM config for an OS image
--open-homepage <os> : Open homepage for the OS
--show [os] : Show OS information
--version : Show version
--help : Show this help message
------------------------------------ Flags -------------------------------------
--create-config:
--disable-unattended : Force quickget not to set up an unattended installation
-------------------------- For testing & development ---------------------------
--url [os] [release] [edition] : Show image URL(s)
--check [os] [release] [edition] : Check image URL(s)
--check-all-arch [os] [release] [edition] : Check downloads for all architectures (amd64 and arm64)
--list : List all supported systems
--list-csv : List everything in csv format
--list-json : List everything in json format
--download <os> <release> [edition] : Download image; no VM configuration
--create-config <os> [path/url] [flags] : Create VM config for an OS image
--open-homepage <os> : Open homepage for the OS
--show [os] : Show OS information
--version : Show version
--help : Show this help message
--disable-unattended : Force quickget not to set up an unattended installation
--url [os] [release] [edition] : Show image URL(s)
--check [os] [release] [edition] : Check image URL(s)
--list : List all supported systems
--list-csv : List everything in csv format
--list-json : List everything in json format
```
Here are some typical uses
@ -172,7 +167,7 @@ Further information is available from the project
- `archcraft` (Archcraft)
- `archlinux` (Arch Linux)
- `artixlinux` (Artix Linux)
- `azurelinux` (Azure Linux)
- `athenaos` (Athena OS)
- `batocera` (Batocera)
- `bazzite` (Bazzite)
- `biglinux` (BigLinux)
@ -200,6 +195,7 @@ Further information is available from the project
- `gnomeos` (GNOME OS)
- `guix` (Guix)
- `haiku` (Haiku)
- `holoiso` (HoloISO)
- `kali` (Kali)
- `kdeneon` (KDE Neon)
- `kolibrios` (KolibriOS)
@ -236,14 +232,16 @@ Further information is available from the project
- `slint` (Slint)
- `slitaz` (SliTaz)
- `solus` (Solus)
- `sparkylinux` (SparkyLinux)
- `spirallinux` (SpiralLinux)
- `tails` (Tails)
- `tinycore` (Tiny Core Linux)
- `trisquel` (Trisquel)
- `trisquel` (Trisquel-)
- `truenas-core` (TrueNAS Core)
- `truenas-scale` (TrueNAS Scale)
- `tuxedo-os` (Tuxedo OS)
- `vanillaos` (Vanilla OS)
- `void` (Void Linux)
- `vxlinux` (VX Linux)
- `zorin` (Zorin OS)
### [Custom Linux guests](https://github.com/quickemu-project/quickemu/wiki/02-Create-Linux-virtual-machines#manually-create-linux-guests)
@ -289,13 +287,6 @@ for solutions or ask for help there** 🛟
`quickget` automatically downloads a macOS recovery image and creates a
virtual machine configuration.
Note: Some VPN users may need to [turn off their
VPN](https://github.com/quickemu-project/quickemu/issues/1391#issuecomment-3506845235)
in order to download a recovery image. Some other users may find [using
a
VPN](https://github.com/quickemu-project/quickemu/issues/1391#issuecomment-2429146013)
necessary in order to download a recovery image.
``` shell
quickget macos big-sur
quickemu --vm macos-big-sur.conf
@ -370,13 +361,13 @@ The default macOS configuration looks like this:
``` shell
guest_os="macos"
img="macos-big-sur/RecoveryImage.img"
disk_img="macos-big-sur/disk.qcow2"
macos_release="big-sur"
img="macos- big-sur/RecoveryImage.img"
disk_img="macos- big-sur/disk.qcow2"
macos_release=" big-sur"
```
- `guest_os="macos"` instructs Quickemu to optimise for macOS.
- `macos_release="big-sur"` instructs Quickemu to optimise for a
- `macos_release=" big-sur"` instructs Quickemu to optimise for a
particular macOS release.
- For example VirtIO Network and Memory Ballooning are available in
Big Sur and newer, but not previous releases.

View File

@ -2,12 +2,12 @@
"nodes": {
"flake-schemas": {
"locked": {
"lastModified": 1775244557,
"narHash": "sha256-iYXRXIX9eafJmwJFAhqT3YxvvpNRuPFSLRCSpvGh8Ic=",
"rev": "15edbeeaf77e42216dbcba8bfd907fdeabb75a2b",
"revCount": 132,
"lastModified": 1761577921,
"narHash": "sha256-eK3/xbUOrxp9fFlei09XNjqcdiHXxndzrTXp7jFpOk8=",
"rev": "47849c7625e223d36766968cc6dc23ba0e135922",
"revCount": 107,
"type": "tarball",
"url": "https://api.flakehub.com/f/pinned/DeterminateSystems/flake-schemas/0.4.2/019d5cf2-ee3c-7313-964e-f3f83c35d509/source.tar.gz"
"url": "https://api.flakehub.com/f/pinned/DeterminateSystems/flake-schemas/0.2.0/019a4a84-544d-7c59-b26d-e334e320c932/source.tar.gz"
},
"original": {
"type": "tarball",
@ -16,18 +16,16 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1776877367,
"narHash": "sha256-EHq1/OX139R1RvBzOJ0aMRT3xnWyqtHBRUBuO1gFzjI=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "0726a0ecb6d4e08f6adced58726b95db924cef57",
"type": "github"
"lastModified": 1768940263,
"narHash": "sha256-sJERJIYTKPFXkoz/gBaBtRKke82h4DkX3BBSsKbfbvI=",
"rev": "3ceaaa8bc963ced4d830e06ea2d0863b6490ff03",
"revCount": 906247,
"type": "tarball",
"url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.2511.906247%2Brev-3ceaaa8bc963ced4d830e06ea2d0863b6490ff03/019be1ae-9947-752c-81ca-8b8670ae9892/source.tar.gz"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
"type": "tarball",
"url": "https://flakehub.com/f/NixOS/nixpkgs/%2A.tar.gz"
}
},
"root": {

View File

@ -2,7 +2,7 @@
description = "Quickemu flake";
inputs = {
flake-schemas.url = "https://flakehub.com/f/DeterminateSystems/flake-schemas/*.tar.gz";
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/*.tar.gz";
};
outputs =
@ -41,7 +41,7 @@
let
# OVMF is only available/needed on Linux
ovmfArgs =
if final.stdenv.hostPlatform.isLinux then
if final.stdenv.isLinux then
{ }
else
{
@ -60,7 +60,7 @@
let
# OVMF is only available/needed on Linux
ovmfArgs =
if pkgs.stdenv.hostPlatform.isLinux then
if pkgs.stdenv.isLinux then
{ }
else
{
@ -80,7 +80,7 @@
let
# OVMF is only available/needed on Linux
ovmfArgs =
if pkgs.stdenv.hostPlatform.isLinux then
if pkgs.stdenv.isLinux then
{ }
else
{

View File

@ -28,6 +28,7 @@
zsync,
OVMF ? null,
OVMFFull ? null,
quickemu,
}:
let
runtimePaths = [
@ -49,35 +50,33 @@ let
xrandr
zsync
]
++ lib.optionals stdenv.hostPlatform.isLinux [
++ lib.optionals stdenv.isLinux [
mesa-demos
OVMF
OVMFFull
usbutils
xdg-user-dirs
];
# Extract version using builtins.split to avoid regex backtracking on large files.
# builtins.match with .* patterns on multi-kilobyte files can cause stack overflow.
versionParts = builtins.split "readonly VERSION=\"([0-9]+\\.[0-9]+\\.[0-9]+)\"" (
builtins.readFile ./quickemu
);
version = builtins.elemAt (builtins.elemAt versionParts 1) 0;
versionMatches = builtins.match ''
.*
readonly[[:blank:]]VERSION="([[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+)"
.*
'' (builtins.readFile ./quickemu);
in
stdenv.mkDerivation (finalAttrs: {
stdenv.mkDerivation rec {
pname = "quickemu";
version = version;
version = builtins.concatStringsSep "" versionMatches;
src = lib.cleanSource ./.;
postPatch = ''
sed -i \
${
lib.optionalString (OVMF != null && OVMFFull != null) ''
-e '/OVMF_CODE_4M.secboot.fd/s|ovmfs=(|ovmfs=("${OVMFFull.firmware}","${OVMFFull.variablesMs}" |' \
-e '/OVMF_CODE_4M.secboot.fd/s|ovmfs=(|ovmfs=("${OVMFFull.firmware}","${OVMFFull.variables}" |' \
-e '/OVMF_CODE_4M.fd/s|ovmfs=(|ovmfs=("${OVMF.firmware}","${OVMF.variables}" |' \
''
} \
-e '/cp "''${VARS_IN}" "''${VARS_OUT}"/a chmod +w "''${VARS_OUT}"' \
-e 's/Icon=.*qemu.svg/Icon=qemu/' \
-e 's,\$(command -v smbd),${samba}/bin/smbd,' \
quickemu
'';
@ -104,12 +103,11 @@ stdenv.mkDerivation (finalAttrs: {
runHook postInstall
'';
passthru.tests = testers.testVersion { package = finalAttrs.finalPackage; };
passthru.tests = testers.testVersion { package = quickemu; };
meta = {
description = "Quickly create and run optimised Windows, macOS and Linux virtual machines";
homepage = "https://github.com/quickemu-project/quickemu";
changelog = "https://github.com/quickemu-project/quickemu/releases/tag/${finalAttrs.version}";
mainProgram = "quickemu";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [
@ -117,4 +115,4 @@ stdenv.mkDerivation (finalAttrs: {
flexiondotorg
];
};
})
}

1076
quickemu

File diff suppressed because it is too large Load Diff

532
quickget
View File

@ -8,20 +8,6 @@ export LC_ALL=C
# Detect host OS for checksum tool compatibility
HOST_OS=$(uname -s)
# Default architecture based on host
HOST_ARCH=$(uname -m)
case "${HOST_ARCH}" in
aarch64|arm64) ARCH="arm64";;
*) ARCH="amd64";;
esac
function arch_suffix() {
# Return architecture suffix for foreign architectures, empty for native
if [ "${ARCH}" != "${NORMALISED_HOST_ARCH}" ]; then
echo "-${ARCH}"
fi
}
function cleanup() {
if [ -n "$(jobs -p)" ]; then
kill "$(jobs -p)" 2>/dev/null
@ -41,7 +27,6 @@ function os_info() {
archcraft) INFO="Archcraft|-|https://archcraft.io/|Yet another minimal Linux distribution, based on Arch Linux.";;
archlinux) INFO="Arch Linux|-|https://archlinux.org/|Lightweight and flexible Linux® distribution that tries to Keep It Simple.";;
artixlinux) INFO="Artix Linux|-|https://artixlinux.org/|The Art of Linux. Simple. Fast. Systemd-free.";;
azurelinux) INFO="Azure Linux|-|https://github.com/microsoft/azurelinux|Microsoft's internal Linux distribution for cloud infrastructure and edge.";;
batocera) INFO="Batocera|-|https://batocera.org/|Retro-gaming distribution with the aim of turning any computer/nano computer into a gaming console during a game or permanently.";;
bazzite) INFO="Bazzite|-|https://github.com/ublue-os/bazzite/|Container native gaming and a ready-to-game SteamOS like.";;
biglinux) INFO="BigLinux|-|https://www.biglinux.com.br/|Is the right choice if you want to have an easy and enriching experience with Linux. It has been perfected over more than 19 years, following our motto: 'In search of the perfect system'.";;
@ -172,14 +157,10 @@ function error_specify_release() {
*ubuntu-server*)
echo -en " - Releases:\t"
releases_ubuntu-server
echo -en " - Archs:\t"
get_supported_archs "${OS}"
;;
*ubuntu*)
echo -en " - Releases:\t"
releases_ubuntu
echo -en " - Archs:\t"
get_supported_archs "${OS}"
;;
*windows*)
echo -en " - Releases:\t"
@ -187,7 +168,6 @@ function error_specify_release() {
echo -en " - Languages:\t"
"languages_${OS}"
echo "${I18NS[@]}"
# Windows uses multi-arch ISOs, skip architecture display
;;
*)
echo -en " - Releases:\t"
@ -196,8 +176,6 @@ function error_specify_release() {
echo -en " - Editions:\t"
"editions_${OS}" | fmt -w 80
fi
echo -en " - Archs:\t"
get_supported_archs "${OS}"
;;
esac
echo -e "\nERROR! You must specify a release."
@ -366,7 +344,6 @@ function test_result() {
local EDITION="${3:-}"
local URL="${4:-}"
local RESULT="${5:-}"
local REASON="${6:-}"
if [ -n "${EDITION}" ]; then
OS="${OS}-${RELEASE}-${EDITION}"
else
@ -376,11 +353,7 @@ function test_result() {
if [ -n "${RESULT}" ]; then
# Pad the OS string for consistent output
OS=$(printf "%-35s" "${OS}")
if [ -n "${REASON}" ]; then
echo -e "${RESULT}: ${OS} ${REASON}"
else
echo -e "${RESULT}: ${OS} ${URL}"
fi
echo -e "${RESULT}: ${OS} ${URL}"
else
OS=$(printf "%-36s" "${OS}:")
echo -e "${OS} ${URL}"
@ -401,11 +374,6 @@ function test_all() {
for RELEASE in $("releases_${FUNC}"); do
if [[ $(type -t "editions_${OS}") == function ]]; then
for EDITION in $(editions_"${OS}"); do
# Check architecture support before generating URL
if ! is_arch_supported "${OS}" "${ARCH}"; then
test_result "${OS}" "${RELEASE}" "${EDITION}" "" "SKIP" "(not available for ${ARCH})"
continue
fi
validate_release releases_"${OS}"
URL=$(get_"${OS}" | cut -d' ' -f1 | head -n 1)
if [ "${OPERATION}" == "show" ]; then
@ -429,27 +397,12 @@ function test_all() {
validate_release releases_macos
(get_macos)
elif [ "${OS}" == "ubuntu-server" ]; then
# Check architecture support before generating URL
if ! is_arch_supported "${OS}" "${ARCH}"; then
test_result "${OS}" "${RELEASE}" "" "" "SKIP" "(not available for ${ARCH})"
continue
fi
validate_release releases_ubuntu-server
(get_ubuntu-server)
elif [[ "${OS}" == *ubuntu* ]]; then
# Ubuntu desktop is amd64 only (no arch function = amd64 default)
if ! is_arch_supported "${OS}" "${ARCH}"; then
test_result "${OS}" "${RELEASE}" "" "" "SKIP" "(not available for ${ARCH})"
continue
fi
validate_release releases_ubuntu
(get_ubuntu)
else
# Check architecture support before generating URL
if ! is_arch_supported "${OS}" "${ARCH}"; then
test_result "${OS}" "${RELEASE}" "" "" "SKIP" "(not available for ${ARCH})"
continue
fi
validate_release releases_"${OS}"
URL=$(get_"${OS}" | cut -d' ' -f1 | head -n 1)
if [ "${OPERATION}" == "show" ]; then
@ -470,7 +423,6 @@ function os_support() {
archcraft \
archlinux \
artixlinux \
azurelinux \
batocera \
bazzite \
biglinux \
@ -614,10 +566,6 @@ function editions_artixlinux() {
echo $(web_pipe "https://mirror1.artixlinux.org/iso/" | grep "artix-" | cut -d'"' -f2 | grep -v sig | sed 's/artix-//' | sed 's/-[0-9]\{8\}-x86_64.iso//' | sort -u)
}
function releases_azurelinux() {
echo 3.0
}
function releases_batocera() {
#shellcheck disable=SC2046,SC2005
echo $(web_pipe "https://mirrors.o2switch.fr/batocera/x86_64/stable/" | grep ^\<a | cut -d'"' -f2 | cut -d '/' -f1 | grep -v '\.' | sort -ru | tail -n +2 | head -n 5)
@ -734,9 +682,9 @@ function releases_easyos() {
# get the latest 2 years of releases so that when we hit next year we still have the latest 2 years
TWO_YEARS=$(web_pipe https://distro.ibiblio.org/easyos/amd64/releases/kirkstone/ | grep -o -E '[[:digit:]]{4}/' | sort -nr | tr -d / | head -n 2 )
for YEAR in ${TWO_YEARS} ; do
ALL_RELEASES="${ALL_RELEASES} $(web_pipe "https://distro.ibiblio.org/easyos/amd64/releases/kirkstone/${YEAR}/" | grep -o -E '[[:digit:]]+(\.[[:digit:]])+/' | tr -d / | sort -nr)"
ALL_RELEASES="${ALL_RELEASES} $(web_pipe https://distro.ibiblio.org/easyos/amd64/releases/kirkstone/${YEAR}/ | grep -o -E '[[:digit:]]+(\.[[:digit:]])+/' | tr -d / | sort -nr)"
done
echo "${ALL_RELEASES}"
echo ${ALL_RELEASES}
}
@ -961,7 +909,7 @@ function releases_parrotsec() {
RELEASES="${RELEASES} ${REL}"
fi
done
echo "${RELEASES}"
echo ${RELEASES}
}
function editions_parrotsec() {
@ -1033,7 +981,7 @@ function releases_rebornos() {
function releases_rockylinux() {
#shellcheck disable=SC2046,SC2005
echo $(web_pipe "http://dl.rockylinux.org/vault/rocky/" | grep "class=\"link" | grep -v -e 'full' -e 'RC' -e 'ISO' -e 'Parent' | cut -d'"' -f4 | tr -d / | sort -ru)
echo $(web_pipe "http://dl.rockylinux.org/vault/rocky/" | grep "^<a href" | grep -v full | grep -v RC | grep -v ISO | cut -d'"' -f2 | tr -d / | sort -ru)
}
function editions_rockylinux() {
@ -1202,94 +1150,6 @@ function releases_zorin() {
echo 18 17 16
}
# Architecture support functions
# These declare which architectures each distro supports.
# Distros without an arch_*() function default to "amd64" only.
function arch_alma() {
echo "amd64 arm64"
}
function arch_alpine() {
echo "amd64 arm64"
}
function arch_azurelinux() {
echo "amd64 arm64"
}
function arch_debian() {
case "${EDITION}" in
netinst) echo "amd64 arm64";;
*) echo "amd64";;
esac
}
function arch_fedora() {
case "${EDITION}" in
Onyx) echo "amd64";;
*) echo "amd64 arm64";;
esac
}
function arch_ubuntu-server() {
echo "amd64 arm64"
}
function arch_ubuntu() {
# Ubuntu Desktop ARM64 only available from 25.10 onwards
local MAJOR MINOR
# When RELEASE is unset (initial arch check), return all supported architectures
# Actual validation happens in get_ubuntu() when release is known
if [ -z "${RELEASE}" ]; then
echo "amd64 arm64"
return
fi
# Non-numeric releases (daily-live, etc.) default to amd64 only
if [[ ! "${RELEASE}" =~ ^[0-9]+\.[0-9]+$ ]]; then
echo "amd64"
return
fi
MAJOR="${RELEASE%%.*}"
MINOR="${RELEASE##*.}"
# 25.10 and later support ARM64
if [ "${MAJOR}" -gt 25 ] || { [ "${MAJOR}" -eq 25 ] && [ "${MINOR}" -ge 10 ]; }; then
echo "amd64 arm64"
else
echo "amd64"
fi
}
# Check if a given architecture is supported for an OS
function is_arch_supported() {
local OS="${1}"
local CHECK_ARCH="${2}"
local SUPPORTED=""
# Check if arch function exists for this OS
if [[ $(type -t "arch_${OS}") == function ]]; then
SUPPORTED=$(arch_"${OS}")
else
# Default: amd64 only
SUPPORTED="amd64"
fi
# Check if requested arch is in supported list
[[ " ${SUPPORTED} " == *" ${CHECK_ARCH} "* ]]
}
# Get supported architectures for an OS
function get_supported_archs() {
local OS="${1}"
# Check if arch function exists for this OS
if [[ $(type -t "arch_${OS}") == function ]]; then
arch_"${OS}"
else
# Default: amd64 only
echo "amd64"
fi
}
function editions_zorin() {
# Lite edition not available for Zorin 18 (Pro-only starting from 18)
# When RELEASE is unset (e.g. csv_data context), return all editions
@ -1310,87 +1170,28 @@ function check_hash() {
iso="${VM_PATH}/${1}"
fi
hash="${2}"
# Guess the hash algorithm by the hash length
case ${#hash} in
32) hash_algo=md5sum;;
40) hash_algo=sha1sum;;
64) hash_algo=sha256sum;;
128) hash_algo=sha512sum;;
*) echo "WARNING! Can't guess hash algorithm, not checking ${iso} hash."
return;;
esac
# Check for algorithm prefix (e.g., "sha256:abc123..." or "b2sum:abc123...")
if [[ "${hash}" == *":"* ]]; then
local hash_prefix="${hash%%:*}"
hash="${hash#*:}"
# Normalise algorithm prefix to lowercase
hash_prefix="$(echo "${hash_prefix}" | tr '[:upper:]' '[:lower:]')"
case "${hash_prefix}" in
md5) hash_algo=md5sum;;
sha1) hash_algo=sha1sum;;
sha256) hash_algo=sha256sum;;
sha512) hash_algo=sha512sum;;
b2sum|blake2|blake2b) hash_algo=b2sum;;
*) echo "WARNING! Unknown hash algorithm '${hash_prefix}', not checking ${iso} hash."
return;;
esac
else
# Guess the hash algorithm by the hash length
case ${#hash} in
32) hash_algo=md5sum;;
40) hash_algo=sha1sum;;
64) hash_algo=sha256sum;;
128) hash_algo=sha512sum;;
*) echo "WARNING! Can't guess hash algorithm, not checking ${iso} hash."
return;;
esac
fi
# On macOS/Darwin, prefer GNU coreutils (prefixed with 'g') if available,
# otherwise fall back to native 'shasum' command
local hash_cmd="${hash_algo}"
# Use GNU coreutils on macOS/Darwin (prefixed with 'g')
if [ "${HOST_OS}" = "Darwin" ]; then
case ${hash_algo} in
md5sum)
if command -v gmd5sum &>/dev/null; then
hash_cmd=gmd5sum
else
# MD5 not directly supported by shasum; use native md5 command
hash_cmd="md5 -r"
fi;;
sha1sum)
if command -v gsha1sum &>/dev/null; then
hash_cmd=gsha1sum
else
hash_cmd="shasum -a 1"
fi;;
sha256sum)
if command -v gsha256sum &>/dev/null; then
hash_cmd=gsha256sum
else
hash_cmd="shasum -a 256"
fi;;
sha512sum)
if command -v gsha512sum &>/dev/null; then
hash_cmd=gsha512sum
else
hash_cmd="shasum -a 512"
fi;;
b2sum)
if command -v gb2sum &>/dev/null; then
hash_cmd=gb2sum
else
echo "WARNING! b2sum not available on macOS without GNU coreutils, not checking ${iso} hash."
return
fi;;
md5sum) hash_algo=gmd5sum;;
sha1sum) hash_algo=gsha1sum;;
sha256sum) hash_algo=gsha256sum;;
sha512sum) hash_algo=gsha512sum;;
esac
fi
echo -n "Checking ${iso} with ${hash_cmd}... "
# Handle MD5 on macOS specially (md5 -r outputs "hash filename" format)
if [ "${hash_cmd}" = "md5 -r" ]; then
local computed_hash
computed_hash=$(md5 -r "${iso}" | cut -d' ' -f1)
if [ "${computed_hash}" != "${hash}" ]; then
echo "ERROR!"
echo "${iso} doesn't match ${hash}. Try running 'quickget' again."
exit 1
else
echo "Good!"
fi
elif ! printf '%s %s\n' "${hash}" "${iso}" | ${hash_cmd} --check --status; then
echo -n "Checking ${iso} with ${hash_algo}... "
if ! echo "${hash} ${iso}" | ${hash_algo} --check --status; then
echo "ERROR!"
echo "${iso} doesn't match ${hash}. Try running 'quickget' again."
exit 1
@ -1442,11 +1243,6 @@ function web_get() {
test_result "${OS}" "${RELEASE}" "${EDITION}" "${URL}"
exit 0
elif [ "${OPERATION}" == "test" ]; then
# Check architecture support before testing URL
if ! is_arch_supported "${OS}" "${ARCH}"; then
test_result "${OS}" "${RELEASE}" "${EDITION}" "" "SKIP" "(not available for ${ARCH})"
exit 0
fi
CHECK=$(web_check "${URL}" && echo "PASS" || echo "FAIL")
test_result "${OS}" "${RELEASE}" "${EDITION}" "${URL}" "${CHECK}"
exit 0
@ -1462,12 +1258,12 @@ function web_get() {
if [[ ${OS} != windows && ${OS} != macos && ${OS} != windows-server ]]; then
echo "Downloading $(pretty_name "${OS}") ${RELEASE} ${EDITION}"
echo "- URL: ${URL}"
echo "- PATH: ${PWD}/${DIR}/${FILE}"
fi
if ! curl --disable --progress-bar --location --output "${DIR}/${FILE}" --continue-at - --user-agent "${USER_AGENT}" "${HEADERS[@]}" -- "${URL}"; then
echo "ERROR! Failed to download ${URL} with curl."
rm -f "${DIR}/${FILE}"
exit 1
fi
}
@ -1512,11 +1308,6 @@ function zsync_get() {
test_result "${OS}" "${RELEASE}" "${EDITION}" "${URL}"
exit 0
elif [ "${OPERATION}" == "test" ]; then
# Check architecture support before testing URL
if ! is_arch_supported "${OS}" "${ARCH}"; then
test_result "${OS}" "${RELEASE}" "${EDITION}" "" "SKIP" "(not available for ${ARCH})"
exit 0
fi
CHECK=$(web_check "${URL}" && echo "PASS" || echo "FAIL")
test_result "${OS}" "${RELEASE}" "${EDITION}" "${URL}" "${CHECK}"
exit 0
@ -1627,19 +1418,10 @@ function make_vm_config() {
if [ ! -e "${CONF_FILE}" ]; then
echo "Making ${CONF_FILE}"
local ARCH_LINE=""
if [ "${ARCH}" != "${NORMALISED_HOST_ARCH}" ]; then
if [ "${ARCH}" == "arm64" ]; then
ARCH_LINE="arch=\"aarch64\""
else
ARCH_LINE="arch=\"x86_64\""
fi
fi
cat << EOF > "${CONF_FILE}"
#!${QUICKEMU} --vm
guest_os="${GUEST}"
${ARCH_LINE:+${ARCH_LINE}
}disk_img="${VM_PATH}/disk.qcow2"
disk_img="${VM_PATH}/disk.qcow2"
${IMAGE_TYPE}="${VM_PATH}/${IMAGE_FILE}"
EOF
echo " - Setting ${CONF_FILE} executable"
@ -1659,7 +1441,7 @@ EOF
echo "disk_size=\"8G\"" >> "${CONF_FILE}";;
bazzite)
echo "disk_size=\"64G\"" >> "${CONF_FILE}";;
dragonflybsd|haiku|openbsd|netbsd|slackware|slax|tinycore)
dragonflybsd|haiku|openbsd|netbsd|slackware|slax|tails|tinycore)
echo "boot=\"legacy\"" >> "${CONF_FILE}";;
deepin)
echo "disk_size=\"64G\"" >> "${CONF_FILE}"
@ -1754,10 +1536,8 @@ EOF
function get_alma() {
local HASH=""
local QEMU_ARCH="x86_64"
[ "${ARCH}" == "arm64" ] && QEMU_ARCH="aarch64"
local ISO="AlmaLinux-${RELEASE}-latest-${QEMU_ARCH}-${EDITION}.iso"
local URL="https://repo.almalinux.org/almalinux/${RELEASE}/isos/${QEMU_ARCH}"
local ISO="AlmaLinux-${RELEASE}-latest-x86_64-${EDITION}.iso"
local URL="https://repo.almalinux.org/almalinux/${RELEASE}/isos/x86_64"
HASH="$(web_pipe "${URL}/CHECKSUM" | grep "(${ISO}" | cut -d' ' -f4)"
echo "${URL}/${ISO} ${HASH}"
}
@ -1765,13 +1545,11 @@ function get_alma() {
function get_alpine() {
local HASH=""
local ISO=""
local QEMU_ARCH="x86_64"
[ "${ARCH}" == "arm64" ] && QEMU_ARCH="aarch64"
local URL="https://dl-cdn.alpinelinux.org/alpine/${RELEASE}/releases/${QEMU_ARCH}"
local URL="https://dl-cdn.alpinelinux.org/alpine/${RELEASE}/releases/x86_64"
local VERSION=""
VERSION=$(web_pipe "${URL}/latest-releases.yaml" | awk '/"Xen"/{found=0} {if(found) print} /"Virtual"/{found=1}' | grep 'version:' | head -1 | awk '{print $2}')
ISO="alpine-virt-${VERSION}-${QEMU_ARCH}.iso"
HASH=$(web_pipe "${URL}/latest-releases.yaml" | awk '/"Xen"/{found=0} {if(found) print} /"Virtual"/{found=1}' | grep 'sha256:' | head -1 | awk '{print $2}')
VERSION=$(web_pipe "${URL}/latest-releases.yaml" | awk '/"Xen"/{found=0} {if(found) print} /"Virtual"/{found=1}' | grep 'version:' | awk '{print $2}')
ISO="alpine-virt-${VERSION}-x86_64.iso"
HASH=$(web_pipe "${URL}/latest-releases.yaml" | awk '/"Xen"/{found=0} {if(found) print} /"Virtual"/{found=1}' | grep 'sha256:' | awk '{print $2}')
echo "${URL}/${ISO} ${HASH}"
}
@ -1822,14 +1600,9 @@ function get_antix() {
function get_archcraft() {
local HASH=""
local ISO=""
local URL=""
local VERSION_FOLDER=""
URL="https://sourceforge.net/projects/archcraft/files/${RELEASE}/download"
URL="$(web_redirect "${URL}" | cut -d? -f1)"
ISO="$(basename "${URL}")"
VERSION_FOLDER="$(dirname "${URL}" | xargs basename)"
HASH=$(web_pipe "https://sourceforge.net/projects/archcraft/files/${VERSION_FOLDER}/${ISO}.sha256sum" | cut -d' ' -f1)
echo "${URL} ${HASH}"
}
@ -1851,15 +1624,6 @@ function get_artixlinux() {
echo "${URL}/${ISO} ${HASH}"
}
function get_azurelinux() {
local QEMU_ARCH="x86_64"
[ "${ARCH}" == "arm64" ] && QEMU_ARCH="aarch64"
local URL="https://aka.ms/azurelinux-${RELEASE}-${QEMU_ARCH}.iso"
local ISO
ISO="$(web_redirect "${URL}")"
echo "${ISO}"
}
function get_batocera() {
local HASH=""
local ISO=""
@ -1953,21 +1717,13 @@ function get_crunchbang++() {
}
function get_debian() {
local DEBIAN_ARCH="${ARCH}"
local DEBCURRENT=""
local HASH=""
local ISO="debian-live-${RELEASE}-${DEBIAN_ARCH}-${EDITION}.iso"
local URL="https://cdimage.debian.org/cdimage/archive/${RELEASE}-live/${DEBIAN_ARCH}/iso-hybrid"
# Debian only provides netinst images for ARM64
if [ "${DEBIAN_ARCH}" == "arm64" ] && [ "${EDITION}" != "netinst" ]; then
echo "ERROR! Debian ${EDITION} is not available for ARM64. Use 'netinst' edition."
exit 1
fi
local ISO="debian-live-${RELEASE}-amd64-${EDITION}.iso"
local URL="https://cdimage.debian.org/cdimage/archive/${RELEASE}-live/amd64/iso-hybrid"
DEBCURRENT=$(web_pipe "https://cdimage.debian.org/debian-cd/" | grep '\.[0-9]/' | cut -d'>' -f 9 | cut -d'/' -f 1)
case "${RELEASE}" in
"${DEBCURRENT}") URL="https://cdimage.debian.org/debian-cd/${RELEASE}-live/${DEBIAN_ARCH}/iso-hybrid";;
"${DEBCURRENT}") URL="https://cdimage.debian.org/debian-cd/${RELEASE}-live/amd64/iso-hybrid";;
esac
if [ "${EDITION}" == "netinst" ]; then
URL="${URL/-live/}"
@ -2086,15 +1842,11 @@ function get_endless() {
}
function get_fedora() {
local FEDORA_ARCH="x86_64"
local HASH=""
local ISO=""
local JSON=""
local URL=""
local VARIANT=""
[ "${ARCH}" == "arm64" ] && FEDORA_ARCH="aarch64"
case ${EDITION} in
Server|Kinoite|Onyx|Silverblue|Sericea|Workstation|KDE) VARIANT="${EDITION}";;
*) VARIANT="Spins";;
@ -2112,10 +1864,12 @@ function get_fedora() {
RELEASE="${RELEASE/_/ }"
fi
# shellcheck disable=SC2086
# Fedora may promote variants from Spins to Editions, in which case we want to accept either "Spins" or the specific edition name to preserve backwards compatibility
# For example, Fedora 42 KDE is now an edition, while previous releases are spins
JSON=$(web_pipe "https://getfedora.org/releases.json" | jq '.[] | select((.variant=="'"${VARIANT}"'" or .variant=="'"${EDITION}"'") and .subvariant=="'"${EDITION}"'" and .arch=="'"${FEDORA_ARCH}"'" and .version=="'"${RELEASE}"'" and (.link | endswith(".iso")))')
JSON=$(web_pipe "https://getfedora.org/releases.json" | jq '.[] | select((.variant=="'"${VARIANT}"'" or .variant=="'"${EDITION}"'") and .subvariant=="'"${EDITION}"'" and .arch=="x86_64" and .version=="'"${RELEASE}"'" and (.link | endswith(".iso")))')
URL=$(echo "${JSON}" | jq -r '.link' | head -n1)
HASH=$(echo "${JSON}" | jq -r '.sha256' | head -n1)
echo "${URL} ${HASH}"
@ -2233,7 +1987,6 @@ function get_kolibrios() {
local HASH=""
local ISO="latest-iso.7z"
local URL="http://builds.kolibrios.org/${EDITION}"
HASH=$(web_pipe "${URL}/sha256sums.txt" | grep "${ISO}" | cut -d' ' -f1)
echo "${URL}/${ISO} ${HASH}"
}
@ -2263,12 +2016,9 @@ function get_lmde() {
function get_maboxlinux() {
local HASH=""
local ISO=""
local URL=""
URL="https://sourceforge.net/projects/mabox-linux/files/${RELEASE}/download"
URL="$(web_redirect "${URL}" | cut -d? -f1)"
ISO="$(basename "${URL}")"
HASH=$(web_pipe "https://repo.maboxlinux.org/iso/${ISO}.md5" | cut -d' ' -f1)
echo "${URL} ${HASH}"
}
@ -2398,14 +2148,11 @@ function get_macos() {
rm "${VM_PATH}/RecoveryImage.dmg" "${VM_PATH}/RecoveryImage.chunklist"
echo " - RecoveryImage.img is ready."
fi
echo "Downloading OpenCore & UEFI firmware"
# Pin to last known-good commit; OVMF_CODE.fd was removed from master on 26 Jan 2026
local OSX_KVM_COMMIT="da4b23b5e92c5b939568700034367e8b7649fe90"
web_get "https://github.com/kholia/OSX-KVM/raw/${OSX_KVM_COMMIT}/OpenCore/OpenCore.qcow2" "${VM_PATH}"
web_get "https://github.com/kholia/OSX-KVM/raw/${OSX_KVM_COMMIT}/OVMF_CODE.fd" "${VM_PATH}"
web_get "https://github.com/kholia/OSX-KVM/raw/master/OpenCore/OpenCore.qcow2" "${VM_PATH}"
web_get "https://github.com/kholia/OSX-KVM/raw/master/OVMF_CODE.fd" "${VM_PATH}"
if [ ! -e "${VM_PATH}/OVMF_VARS-1920x1080.fd" ]; then
web_get "https://github.com/kholia/OSX-KVM/raw/${OSX_KVM_COMMIT}/OVMF_VARS-1920x1080.fd" "${VM_PATH}"
web_get "https://github.com/kholia/OSX-KVM/raw/master/OVMF_VARS-1920x1080.fd" "${VM_PATH}"
fi
fi
make_vm_config RecoveryImage.img
@ -2683,12 +2430,13 @@ function get_rebornos() {
}
function get_rockylinux() {
if { [[ "${RELEASE}" =~ ^8. ]] || [[ "${RELEASE}" =~ ^10. ]]; } && [[ "${EDITION}" == "dvd" ]]; then
if [[ "${RELEASE}" =~ ^8. ]] && [[ "${EDITION}" == "dvd" ]]; then
EDITION="dvd1"
fi
local HASH=""
local ISO="Rocky-${RELEASE}-x86_64-${EDITION}.iso"
local URL="https://dl.rockylinux.org/vault/rocky/${RELEASE}/isos/x86_64"
local URL=""
URL="https://dl.rockylinux.org/vault/rocky/${RELEASE}/isos/x86_64"
HASH=$(web_pipe "${URL}/CHECKSUM" | grep "SHA256" | grep "${ISO})" | cut -d' ' -f4)
echo "${URL}/${ISO} ${HASH}"
}
@ -2833,18 +2581,13 @@ function get_tuxedo-os() {
}
function get_ubuntu-server() {
local DATA=""
local HASH=""
local ISO=""
local NAME="live-server"
local UBUNTU_ARCH="${ARCH}"
local URL=""
if [[ "${RELEASE}" == "daily"* ]]; then
URL="https://cdimage.ubuntu.com/${OS}/${RELEASE}/current"
elif [ "${UBUNTU_ARCH}" == "arm64" ]; then
# ARM64 ISOs are hosted on cdimage.ubuntu.com
URL="https://cdimage.ubuntu.com/releases/${RELEASE}/release"
else
URL="https://releases.ubuntu.com/${RELEASE}"
fi
@ -2854,11 +2597,11 @@ function get_ubuntu-server() {
esac
if web_check "${URL}/SHA256SUMS"; then
DATA=$(web_pipe "${URL}/SHA256SUMS" | grep "${NAME}" | grep "${UBUNTU_ARCH}" | grep iso | tail -n 1 )
DATA=$(web_pipe "${URL}/SHA256SUMS" | grep "${NAME}" | grep amd64 | grep iso | tail -n 1 )
ISO=$(cut -d'*' -f2 <<<"${DATA}")
HASH=$(cut -d' ' -f1 <<<"${DATA}")
else
DATA=$(web_pipe "${URL}/MD5SUMS" | grep "${NAME}" | grep "${UBUNTU_ARCH}" | grep iso | tail -n 1 )
DATA=$(web_pipe "${URL}/MD5SUMS" | grep "${NAME}" | grep amd64 | grep iso | tail -n 1 )
ISO=$(cut -d' ' -f3 <<<"${DATA}")
HASH=$(cut -d' ' -f1 <<<"${DATA}")
fi
@ -2873,22 +2616,10 @@ function get_ubuntu-server() {
}
function get_ubuntu() {
local DATA=""
local HASH=""
local ISO=""
local UBUNTU_ARCH="${ARCH}"
local HASH=""
local URL=""
# Validate architecture support now that RELEASE is known
if ! is_arch_supported "${OS}" "${UBUNTU_ARCH}"; then
if [ "${OPERATION}" == "test" ] || [ "${OPERATION}" == "show" ]; then
test_result "${OS}" "${RELEASE}" "" "" "SKIP" "(not available for ${UBUNTU_ARCH})"
exit 0
else
echo "ERROR! $(pretty_name "${OS}") ${RELEASE} is not available for ${UBUNTU_ARCH} architecture."
exit 1
fi
fi
local DATA=""
if [[ "${RELEASE}" == "daily"* ]] && [ "${OS}" == "ubuntustudio" ]; then
# Ubuntu Studio daily-live images are in the dvd directory
@ -2900,24 +2631,21 @@ function get_ubuntu() {
else
URL="https://cdimage.ubuntu.com/${OS}/jammy/daily-live/current"
fi
VM_PATH="${OS}-jammy-live$(arch_suffix)"
VM_PATH="${OS}-jammy-live"
elif [[ "${RELEASE}" == "daily"* ]] || [ "${RELEASE}" == "dvd" ]; then
URL="https://cdimage.ubuntu.com/${OS}/${RELEASE}/current"
VM_PATH="${OS}-${RELEASE}$(arch_suffix)"
elif [ "${OS}" == "ubuntu" ] && [ "${UBUNTU_ARCH}" == "arm64" ]; then
# ARM64 desktop ISOs are hosted on cdimage.ubuntu.com
URL="https://cdimage.ubuntu.com/releases/${RELEASE}/release"
VM_PATH="${OS}-${RELEASE}"
elif [ "${OS}" == "ubuntu" ]; then
URL="https://releases.ubuntu.com/${RELEASE}"
else
URL="https://cdimage.ubuntu.com/${OS}/releases/${RELEASE}/release"
fi
if web_check "${URL}/SHA256SUMS"; then
DATA=$(web_pipe "${URL}/SHA256SUMS" | grep 'desktop\|dvd\|install' | grep "${UBUNTU_ARCH}" | grep iso | grep -v "+mac" | tail -n 1 )
DATA=$(web_pipe "${URL}/SHA256SUMS" | grep 'desktop\|dvd\|install' | grep amd64 | grep iso | grep -v "+mac" | tail -n 1 )
ISO=$(cut -d'*' -f2 <<<"${DATA}" | sed '1q;d')
HASH=$(cut -d' ' -f1 <<<"${DATA}" | sed '1q;d')
else
DATA=$(web_pipe "${URL}/MD5SUMS" | grep 'desktop\|dvd\|install' | grep "${UBUNTU_ARCH}" | grep iso | grep -v "+mac" | tail -n 1 )
DATA=$(web_pipe "${URL}/MD5SUMS" | grep 'desktop\|dvd\|install' | grep amd64 | grep iso | grep -v "+mac" | tail -n 1 )
ISO=$(cut -d'*' -f2 <<<"${DATA}")
HASH=$(cut -d' ' -f1 <<<"${DATA}")
fi
@ -3618,10 +3346,7 @@ function create_vm() {
if [[ ${ISO} = *".gz"* ]]; then
gzip -d "${VM_PATH}/${ISO}"
ISO="${ISO/.gz/}"
fi
# Resize the raw image to provide space for Batocera's partition expansion
require_qemu_img
${QEMU_IMG} resize -f raw "${VM_PATH}/${ISO}" 128G;;
fi;;
dragonflybsd)
# Could be other OS iso files compressed with bzip2 or gzip
# but for now we'll keep this to know cases
@ -3763,23 +3488,21 @@ Advanced usage:
quickget --download ubuntu 22.04
Arguments:
--arch <arch> : Set architecture (arm64, aarch64, amd64, x86_64)
--download <os> <release> [edition] : Download image; no VM configuration
--create-config <os> [path/url] [flags] : Create VM config for an OS image
--open-homepage <os> : Open homepage for the OS
--show [os] : Show OS information
--version : Show version
--help : Show this help message
--download <os> <release> [edition] : Download image; no VM configuration
--create-config <os> [path/url] [flags] : Create VM config for an OS image
--open-homepage <os> : Open homepage for the OS
--show [os] : Show OS information
--version : Show version
--help : Show this help message
------------------------------------ Flags -------------------------------------
--create-config:
--disable-unattended : Force quickget not to set up an unattended installation
--disable-unattended : Force quickget not to set up an unattended installation
-------------------------- For testing & development ---------------------------
--url [os] [release] [edition] : Show image URL(s)
--check [os] [release] [edition] : Check image URL(s)
--check-all-arch [os] [release] [edition] : Check downloads for all architectures (amd64 and arm64)
--list : List all supported systems
--list-csv : List everything in csv format
--list-json : List everything in json format
--url [os] [release] [edition] : Show image URL(s)
--check [os] [release] [edition] : Check image URL(s)
--list : List all supported systems
--list-csv : List everything in csv format
--list-json : List everything in json format
--------------------------------------------------------------------------------
Supported Operating Systems:\n\n' "$(${QUICKEMU} --version)" "${CURL_VERSION}"
@ -3796,9 +3519,6 @@ fi
QUICKEMU=$(resolve_quickemu)
I18NS=()
OPERATION=""
CHECK_ALL_ARCH="false"
# Normalised host architecture for foreign arch detection
NORMALISED_HOST_ARCH="${ARCH}"
CURL=$(command -v curl)
if [ ! -x "${CURL}" ]; then
echo "ERROR! curl not found. Please install curl"
@ -3807,33 +3527,10 @@ fi
CURL_VERSION=$("${CURL}" --version | head -n 1 | cut -d' ' -f2)
#TODO: Deprecate `list`, `list_csv`, and `list_json` in favor of `--list`, `--list-csv`, and `--list-json`
# Function to process --arch flag
function parse_arch_flag() {
if [ "${1}" == "--arch" ] || [ "${1}" == "-arch" ]; then
case "${2}" in
arm64|aarch64) ARCH="arm64";;
amd64|x86_64) ARCH="amd64";;
*) echo "ERROR! Unsupported architecture: ${2}"; exit 1;;
esac
return 0 # Flag was found
fi
return 1 # Flag was not found
}
# Process --arch flag first if present (can be combined with other flags)
if parse_arch_flag "${1}" "${2}"; then
shift 2
fi
case "${1}" in
--download|-download)
OPERATION="download"
shift
# Handle --arch after --download
if parse_arch_flag "${1}" "${2}"; then
shift 2
fi
;;
--create-config|-create-config)
OPERATION="config"
@ -3864,10 +3561,6 @@ case "${1}" in
--url|-url)
OPERATION="show"
shift
# Handle --arch after --url
if parse_arch_flag "${1}" "${2}"; then
shift 2
fi
if [ -z "${1}" ]; then
for OS in $(os_support); do
(test_all "${OS}")
@ -3880,10 +3573,6 @@ case "${1}" in
--check|-check)
OPERATION="test"
shift
# Handle --arch after --check
if parse_arch_flag "${1}" "${2}"; then
shift 2
fi
if [ -z "${1}" ]; then
for OS in $(os_support); do
(test_all "${OS}")
@ -3893,25 +3582,6 @@ case "${1}" in
test_all "${1}"
exit 0
fi;;
--check-all-arch|-check-all-arch)
OPERATION="test"
CHECK_ALL_ARCH="true"
shift
if [ -z "${1}" ]; then
for CHECK_ARCH in amd64 arm64; do
ARCH="${CHECK_ARCH}"
for OS in $(os_support); do
(test_all "${OS}")
done
done
exit 0
elif [ -z "${2}" ]; then
for CHECK_ARCH in amd64 arm64; do
ARCH="${CHECK_ARCH}"
test_all "${1}"
done
exit 0
fi;;
--list-csv|-list-csv|list|list_csv) list_csv;;
--list-json|-list-json|list_json) list_json;;
--list|-list) list_supported;;
@ -3926,69 +3596,9 @@ fi
os_supported
# Handle --check-all-arch for specific release/edition
if [ "${CHECK_ALL_ARCH}" == "true" ] && [ -n "${2}" ]; then
RELEASE="${2}"
EDITION="${3:-}"
for CHECK_ARCH in amd64 arm64; do
ARCH="${CHECK_ARCH}"
# Check architecture support before testing URL
if ! is_arch_supported "${OS}" "${ARCH}"; then
if [ -n "${EDITION}" ]; then
test_result "${OS}" "${RELEASE}" "${EDITION}" "" "SKIP" "(not available for ${ARCH})"
else
test_result "${OS}" "${RELEASE}" "" "" "SKIP" "(not available for ${ARCH})"
fi
continue
fi
# Validate release
case ${OS} in
*ubuntu-server*) validate_release releases_ubuntu-server;;
*ubuntu*) validate_release releases_ubuntu;;
*) validate_release "releases_${OS}";;
esac
# Generate and check URL
if [[ $(type -t "editions_${OS}") == function ]] && [ -n "${EDITION}" ]; then
URL=$(get_"${OS}" | cut -d' ' -f1 | head -n 1)
elif [ "${OS}" == "macos" ]; then
(get_macos)
continue
elif [[ "${OS}" == *"ubuntu-server"* ]]; then
(get_ubuntu-server)
continue
elif [[ "${OS}" == *"ubuntu"* ]]; then
(get_ubuntu)
continue
elif [[ "${OS}" == "windows"* ]]; then
test_result "${OS}" "${RELEASE}" "${EDITION}" "" "SKIP" "(Windows not supported in check mode)"
continue
else
URL=$(get_"${OS}" | cut -d' ' -f1 | head -n 1)
fi
CHECK=$(web_check "${URL}" && echo "PASS" || echo "FAIL")
test_result "${OS}" "${RELEASE}" "${EDITION}" "${URL}" "${CHECK}"
done
exit 0
fi
# Validate architecture support before attempting download
# Skip for OSes with editions_* functions - they have edition-dependent arch support
# and will be validated after EDITION is parsed
if [[ $(type -t "editions_${OS}") != function ]]; then
if ! is_arch_supported "${OS}" "${ARCH}"; then
if [ "${OPERATION}" == "test" ] || [ "${OPERATION}" == "show" ]; then
test_result "${OS}" "${2:-}" "${3:-}" "" "SKIP" "(not available for ${ARCH})"
exit 0
else
echo "ERROR! $(pretty_name "${OS}") is not available for ${ARCH} architecture."
exit 1
fi
fi
fi
if [ -n "${2}" ]; then
RELEASE="${2}"
VM_PATH="${OS}-${RELEASE}$(arch_suffix)"
VM_PATH="${OS}-${RELEASE}"
# If the OS has an editions_() function, use it.
if [[ $(type -t "editions_${OS}") == function ]]; then
validate_release "releases_${OS}"
@ -4010,18 +3620,8 @@ if [ -n "${2}" ]; then
echo -e "\nERROR! You must specify an edition."
exit 1
fi
# Now that EDITION is known, validate architecture support
if ! is_arch_supported "${OS}" "${ARCH}"; then
if [ "${OPERATION}" == "test" ] || [ "${OPERATION}" == "show" ]; then
test_result "${OS}" "${RELEASE}" "${EDITION}" "" "SKIP" "(not available for ${ARCH})"
exit 0
else
echo "ERROR! $(pretty_name "${OS}") ${EDITION} is not available for ${ARCH} architecture."
exit 1
fi
fi
handle_missing
VM_PATH="${OS}-${RELEASE}-${EDITION}$(arch_suffix)"
VM_PATH="${OS}-${RELEASE}-${EDITION}"
create_vm "$("get_${OS}" "${EDITION}")"
elif [ "${OS}" == "macos" ]; then
# macOS doesn't use create_vm()
@ -4044,7 +3644,7 @@ if [ -n "${2}" ]; then
if ! is_valid_language "${I18N}"; then
error_not_supported_lang
fi
VM_PATH="$(echo "${OS}-${RELEASE}-${I18N// /-}" | tr -d '()')$(arch_suffix)"
VM_PATH="$(echo "${OS}-${RELEASE}-${I18N// /-}" | tr -d '()')"
fi
validate_release "releases_${OS}"
get_windows