Skip to content

Commit 28793a3

Browse files
committed
Add Ubuntu 26.04 dual boot image
1 parent 1514c95 commit 28793a3

5 files changed

Lines changed: 312 additions & 0 deletions

File tree

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
```
2+
$ curl -LO \
3+
https://releases.ubuntu.com/resolute/ubuntu-26.04-desktop-amd64.iso
4+
# curl -LO \
5+
https://crake-nexus.org.boxcutter.net/repository/ubuntu-releases-proxy/resolute/ubuntu-26.04-desktop-amd64.iso
6+
# shasum -a 256 ubuntu-26.04-desktop-amd64.iso
7+
487f87faaf547ea30e0aba4d5b53346292571256b25333a978db1692bcee9dd2 ubuntu-26.04-desktop-amd64.iso
8+
9+
docker run -it --rm \
10+
--mount type=bind,source="$(pwd)",target=/data \
11+
docker.io/boxcutter/ubuntu-autoinstall \
12+
--source ubuntu-26.04-desktop-amd64.iso \
13+
--autoinstall autoinstall.yaml \
14+
--destination ubuntu-26.04-desktop-amd64-autoinstall.iso \
15+
--grub grub.cfg \
16+
--loopback loopback.cfg \
17+
--config-root
18+
```
19+
20+
```
21+
docker container run --rm --interactive --tty \
22+
--mount type=bind,source="$(pwd)/test",target=/share \
23+
docker.io/boxcutter/cinc-auditor exec example \
24+
--key-files /Users/taylor/.ssh/id_ed25519 \
25+
--target ssh://autobot@10.63.33.125
26+
27+
docker container run --rm --interactive --tty \
28+
--mount type=bind,source="$(pwd)",target=/share \
29+
docker.io/boxcutter/cinc-auditor exec /share/test \
30+
--no-create-lockfile \
31+
--no-distinct-exit \
32+
--password superseekret \
33+
--target ssh://autobot@10.63.33.171
34+
```
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
#cloud-config
2+
autoinstall:
3+
version: 1
4+
source:
5+
search_drivers: true
6+
id: ubuntu-desktop-minimal
7+
# https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/2097769
8+
network:
9+
version: 2
10+
ethernets:
11+
# Intel I219-LM interface that supports vPro/AMT pass-through
12+
eno1:
13+
dhcp4: false
14+
dhcp6: false
15+
optional: true
16+
# Intel I210-AT standalone gigabit ethernet
17+
enp113s0:
18+
dhcp4: true
19+
dhcp6: false
20+
optional: true
21+
wlp4s0:
22+
dhcp4: true
23+
dhcp6: false
24+
optional: true
25+
bridges:
26+
br0:
27+
interfaces:
28+
- eno1
29+
dhcp4: true
30+
dhcp6: false
31+
accept-ra: false
32+
link-local: []
33+
parameters:
34+
stp: false
35+
forward-delay: 0
36+
storage:
37+
config:
38+
- transport: pcie
39+
preserve: true
40+
id: nvme-controller-nvme1
41+
type: nvme_controller
42+
- ptable: gpt
43+
serial: KINGSTON_SNVS2000G_50026B778481A6FF_1
44+
wwn: eui.00000000000000000026b778481a6ff5
45+
nvme_controller: nvme-controller-nvme1
46+
path: /dev/nvme1n1
47+
preserve: false
48+
name: ''
49+
grub_device: false
50+
id: disk-nvme1n1
51+
type: disk
52+
- device: disk-nvme1n1
53+
size: 1127219200
54+
wipe: superblock
55+
flag: boot
56+
number: 1
57+
preserve: false
58+
grub_device: true
59+
offset: 1048576
60+
path: /dev/nvme1n1p1
61+
id: partition-0
62+
type: partition
63+
- fstype: fat32
64+
volume: partition-0
65+
preserve: false
66+
id: format-0
67+
type: format
68+
- device: disk-nvme1n1
69+
size: 1999269527552
70+
wipe: superblock
71+
number: 2
72+
preserve: false
73+
offset: 1128267776
74+
path: /dev/nvme1n1p2
75+
id: partition-1
76+
type: partition
77+
- fstype: ext4
78+
volume: partition-1
79+
preserve: false
80+
id: format-1
81+
type: format
82+
- path: /
83+
device: format-1
84+
id: mount-1
85+
type: mount
86+
- path: /boot/efi
87+
device: format-0
88+
id: mount-0
89+
type: mount
90+
timezone: UTC
91+
locale: en_US.UTF-8
92+
keyboard:
93+
layout: us
94+
kernel:
95+
flavor: hwe
96+
updates: all
97+
ssh:
98+
install-server: true
99+
allow-pw: true
100+
apt:
101+
preserve_sources_list: false
102+
mirror-selection:
103+
primary:
104+
# http://archive.ubuntu.com/ubntu
105+
- uri: "http://crake-nexus.org.boxcutter.net/repository/ubuntu-archive-apt-proxy/ubuntu"
106+
arches: [i386, amd64]
107+
# http://ports.ubuntu.com/ubuntu-ports
108+
- uri: "http://crake-nexus.org.boxcutter.net/repository/ubuntu-ports-proxy/ubuntu-ports"
109+
arches: [s390x, arm64, armhf, powerpc, ppc64el, riscv64]
110+
late-commands:
111+
# Because we're using preserve_hostname to allow manual setting of the
112+
# hostname, set an initial hostname manually - the identity block requires
113+
# a username and it doesn't support flexible enough configuration
114+
# NOTE: 'curtin in-target' doesn't invoke a shell, so you need to run
115+
# commands within a shell that need redirection.
116+
- curtin in-target -- sh -c 'echo pxe > /etc/hostname'
117+
# Seed the already ran marker for gnome-initial-setup so new users inherit
118+
- curtin in-target -- mkdir -p /etc/skel/.config
119+
- curtin in-target -- touch /etc/skel/.config/gnome-initial-setup-done
120+
- curtin in-target -- mkdir -p /etc/skel/.config/gnome-initial-setup
121+
- curtin in-target -- touch /etc/skel/.config/gnome-initial-setup/upgrade-26.04-done
122+
# Run updates at our own cadence
123+
- curtin in-target -- systemctl disable apt-daily.timer
124+
- curtin in-target -- systemctl disable apt-daily-upgrade.timer
125+
- curtin in-target -- systemctl mask apt-daily.service
126+
- curtin in-target -- systemctl mask apt-daily-upgrade.service
127+
- curtin in-target -- sh -c 'sed -i "s/^APT::Periodic::Update-Package-Lists.*/APT::Periodic::Update-Package-Lists \"0\";/g" /etc/apt/apt.conf.d/20auto-upgrades'
128+
- curtin in-target -- sh -c 'sed -i "s/^APT::Periodic::Unattended-Upgrade.*/APT::Periodic::Unattended-Upgrade \"0\";/g" /etc/apt/apt.conf.d/20auto-upgrades'
129+
- curtin in-target -- sh -c 'sed -i "s/^APT::Periodic::.Download-Upgradeable-Packages */APT::Periodic::Download-Upgradeable-Packages \"0\";/g" /etc/apt/apt.conf.d/20auto-upgrades'
130+
- curtin in-target -- sh -c 'sed -i "s/^APT::Periodic::.AutocleanInterval */APT::Periodic::AutocleanInterval \"0\";/g" /etc/apt/apt.conf.d/20auto-upgrades'
131+
- curtin in-target -- sh -c 'snap refresh --hold || true'
132+
- curtin in-target -- sh -c 'echo "Hidden=true" >> /etc/xdg/autostart/update-notifier.desktop'
133+
- curtin in-target -- systemctl disable update-notifier-download.timer || true
134+
- curtin in-target -- systemctl disable update-notifier-motd.timer || true
135+
user-data: # cloud-init starts here
136+
preserve_hostname: true
137+
users:
138+
# Temporary user used for initial bootstrapping with CM tool
139+
- name: autobot
140+
uid: 63112
141+
primary_group: users
142+
groups: users
143+
shell: /bin/bash
144+
# Testing with a plaintext password
145+
plain_text_passwd: superseekret
146+
# Replace with your generated salted SHA-512 hash using 'openssl passwd -6'
147+
# passwd: "$6$W32sh2s3EDp01J$ajF/6iHYX1Ef2pF5mPi..zBFiU4Qzvnif.hT2MB.dZ9mSx6txdPiz..."
148+
sudo: ALL=(ALL) NOPASSWD:ALL
149+
lock_passwd: false
150+
ssh_authorized_keys:
151+
# taylor
152+
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEWerEkujoB7ipGnWJwnPGFu3DuUQJtc1zB6YqjGRziE sheila
153+
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINRK4hkcpUiaSkiLEytgwMYcKylBioXPLx1TnwJFrLPl mahowald
154+
chpasswd: {expire: false}
155+
ssh_pwauth: true
156+
# DBus doesn't appear to be active in late-commands, so wait to configure
157+
# power saving defaults until cloud-init time, plus cloud-init has
158+
# a nice module to write out files
159+
write_files:
160+
# Configure system-wide defaults to disable screen blanking
161+
- path: /etc/dconf/db/local.d/00-screensaver
162+
content: |
163+
[org/gnome/desktop/session]
164+
idle-delay=uint32 0
165+
166+
[org/gnome/desktop/screensaver]
167+
lock-enabled=false
168+
idle-activation-enabled=false
169+
170+
[org/gnome/settings-daemon/plugins/power]
171+
sleep-inactive-ac-type="nothing"
172+
sleep-inactive-battery-type="nothing"
173+
idle-dim=false
174+
# Configure system to refer to user settings in ~/.config/dconf/user
175+
# database first, then look for system-wide defaults in
176+
# /etc/dconf/db/local
177+
- path: /etc/dconf/profile/user
178+
content: |
179+
user-db:user
180+
system-db:local
181+
runcmd:
182+
# Update the GNOME system database with the changes to /etc/dconf
183+
# above
184+
- dconf update
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
set timeout=30
2+
3+
loadfont unicode
4+
5+
set menu_color_normal=white/black
6+
set menu_color_highlight=black/light-gray
7+
8+
menuentry "Ubuntu Desktop Autoinstalll" {
9+
set gfxpayload=keep
10+
linux /casper/vmlinuz autoinstall --- quiet splash
11+
initrd /casper/initrd
12+
}
13+
menuentry "Ubuntu (safe graphics)" {
14+
set gfxpayload=keep
15+
linux /casper/vmlinuz nomodeset --- quiet splash
16+
initrd /casper/initrd
17+
}
18+
grub_platform
19+
if [ "$grub_platform" = "efi" ]; then
20+
menuentry 'Boot from next volume' {
21+
exit 1
22+
}
23+
menuentry 'UEFI Firmware Settings' {
24+
fwsetup
25+
}
26+
else
27+
menuentry 'Test memory' {
28+
linux16 /boot/memtest86+x64.bin
29+
}
30+
fi
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
menuentry "Try or Install Ubuntu" {
3+
set gfxpayload=keep
4+
linux /casper/vmlinuz iso-scan/filename=${iso_path} --- quiet splash
5+
initrd /casper/initrd
6+
}
7+
menuentry "Ubuntu (safe graphics)" {
8+
set gfxpayload=keep
9+
linux /casper/vmlinuz nomodeset iso-scan/filename=${iso_path} --- quiet splash
10+
initrd /casper/initrd
11+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
describe package('openssh-server') do
2+
it { should be_installed }
3+
end
4+
5+
target_user = input('target_user', value: 'autobot')
6+
7+
control 'gsettings-available' do
8+
impact 1.0
9+
title 'gsettings binary and required schemas exist'
10+
desc 'Ensure gsettings is present and the GNOME schemas we query are available'
11+
12+
describe command('which gsettings') do
13+
its('exit_status') { should eq 0 }
14+
end
15+
16+
# Check schemas exist (skip tests if not)
17+
%w[
18+
org.gnome.desktop.session
19+
org.gnome.desktop.screensaver
20+
org.gnome.settings-daemon.plugins.power
21+
].each do |schema|
22+
describe command("sudo -iu #{target_user} gsettings list-schemas | grep -Fx '#{schema}'") do
23+
its('exit_status') { should eq 0 }
24+
end
25+
end
26+
end
27+
28+
control 'gnome-screensaver-and-power-settings' do
29+
impact 1.0
30+
title 'Verify GNOME idle/screensaver/power settings via gsettings'
31+
only_if('gsettings not found') { command('which gsettings').exit_status == 0 }
32+
33+
checks = [
34+
# schema, key, expected stdout (exactly as gsettings prints it)
35+
['org.gnome.desktop.session', 'idle-delay', 'uint32 0'],
36+
['org.gnome.desktop.screensaver', 'lock-enabled', 'false'],
37+
['org.gnome.desktop.screensaver', 'idle-activation-enabled', 'false'],
38+
['org.gnome.settings-daemon.plugins.power', 'sleep-inactive-ac-type', "'nothing'"],
39+
['org.gnome.settings-daemon.plugins.power', 'sleep-inactive-battery-type',"'nothing'"],
40+
['org.gnome.settings-daemon.plugins.power', 'idle-dim', 'false'],
41+
]
42+
43+
checks.each do |schema, key, expected|
44+
desc_str = "#{schema} #{key} should be #{expected}"
45+
describe(desc_str) do
46+
cmd = command("sudo -iu #{target_user} gsettings get #{schema} #{key}")
47+
it "has expected value (#{expected})" do
48+
expect(cmd.exit_status).to eq(0)
49+
expect(cmd.stdout.strip).to eq(expected)
50+
end
51+
end
52+
end
53+
end

0 commit comments

Comments
 (0)