feat: flip images to UEFI default (#237)

This commit is contained in:
Julian Sommer
2026-05-20 12:34:51 +10:00
committed by GitHub
parent 78d179c89b
commit 20a8a39608
13 changed files with 98 additions and 47 deletions
+1
View File
@@ -170,6 +170,7 @@ install-system:
-o Dpkg::Options::="--force-confdef" \
-o Dpkg::Options::="--force-confold" \
nbdkit nbdkit-plugin-dev pkg-config $(QEMU_PACKAGES) qemu-utils qemu-kvm \
ovmf qemu-efi-aarch64 \
libvirt-daemon-system libvirt-clients libvirt-dev make gcc jq curl \
iproute2 netcat-openbsd openssh-client wget git unzip sudo xz-utils file \
ovn-central ovn-host openvswitch-switch dhcpcd-base
+25
View File
@@ -84,6 +84,14 @@ var supportedPlatforms = map[string]bool{
"Windows": true,
}
// Mirrors the gateway RegisterImage allowlist so admin imports can't write an
// AMI with a boot mode that RegisterImage would reject.
var supportedBootModes = map[string]bool{
"bios": true,
"uefi": true,
"uefi-preferred": true,
}
var adminCmd = &cobra.Command{
Use: "admin",
Short: "Administrative commands for Spinifex platform management",
@@ -304,6 +312,7 @@ func init() {
imagesImportCmd.Flags().String("version", "", "Specified distro version (e.g 12)")
imagesImportCmd.Flags().String("arch", "", "Specified distro arch (e.g aarch64, arm64, x86_64)")
imagesImportCmd.Flags().String("platform", "Linux/UNIX", "Specified platform (e.g Linux/UNIX, Windows)")
imagesImportCmd.Flags().String("boot-mode", "", "Boot mode for the imported AMI (bios|uefi|uefi-preferred). Required with --file. Overrides the catalog value when used with --name.")
imagesImportCmd.Flags().StringSlice("tag", nil, "Tag to apply to the imported AMI as key=value (repeatable; e.g. --tag spinifex:managed-by=elbv2)")
imagesImportCmd.Flags().Bool("force", false, "Force command execution (overwrites existing files)")
imagesImportCmd.Flags().Bool("skip-verify", false, "Skip catalog-image checksum verification (INSECURE; operator assumes integrity responsibility)")
@@ -376,6 +385,22 @@ func runimagesImportCmd(cmd *cobra.Command, args []string) {
}
}
// --file imports have no catalog metadata to inherit from, so the operator
// must declare the boot mode explicitly — guessing would silently produce
// a BIOS AMI from a UEFI-only image (or vice versa) and fail at launch.
// --name imports inherit from the catalog; the flag overrides when set.
bootModeFlag, _ := cmd.Flags().GetString("boot-mode")
if bootModeFlag != "" {
if !supportedBootModes[bootModeFlag] {
fmt.Fprintf(os.Stderr, "Unsupported --boot-mode %q (expected bios|uefi|uefi-preferred)\n", bootModeFlag)
os.Exit(1)
}
image.BootMode = bootModeFlag
} else if imageName == "" {
fmt.Fprintf(os.Stderr, "--boot-mode is required when importing via --file (expected bios|uefi|uefi-preferred)\n")
os.Exit(1)
}
// --tag k=v (repeatable) merges user-supplied tags into the AMI. Overrides
// catalog tags on key collision so operators can re-tag a known image.
tagFlags, _ := cmd.Flags().GetStringSlice("tag")
+2 -2
View File
@@ -89,7 +89,7 @@ Operational commands for inspecting cluster state. These fan out NATS requests t
| Command | Flags | Prerequisites | Basic Logic | Test Cases | Status |
|---------|-------|---------------|-------------|------------|--------|
| `spx admin images import` | `--name`, `--file`, `--force`, `--skip-verify` | Cluster must be running; either `--name` (catalog download) or `--file` (operator-supplied media) | Catalog imports (`--name`) download the image, fetch the catalog `Checksum` URL, and verify the SHA-256/SHA-512 digest before extraction. Mismatch fails closed; the cached file is left on disk and `--force` re-downloads. `--file` imports skip verification — operator-supplied media is outside Spinifex's trust boundary, and the skip is logged at INFO for audit. `--skip-verify` bypasses verification for catalog imports and emits a WARN slog + stderr notice; use only for debugging or when upstream mirrors are confirmed-broken. | 1. Import valid catalog image (verifies checksum)<br>2. Tampered cache hit fails with `ErrChecksumMismatch`<br>3. `--force` recovers after a mismatch<br>4. `--file` import skips verification<br>5. `--skip-verify` bypasses checksum with WARN | **DONE** |
| `spx admin images import` | `--name`, `--file`, `--distro`, `--version`, `--arch`, `--platform`, `--boot-mode` (bios/uefi/uefi-preferred), `--tag`, `--force`, `--skip-verify` | Cluster must be running; either `--name` (catalog download) or `--file` (operator-supplied media). `--file` mode additionally requires `--distro`, `--version`, `--arch`, `--boot-mode`. | Catalog imports (`--name`) download the image, fetch the catalog `Checksum` URL, verify the SHA-256/SHA-512 digest, and inherit `BootMode` from the catalog entry. `--boot-mode` overrides the catalog value when set. Mismatch fails closed; the cached file is left on disk and `--force` re-downloads. `--file` imports skip checksum verification (operator-supplied media is outside Spinifex's trust boundary, the skip is logged at INFO for audit) and require an explicit `--boot-mode` because there is no catalog metadata to inherit from. `--skip-verify` bypasses verification for catalog imports and emits a WARN slog + stderr notice; use only for debugging or when upstream mirrors are confirmed-broken. | 1. Import valid catalog image (verifies checksum)<br>2. Tampered cache hit fails with `ErrChecksumMismatch`<br>3. `--force` recovers after a mismatch<br>4. `--file` import skips verification<br>5. `--skip-verify` bypasses checksum with WARN<br>6. `--file` without `--boot-mode` rejected<br>7. `--boot-mode=invalid` rejected | **DONE** |
| `spx admin images list` | — | None | Lists available OS images that can be imported or downloaded | 1. List available images | **DONE** |
#### Image integrity verification (CMMC SI.L1-3.14.2)
@@ -168,7 +168,7 @@ file, deferred to a later phase.
|---------|-------------------|---------------|---------------|-------------|------------|--------|
| `describe-images` | `--image-ids` (format validation only), `--owners` (self, account ID, alias), `--filters` (name, state, architecture, image-id, is-public, owner-id, description, image-type, tag:\*) | `--executable-users`, `--include-deprecated`, `--include-disabled`, `--max-results`, `--next-token`, `--dry-run` | None | NATS `ec2.DescribeImages` → daemon reads AMI metadata from Predastore S3 buckets (ami-*) → filters by ImageIds, Owners, and Filters → returns image list with state, architecture, block device mappings | 1. List all images<br>2. Filter by image ID<br>3. Filter by owner (self/amazon)<br>4. Non-existent AMI returns empty<br>5. Verify metadata fields (architecture, state, rootDeviceName)<br>6. Filter by name wildcard<br>7. Unknown filter returns InvalidParameterValue | **DONE** |
| `create-image` | `--instance-id`, `--name`, `--description`, `--tag-specifications` | `--no-reboot`, `--block-device-mappings`, `--dry-run` | Instance must exist (running or stopped) | Gateway validates input → NATS `ec2.{instanceId}.CreateImage` (per-instance topic) → daemon extracts root volume → snapshots via `ebs.snapshot` NATS (running) or offline S3 copy (stopped) → creates AMI metadata in S3 (`{amiId}/config.json`) → stores tags → returns ami-ID. Duplicate AMI name validation enforced. | 1. Create image from running instance<br>2. Create image from stopped instance<br>3. Invalid instance ID (error)<br>4. Duplicate AMI name (error)<br>5. Verify new AMI appears in describe-images<br>6. Launch new instance from created AMI | **DONE** |
| `register-image` | `--name`, `--description`, `--architecture` (x86_64/arm64/i386), `--root-device-name`, `--virtualization-type` (hvm only), `--block-device-mappings` (root with `Ebs.SnapshotId`+optional `VolumeSize`), `--tag-specifications` | `--billing-products`, `--uefi-data` | Backing snapshot must exist in Predastore (`{snapshotId}/metadata.json`); caller must own snapshot or it must be system-owned | Gateway validates name length (3–128), `snap-` prefix, architecture/virtualization values → NATS `ec2.RegisterImage` → daemon checks AMI name uniqueness, reads snapshot metadata, verifies snapshot ownership, builds `viperblock.AMIMetadata` (defaults: `Architecture=x86_64`, `Virtualization=hvm`, `PlatformDetails=Linux/UNIX`, `RootDeviceType=ebs`), writes `{amiId}/config.json`. Pointer-only — never touches block data. `BootMode`, `KernelId`, `RamdiskId`, `TpmSupport`, `ImdsSupport`, `EnaSupport`, `SriovNetSupport`, `ImageLocation`, `paravirtual` virtualization rejected with `InvalidParameterValue`. `VolumeSize` smaller than snapshot rejected. | 1. Register with valid snapshot<br>2. Missing name/snapshot (error)<br>3. Duplicate AMI name (`InvalidAMIName.Duplicate`)<br>4. Snapshot not found (`InvalidSnapshot.NotFound`)<br>5. Cross-account snapshot (`UnauthorizedOperation`)<br>6. Tags from `TagSpecifications` persisted<br>7. Verify registered image in describe-images | **DONE** |
| `register-image` | `--name`, `--description`, `--architecture` (x86_64/arm64/i386), `--root-device-name`, `--virtualization-type` (hvm only), `--boot-mode` (bios/uefi/uefi-preferred), `--block-device-mappings` (root with `Ebs.SnapshotId`+optional `VolumeSize`), `--tag-specifications` | `--billing-products`, `--uefi-data` | Backing snapshot must exist in Predastore (`{snapshotId}/metadata.json`); caller must own snapshot or it must be system-owned | Gateway validates name length (3–128), `snap-` prefix, architecture/virtualization/boot-mode values → NATS `ec2.RegisterImage` → daemon checks AMI name uniqueness, reads snapshot metadata, verifies snapshot ownership, builds `viperblock.AMIMetadata` (defaults: `Architecture=x86_64`, `Virtualization=hvm`, `PlatformDetails=Linux/UNIX`, `RootDeviceType=ebs`), writes `{amiId}/config.json`. Pointer-only — never touches block data. `BootMode` outside `bios|uefi|uefi-preferred`, `KernelId`, `RamdiskId`, `TpmSupport`, `ImdsSupport`, `EnaSupport`, `SriovNetSupport`, `ImageLocation`, `paravirtual` virtualization rejected with `InvalidParameterValue`. `uefi-preferred` is treated as `uefi` at launch. `VolumeSize` smaller than snapshot rejected. | 1. Register with valid snapshot<br>2. Missing name/snapshot (error)<br>3. Duplicate AMI name (`InvalidAMIName.Duplicate`)<br>4. Snapshot not found (`InvalidSnapshot.NotFound`)<br>5. Cross-account snapshot (`UnauthorizedOperation`)<br>6. Tags from `TagSpecifications` persisted<br>7. Verify registered image in describe-images<br>8. `--boot-mode=uefi` accepted, returned by `describe-images`<br>9. `--boot-mode=invalid` rejected (`InvalidParameterValue`) | **DONE** |
| `deregister-image` | `--image-id` | `--dry-run` | AMI must exist; caller must own it (system AMIs immutable via this API) | Gateway validates `ami-` prefix → NATS `ec2.DeregisterImage` → daemon hard-deletes `{amiId}/config.json` from Predastore. Backing snapshot is left intact (matches AWS — operators run `delete-snapshot` separately to reclaim block storage). Cross-account/system-AMI mutations rejected with `UnauthorizedOperation`. Re-deregister returns `InvalidAMIID.NotFound` (no tombstone). | 1. Deregister existing AMI<br>2. Deregister non-existent AMI (`InvalidAMIID.NotFound`)<br>3. Re-deregister already-deleted AMI (`InvalidAMIID.NotFound`)<br>4. Cross-account AMI (`UnauthorizedOperation`)<br>5. System AMI (`UnauthorizedOperation`)<br>6. Verify deregistered AMI not in describe-images<br>7. Backing snapshot untouched | **DONE** |
| `copy-image` | `--source-image-id`, `--source-region` (must equal gateway region), `--name`, `--description`, `--client-token` (accepted, not honoured), `--copy-image-tags`, `--tag-specifications` (image only) | `--encrypted`, `--kms-key-id`, `--destination-outpost-arn`, `--dry-run` | Source AMI must exist and be owned by caller OR be a system AMI; backing snapshot must still exist | Gateway validates `ami-` prefix, name length (3–128), same-region — cross-region / `Encrypted` / `KmsKeyId` / `DestinationOutpostArn` rejected with `InvalidParameterValue`. NATS `ec2.CopyImage` → daemon checks name uniqueness, reads source `ami-xxx/config.json`, visibility-filters cross-account sources as `InvalidAMIID.NotFound`, reads source `{snap-xxx}/metadata.json` (missing or empty SnapshotID → `InvalidAMIID.NotFound`), writes new `snap-yyy/metadata.json` that inherits source `VolumeID` (no block copy), writes new `ami-yyy/config.json` owned by caller. `Description` inherits from source when unset. Tag merge: `CopyImageTags=true` seeds tags from source, explicit image-resource `TagSpecifications` override colliding keys and append new ones; non-image tag specs ignored. | 1. Same-region copy produces new `ami-`/`snap-` pair with distinct IDs<br>2. New snap shares source `VolumeID` (metadata-only)<br>3. New AMI owned by caller, source untouched<br>4. System AMI copied into caller's account<br>5. Cross-account source (`InvalidAMIID.NotFound`)<br>6. Missing source AMI (`InvalidAMIID.NotFound`)<br>7. Orphaned source (missing/empty `SnapshotID`) → `InvalidAMIID.NotFound`<br>8. Duplicate name (`InvalidAMIName.Duplicate`)<br>9. Cross-region / `Encrypted` / `KmsKeyId` rejected (`InvalidParameterValue`)<br>10. `CopyImageTags` true/false tag inheritance semantics | **DONE** |
| `import-image` | — | `--disk-containers` (Format, Url/S3Bucket+S3Key), `--description`, `--architecture`, `--platform` | S3 bucket with disk image | Download disk image from S3 → convert format (VMDK/VHD/RAW→QCOW2) → create viperblock volume → register as AMI | 1. Import QCOW2 image<br>2. Import RAW image<br>3. Invalid format (error)<br>4. Verify imported image launchable | **NOT STARTED** |
@@ -57,6 +57,7 @@ sudo apt update
sudo apt install --download-only -y \
nbdkit nbdkit-plugin-dev pkg-config \
qemu-system-x86 qemu-utils qemu-kvm \
ovmf qemu-efi-aarch64 \
libvirt-daemon-system libvirt-clients libvirt-dev \
ovn-central ovn-host openvswitch-switch \
dhcpcd-base make gcc jq curl iproute2 netcat-openbsd \
@@ -141,7 +142,7 @@ Register the pre-staged image with Spinifex:
```bash
sudo spx admin images import --file /mnt/usb/images/debian-13-amd64.qcow2 \
--distro debian --version 13 --arch x86_64
--distro debian --version 13 --arch x86_64 --boot-mode uefi
```
## Step 9. Verify
@@ -183,4 +184,4 @@ sudo INSTALL_SPINIFEX_TARBALL=/mnt/usb/tarball/spinifex-...tar.gz \
### Image Import Fails
`spx admin images import --file` requires the distro/version/arch flags so the image registers in the catalogue. If the import succeeds but `aws ec2 describe-images` returns empty, check `journalctl -u spinifex-daemon -f` for predastore upload errors.
`spx admin images import --file` requires the distro/version/arch/boot-mode flags so the image registers in the catalogue. If the import succeeds but `aws ec2 describe-images` returns empty, check `journalctl -u spinifex-daemon -f` for predastore upload errors.
@@ -58,10 +58,10 @@ spx admin images list
```
NAME | DISTRO | VERSION | ARCH | BOOT
debian-13-arm64 | debian | 13 | arm64 | bios
debian-13-x86_64 | debian | 13 | x86_64 | bios
ubuntu-26.04-arm64 | ubuntu | 26.04 | arm64 | bios
ubuntu-26.04-x86_64 | ubuntu | 26.04 | x86_64 | bios
debian-13-arm64 | debian | 13 | arm64 | uefi
debian-13-x86_64 | debian | 13 | x86_64 | uefi
ubuntu-26.04-arm64 | ubuntu | 26.04 | arm64 | uefi
ubuntu-26.04-x86_64 | ubuntu | 26.04 | x86_64 | uefi
```
Import an image:
@@ -73,7 +73,7 @@ spx admin images import --name ubuntu-26.04-x86_64
Or import a local image file:
```bash
spx admin images import --file ~/images/ubuntu-26.04.img --distro ubuntu --version 26.04 --arch x86_64
spx admin images import --file ~/images/ubuntu-26.04.img --distro ubuntu --version 26.04 --arch x86_64 --boot-mode uefi
```
Verify the import and note the AMI ID:
@@ -61,6 +61,7 @@
--distro {{ spinifex_smoketest_distro }}
--version {{ spinifex_smoketest_version }}
--arch {{ smoketest_arch }}
--boot-mode uefi
register: smoketest_import_local
until: >-
smoketest_import_local.rc == 0 or
+6 -4
View File
@@ -75,6 +75,7 @@ case "$DISTRO" in
OUTPUT_RAW="${BUILD_DIR}/${IMAGE_NAME}-alpine.raw"
DISTRO_VERSION="${ALPINE_VERSION}"
ROOT_PART="${NBD_DEV}"
BOOT_MODE="bios"
;;
ubuntu)
if [[ -z "${UBUNTU_VERSION:-}" ]]; then
@@ -87,6 +88,7 @@ case "$DISTRO" in
OUTPUT_RAW="${BUILD_DIR}/${IMAGE_NAME}-ubuntu.raw"
DISTRO_VERSION="${UBUNTU_VERSION}"
ROOT_PART="${NBD_DEV}p1"
BOOT_MODE="uefi"
;;
*)
echo "ERROR: Unknown DISTRO: $DISTRO (supported: alpine, ubuntu)"
@@ -189,7 +191,7 @@ if [[ -f "$OUTPUT_RAW" ]] && [[ $(( $(date +%s) - $(stat -c %Y "$OUTPUT_RAW") ))
if [[ "$DO_IMPORT" == true ]]; then
echo "Importing as AMI..."
rm -f "$OUTPUT_IMAGE"
IMPORT_ARGS=(--file "$OUTPUT_RAW" --distro "${DISTRO}" --version "${DISTRO_VERSION}" --arch x86_64)
IMPORT_ARGS=(--file "$OUTPUT_RAW" --distro "${DISTRO}" --version "${DISTRO_VERSION}" --arch x86_64 --boot-mode "${BOOT_MODE}")
if [[ -n "${SYSTEM_TAG:-}" ]]; then
IMPORT_ARGS+=(--tag "$SYSTEM_TAG")
fi
@@ -423,7 +425,7 @@ echo ""
if [[ "$DO_IMPORT" == true ]]; then
echo "Importing as AMI..."
rm -f "$OUTPUT_IMAGE"
IMPORT_ARGS=(--file "$OUTPUT_RAW" --distro "${DISTRO}" --version "${DISTRO_VERSION}" --arch x86_64)
IMPORT_ARGS=(--file "$OUTPUT_RAW" --distro "${DISTRO}" --version "${DISTRO_VERSION}" --arch x86_64 --boot-mode "${BOOT_MODE}")
if [[ -n "${SYSTEM_TAG:-}" ]]; then
IMPORT_ARGS+=(--tag "$SYSTEM_TAG")
fi
@@ -433,9 +435,9 @@ else
echo " spx admin images import \\"
echo " --file $OUTPUT_RAW \\"
if [[ -n "${SYSTEM_TAG:-}" ]]; then
echo " --distro ${DISTRO} --version ${DISTRO_VERSION} --arch x86_64 \\"
echo " --distro ${DISTRO} --version ${DISTRO_VERSION} --arch x86_64 --boot-mode ${BOOT_MODE} \\"
echo " --tag ${SYSTEM_TAG}"
else
echo " --distro ${DISTRO} --version ${DISTRO_VERSION} --arch x86_64"
echo " --distro ${DISTRO} --version ${DISTRO_VERSION} --arch x86_64 --boot-mode ${BOOT_MODE}"
fi
fi
+1 -1
View File
@@ -214,7 +214,7 @@ install_apt_deps() {
DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq \
nbdkit \
$QEMU_PACKAGES qemu-utils qemu-kvm ovmf less \
$QEMU_PACKAGES qemu-utils qemu-kvm ovmf qemu-efi-aarch64 less \
libvirt-daemon-system libvirt-clients \
pciutils \
jq curl iproute2 netcat-openbsd wget unzip xz-utils file \
+1 -1
View File
@@ -126,7 +126,7 @@ else
if [ -f "$LOCAL_IMAGE" ]; then
echo " Using local image: $LOCAL_IMAGE"
sudo /usr/local/bin/spx admin images import \
--file "$LOCAL_IMAGE" --distro ubuntu --version 26.04 --arch "$IMG_ARCH"
--file "$LOCAL_IMAGE" --distro ubuntu --version 26.04 --arch "$IMG_ARCH" --boot-mode uefi
else
echo " Downloading image: $IMAGE_NAME"
sudo /usr/local/bin/spx admin images import --name "$IMAGE_NAME"
+11 -1
View File
@@ -17,6 +17,14 @@ var validRegisterImageArchitectures = map[string]bool{
"i386": true,
}
// uefi-preferred is accepted and treated as uefi at launch (single host, single
// firmware path — the BIOS-fallback ambiguity AWS resolves doesn't apply here).
var validRegisterImageBootModes = map[string]bool{
"bios": true,
"uefi": true,
"uefi-preferred": true,
}
// ValidateRegisterImageInput rejects inputs that ask for behaviour spinifex
// doesn't have (PV, S3 bundles, kernel/ramdisk, IMDS/TPM/ENA hints) rather
// than silently discarding them. Registration is pointer-only: caller supplies
@@ -48,7 +56,9 @@ func ValidateRegisterImageInput(input *ec2.RegisterImageInput) error {
}
if input.BootMode != nil && *input.BootMode != "" {
return errors.New(awserrors.ErrorInvalidParameterValue)
if !validRegisterImageBootModes[*input.BootMode] {
return errors.New(awserrors.ErrorInvalidParameterValue)
}
}
if input.KernelId != nil && *input.KernelId != "" {
return errors.New(awserrors.ErrorInvalidParameterValue)
@@ -124,8 +124,23 @@ func TestValidateRegisterImageInput(t *testing.T) {
errMsg: awserrors.ErrorInvalidParameterValue,
},
{
name: "BootModeRejected",
name: "BootModeAcceptedBios",
mutate: func(i *ec2.RegisterImageInput) { i.BootMode = aws.String("bios") },
wantErr: false,
},
{
name: "BootModeAcceptedUEFI",
mutate: func(i *ec2.RegisterImageInput) { i.BootMode = aws.String("uefi") },
wantErr: false,
},
{
name: "BootModeAcceptedUEFIPreferred",
mutate: func(i *ec2.RegisterImageInput) { i.BootMode = aws.String("uefi-preferred") },
wantErr: false,
},
{
name: "BootModeRejectedInvalidValue",
mutate: func(i *ec2.RegisterImageInput) { i.BootMode = aws.String("legacy-bios") },
wantErr: true,
errMsg: awserrors.ErrorInvalidParameterValue,
},
+25 -30
View File
@@ -285,7 +285,7 @@ var AvailableImages = map[string]Images{
URL: "https://cloud.debian.org/images/cloud/trixie/20260518-2482/debian-13-genericcloud-amd64-20260518-2482.tar.xz",
Checksum: "https://cloud.debian.org/images/cloud/trixie/20260518-2482/SHA512SUMS",
ChecksumType: "sha512",
BootMode: "bios",
BootMode: "uefi",
},
"debian-13-arm64": {
@@ -299,7 +299,7 @@ var AvailableImages = map[string]Images{
URL: "https://cloud.debian.org/images/cloud/trixie/20260518-2482/debian-13-genericcloud-arm64-20260518-2482.tar.xz",
Checksum: "https://cloud.debian.org/images/cloud/trixie/20260518-2482/SHA512SUMS",
ChecksumType: "sha512",
BootMode: "bios",
BootMode: "uefi",
},
"ubuntu-26.04-x86_64": {
@@ -313,7 +313,7 @@ var AvailableImages = map[string]Images{
URL: "https://cloud-images.ubuntu.com/resolute/20260421/resolute-server-cloudimg-amd64.img",
Checksum: "https://cloud-images.ubuntu.com/resolute/20260421/SHA256SUMS",
ChecksumType: "sha256",
BootMode: "bios",
BootMode: "uefi",
},
"ubuntu-26.04-arm64": {
@@ -327,41 +327,36 @@ var AvailableImages = map[string]Images{
URL: "https://cloud-images.ubuntu.com/resolute/20260421/resolute-server-cloudimg-arm64.img",
Checksum: "https://cloud-images.ubuntu.com/resolute/20260421/SHA256SUMS",
ChecksumType: "sha256",
BootMode: "bios",
BootMode: "uefi",
},
"alpine-3.22.2-x86_64": {
Name: "alpine-3.22.2-x86_64",
Description: "Alpine Linux 3.22.2 x86_64 cloud image",
"alpine-3.22.4-x86_64": {
Name: "alpine-3.22.4-x86_64",
Description: "Alpine Linux 3.22.4 x86_64 cloud image",
Distro: "alpine",
Version: "3.22.2",
Version: "3.22.4",
Arch: "x86_64",
Platform: "Linux/UNIX",
CreatedAt: time.Date(2025, 10, 6, 0, 0, 0, 0, time.UTC),
URL: "https://dl-cdn.alpinelinux.org/alpine/v3.22/releases/cloud/generic_alpine-3.22.2-x86_64-bios-cloudinit-r0.qcow2",
Checksum: "https://dl-cdn.alpinelinux.org/alpine/v3.22/releases/cloud/generic_alpine-3.22.2-x86_64-bios-cloudinit-r0.qcow2.sha512",
CreatedAt: time.Date(2026, 4, 17, 0, 0, 0, 0, time.UTC),
URL: "https://dl-cdn.alpinelinux.org/alpine/v3.22/releases/cloud/generic_alpine-3.22.4-x86_64-uefi-cloudinit-r0.qcow2",
Checksum: "https://dl-cdn.alpinelinux.org/alpine/v3.22/releases/cloud/generic_alpine-3.22.4-x86_64-uefi-cloudinit-r0.qcow2.sha512",
ChecksumType: "sha512",
BootMode: "bios",
BootMode: "uefi",
},
/*
"alpine-3.22.2-arm64":
// Alpine Linux (cloud init) arm64 (Requires UEFI boot, TODO)
{
Name: "alpine-3.22.2-arm64",
Description: "Alpine Linux 3.22.2 arm64 cloud image",
Distro: "alpine",
Version: "3.22.2",
Arch: "arm64",
Platform: "Linux/UNIX",
CreatedAt: time.Date(2025, 10, 6, 0, 0, 0, 0, time.UTC),
URL: "https://dl-cdn.alpinelinux.org/alpine/v3.22/releases/cloud/gcp_alpine-3.22.2-aarch64-uefi-cloudinit-metal-r0.raw.tar.gz",
Checksum: "https://dl-cdn.alpinelinux.org/alpine/v3.22/releases/cloud/gcp_alpine-3.22.2-aarch64-uefi-cloudinit-metal-r0.raw.tar.gz.sha512",
ChecksumType: "sha512",
BootMode: "uefi",
},
*/
"alpine-3.22.4-arm64": {
Name: "alpine-3.22.4-arm64",
Description: "Alpine Linux 3.22.4 arm64 cloud image",
Distro: "alpine",
Version: "3.22.4",
Arch: "arm64",
Platform: "Linux/UNIX",
CreatedAt: time.Date(2026, 4, 17, 0, 0, 0, 0, time.UTC),
URL: "https://dl-cdn.alpinelinux.org/alpine/v3.22/releases/cloud/generic_alpine-3.22.4-aarch64-uefi-cloudinit-r0.qcow2",
Checksum: "https://dl-cdn.alpinelinux.org/alpine/v3.22/releases/cloud/generic_alpine-3.22.4-aarch64-uefi-cloudinit-r0.qcow2.sha512",
ChecksumType: "sha512",
BootMode: "uefi",
},
}
// AMI / image extraction utils
+1
View File
@@ -295,6 +295,7 @@ IMPORT_LOG=$(./bin/spx admin images import \
--arch "$ARCH" \
--distro ubuntu \
--version "$UBUNTU_VER" \
--boot-mode uefi \
--config "$HOME/node1/config/spinifex.toml" \
--spinifex-dir "$HOME/node1/" \
--force 2>/dev/null)