Add Ubuntu 26.04 virtual machine
Add run-ubuntu2604.py with its QEMU config files and NoCloud seed. The launcher follows the Debian 13 one, with UBUNTU_VM_ settings and SSH forwarded to host port 2225. The seed injects the current user's SSH public key, uses the USTC mirror (ubuntu-ports on arm64) and installs the GNOME desktop on first boot. Update vm-images for the ubuntu2604 image target. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kwxp2XWvKnuEBifnCbhyX5
This commit is contained in:
1 parent
649399aaa1
commit
1691062554
13 files changed
+564
-4
No files matched your search
+2
-1
@@ -7,7 +7,8 @@ Each operating system has an independent NoCloud configuration and generated
|
||||
seediso/
|
||||
├── debian13/
|
||||
├── almalinux10/
|
||||
└── fedora44/
|
||||
├── fedora44/
|
||||
└── ubuntu2604/
|
||||
```
|
||||
|
||||
Keeping per-OS metadata separate allows each VM to use a distinct hostname and
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
seed.iso
|
||||
*.iso
|
||||
@@ -0,0 +1,21 @@
|
||||
# Ubuntu 26.04 seed.iso
|
||||
|
||||
This directory contains the cloud-init NoCloud configuration used by
|
||||
`run-ubuntu2604.py`.
|
||||
|
||||
1. Edit `user-data`, `meta-data`, and (if needed) `network-config`.
|
||||
2. Build the image:
|
||||
|
||||
```bash
|
||||
./seediso/ubuntu2604/build-seed.sh
|
||||
```
|
||||
|
||||
To choose another output path:
|
||||
|
||||
```bash
|
||||
./seediso/ubuntu2604/build-seed.sh /path/to/seed.iso
|
||||
```
|
||||
|
||||
The script uses `cloud-localds` when available, then falls back to `xorriso`,
|
||||
`genisoimage`, or `mkisofs`. Attach the resulting ISO as a CD-ROM when booting
|
||||
a cloud-init-enabled virtual machine.
|
||||
Executable
+62
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
output="${1:-${script_dir}/seed.iso}"
|
||||
files=(user-data meta-data)
|
||||
|
||||
# Public key injected into user-data: $SSH_PUBKEY_FILE, else the first
|
||||
# ~/.ssh/id_*.pub, else the first key offered by ssh-agent.
|
||||
pubkey=""
|
||||
if [[ -n "${SSH_PUBKEY_FILE:-}" ]]; then
|
||||
pubkey="$(head -n1 -- "${SSH_PUBKEY_FILE}")"
|
||||
else
|
||||
for f in "${HOME}"/.ssh/id_ed25519.pub "${HOME}"/.ssh/id_*.pub; do
|
||||
if [[ -f "$f" ]]; then pubkey="$(head -n1 -- "$f")"; break; fi
|
||||
done
|
||||
if [[ -z "$pubkey" ]] && command -v ssh-add >/dev/null 2>&1; then
|
||||
pubkey="$(ssh-add -L 2>/dev/null | head -n1 || true)"
|
||||
fi
|
||||
fi
|
||||
if [[ "$pubkey" != ssh-* && "$pubkey" != ecdsa-* && "$pubkey" != sk-* ]]; then
|
||||
printf 'Error: no SSH public key found; set SSH_PUBKEY_FILE.\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
work="$(mktemp -d)"
|
||||
trap 'rm -rf -- "${work}"' EXIT
|
||||
template="$(<"${script_dir}/user-data")"
|
||||
printf '%s\n' "${template//@SSH_PUBKEY@/${pubkey}}" > "${work}/user-data"
|
||||
cp -- "${script_dir}/meta-data" "${work}/meta-data"
|
||||
if [[ -f "${script_dir}/network-config" ]]; then
|
||||
cp -- "${script_dir}/network-config" "${work}/network-config"
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname -- "$output")"
|
||||
|
||||
if [[ -f "${script_dir}/network-config" ]]; then
|
||||
files+=(network-config)
|
||||
fi
|
||||
|
||||
if command -v cloud-localds >/dev/null 2>&1; then
|
||||
args=()
|
||||
if [[ -f "${script_dir}/network-config" ]]; then
|
||||
args+=(--network-config="${work}/network-config")
|
||||
fi
|
||||
cloud-localds "${args[@]}" "${output}" \
|
||||
"${work}/user-data" "${work}/meta-data"
|
||||
elif command -v xorriso >/dev/null 2>&1; then
|
||||
xorriso -as mkisofs -quiet -volid cidata -joliet -rock \
|
||||
-output "${output}" "${files[@]/#/${work}/}"
|
||||
elif command -v genisoimage >/dev/null 2>&1; then
|
||||
genisoimage -quiet -output "${output}" -volid cidata -joliet -rock \
|
||||
"${files[@]/#/${work}/}"
|
||||
elif command -v mkisofs >/dev/null 2>&1; then
|
||||
mkisofs -quiet -output "${output}" -volid cidata -joliet -rock \
|
||||
"${files[@]/#/${work}/}"
|
||||
else
|
||||
printf 'Error: install cloud-image-utils, xorriso, genisoimage, or mkisofs.\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf 'Created %s\n' "${output}"
|
||||
@@ -0,0 +1,2 @@
|
||||
instance-id: ubuntu2604-host-001
|
||||
local-hostname: ubuntu2604-host
|
||||
@@ -0,0 +1,10 @@
|
||||
version: 2
|
||||
ethernets:
|
||||
all-en:
|
||||
match:
|
||||
name: "en*"
|
||||
dhcp4: true
|
||||
all-eth:
|
||||
match:
|
||||
name: "eth*"
|
||||
dhcp4: true
|
||||
@@ -0,0 +1,46 @@
|
||||
#cloud-config
|
||||
preserve_hostname: false
|
||||
manage_etc_hosts: true
|
||||
ssh_pwauth: true
|
||||
|
||||
users:
|
||||
- name: guofang
|
||||
gecos: Guofang
|
||||
groups: [sudo]
|
||||
shell: /bin/bash
|
||||
sudo: "ALL=(ALL) NOPASSWD: ALL"
|
||||
lock_passwd: false
|
||||
ssh_authorized_keys:
|
||||
- @SSH_PUBKEY@
|
||||
hashed_passwd: $6$0NtCERV3eO12t9oJ$nlFE2sSc66nFfuD5X0xMnOla1cuzOnHfeGNRY5X7dCDHg.WzWVmuRe7M17Puj44.eCWLnJAWt4WNjd9vP9X0D0
|
||||
|
||||
chpasswd:
|
||||
expire: false
|
||||
|
||||
# amd64 packages are in the ubuntu archive, arm64 packages in ubuntu-ports.
|
||||
apt:
|
||||
primary:
|
||||
- arches: [amd64, i386]
|
||||
uri: "https://mirrors.ustc.edu.cn/ubuntu"
|
||||
- arches: [default]
|
||||
uri: "https://mirrors.ustc.edu.cn/ubuntu-ports"
|
||||
security:
|
||||
- arches: [amd64, i386]
|
||||
uri: "https://mirrors.ustc.edu.cn/ubuntu"
|
||||
- arches: [default]
|
||||
uri: "https://mirrors.ustc.edu.cn/ubuntu-ports"
|
||||
|
||||
package_update: true
|
||||
|
||||
packages:
|
||||
- ubuntu-desktop-minimal
|
||||
- ibus-table-wubi
|
||||
|
||||
runcmd:
|
||||
- systemctl set-default graphical.target
|
||||
|
||||
power_state:
|
||||
delay: now
|
||||
mode: reboot
|
||||
message: "GNOME installation completed; rebooting into graphical mode."
|
||||
condition: true
|
||||
Reference in new issue
Block a user