-
Notifications
You must be signed in to change notification settings - Fork 3
/
create_rpibuntu.sh
executable file
·438 lines (344 loc) · 12.8 KB
/
create_rpibuntu.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
#! /bin/bash
# Written 2015 by Mario Kicherer (dev@kicherer.org)
#
# This script creates a disk image with an almost minimal Ubuntu Linux that
# boots on a Raspberry Pi 2 system.
#
# To use this script you need a few other tools, e.g., a static qemu binary
# for ARM (from package qemu-user-static on Ubuntu). Please see the
# "check_tool" lines below.
#
# You can configure the image using environment variables. For example,
# to directly write to a SD card known as /dev/sdX, execute:
#
# LODEV=/dev/sdX create_rpibuntu.sh
#
# Or, to create an image with a (16 GB - 200 MB) root partition, a 200 MB boot
# partition and a wifi-ready setup for common wifi hardware, call:
#
# IMG_SIZE_MB=16000 BOOT_SIZE_MB=200 \
# ADDITIONAL_PKGS="ssh linux-firmware connman" create_rpibuntu.sh
[ -f create_rpibuntu.cfg ] && source create_rpibuntu.cfg
### choose the Ubuntu release
RELEASE=${RELEASE-16.04}
RELEASE_NAME=${RELEASE_NAME-xenial}
RPIBUNTU_REVISION=${RPIBUNTU_REVISION-0}
RPIBUNTU_ARCH=${RPIBUNTU_ARCH-armhf}
UBUNTU_MIRROR=${UBUNTU_MIRROR-http://ports.ubuntu.com}
UBUNTU_MIRROR_PATH=${UBUNTU_MIRROR_PATH-ubuntu-ports/}
### default size of the complete image and the boot partition
IMG_SIZE_MB=${IMG_SIZE_MB-800}
BOOT_SIZE_MB=${BOOT_SIZE_MB-100}
### additional packages that will be installed
ADDITIONAL_PKGS=${ADDITIONAL_PKGS-ssh}
### execute this script in the chroot before starting the shell and finishing
### the image
# USER_SCRIPT=/path/to/script
### if set to 0, do not start a shell inside the new installation
START_SHELL=${START_SHELL-1}
# name of the resulting image (default: rpibuntu_15.10.img)
[ ${RPIBUNTU_REVISION} -gt 0 ] && REV=".${RPIBUNTU_REVISION}"
IMG_PATH=${IMG_PATH-rpibuntu_${RELEASE}${REV}.img}
function errcheck() {
LAST=$?
if [ "${LAST}" != "0" ]; then
echo "error, \"$1\" failed with return value ${LAST}. output:"
echo "$2"
caller
exit 1
fi
}
function check_tool {
which $1 >/dev/null; errcheck "tool $1 not found"
}
QEMU_ARM=${QEMU_ARM-qemu-arm}
if [ "${USER}" != "root" ]; then
echo "This script must be run as root user."
exit 1
fi
check_tool debootstrap
check_tool mkfs.vfat
check_tool mkfs.btrfs
check_tool kpartx
check_tool btrfs
check_tool "${QEMU_ARM}"
UBUNTU_KEYRING=${UBUNTU_KEYRING-/usr/share/keyrings/ubuntu-archive-keyring.gpg}
if [ ! -f ${UBUNTU_KEYRING} ]; then
echo "Ubuntu keyring (${UBUNTU_KEYRING}) not found. To verify"
echo "the downloaded files, please get this file or pass its location using"
echo "UBUNTU_KEYRING environment variable."
exit 1
fi
echo "Creating an Ubuntu ${RELEASE} ${RELEASE_NAME} image"
if [ "${LODEV}" == "" ]; then
if [ ! -f ${IMG_PATH} ]; then
echo "Create sparse image file"
dd of=${IMG_PATH} bs=1000k seek=${IMG_SIZE_MB} count=0 status=none || errcheck "sparse dd"
fi
LODEV=$(losetup -a | grep ${IMG_PATH} | cut -d ":" -f1)
if [ "${LODEV}" == "" ]; then
LODEV=$(losetup -f --show ${IMG_PATH}); errcheck "losetup"
echo "Created new loopback device ${LODEV}"
fi
DIRECT_WRITE=0
else
DIRECT_WRITE=1
echo "using device file ${LODEV}"
fi
# TODO check both partition
echo "check if partition table exists"
PARTTABLE=$(sfdisk -d ${LODEV} | grep "Id=83")
if [ "${PARTTABLE}" == "" ]; then
echo "create new partition table"
OUTPUT=$(fdisk ${LODEV} 2>&1 <<EOF
o
n
p
1
+${BOOT_SIZE_MB}M
t
c
n
p
2
w
EOF
)
# TODO fdisk always returns an error code as the new partition table will not
# be used automatically
# errcheck "fdisk" "${OUTPUT}"
fi
LOBASE=$(basename ${LODEV})
[[ ${LOBASE:(-1)} =~ [0-9] ]] && LOBASE="${LOBASE}p"
BOOTDEV=/dev/mapper/${LOBASE}1
ROOTDEV=/dev/mapper/${LOBASE}2
if [ ! -b ${BOOTDEV} ] || [ ! -b ${ROOTDEV} ]; then
echo "creating device files"
kpartx -as ${LODEV} || errcheck "kpartx"
fi
ROOTDIR=$(mktemp -d)/
BOOTDIR=${ROOTDIR}/boot/
echo "trying to mount ${ROOTDEV} to ${ROOTDIR}"
mount "${ROOTDEV}" "${ROOTDIR}" 2>/dev/null
RES=$?
if [ "${RES}" == "32" ]; then
echo "creating new BTRFS on ${ROOTDEV}"
OUTPUT=$(mkfs.btrfs ${ROOTDEV} 2>&1)
errcheck "mkfs.btrfs" "${OUTPUT}"
mount "${ROOTDEV}" "${ROOTDIR}" 2>/dev/null || errcheck "mount ${ROOTDEV}"
fi
SUBVOL=$(btrfs subvolume list "${ROOTDIR}" | grep " @root$")
if [ "${SUBVOL}" == "" ]; then
echo "Creating new root subvolume"
btrfs subvolume create "${ROOTDIR}"/@root || errcheck "subvolume create"
ID=$(btrfs subvolume list "${ROOTDIR}" | grep "@root$" | sed -r 's/ID ([[:digit:]]+).*/\1/g')
btrfs subvolume set-default ${ID} "${ROOTDIR}" || errcheck "subvolume set-default"
umount "${ROOTDIR}"
mount "${ROOTDEV}" "${ROOTDIR}" || errcheck "final mount root"
fi
if [ ! -d ${BOOTDIR} ]; then
mkdir ${BOOTDIR} || errcheck "mkdir ${BOOTDIR} failed"
fi
echo "mounting ${BOOTDEV} to ${BOOTDIR}"
mount "${BOOTDEV}" "${BOOTDIR}" 2>/dev/null
RES=$?
if [ "${RES}" == "32" ]; then
echo "creating new FAT32 on ${BOOTDEV}"
OUTPUT=$(mkfs.vfat -F 32 ${BOOTDEV} 2>&1)
errcheck "mkfs.vfat" "${OUTPUT}"
mount "${BOOTDEV}" "${BOOTDIR}" 2>/dev/null || errcheck "mount ${BOOTDEV}"
fi
if [ ! -f "${ROOTDIR}"/tmp/.debootstrap_foreign ]; then
echo "Starting first debootstrap stage"
debootstrap --arch=${RPIBUNTU_ARCH} --foreign \
--keyring="${UBUNTU_KEYRING}" \
${RELEASE_NAME} "${ROOTDIR}" ${UBUNTU_MIRROR}/${UBUNTU_MIRROR_PATH}
# Do not abort as debootstrap sometimes fails to install all packages for
# some reason. This is fixed by an "apt-get -f install" later.
#errcheck "first stage debootstrap"
touch "${ROOTDIR}"/tmp/.debootstrap_foreign
else
echo "First deboostrap stage already run"
fi
echo "Preparing for chroot"
cp "$(which ${QEMU_ARM})" "${ROOTDIR}"/usr/bin || errcheck
cp "${UBUNTU_KEYRING}" "${ROOTDIR}"/tmp/ || errcheck
if [ ! -f /proc/sys/fs/binfmt_misc/arm ]; then
modprobe binfmt_misc
echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\x00\xff\xfe\xff\xff\xff:/usr/bin/qemu-arm:'"${QEMU_BINFMT_FLAGS}" > /proc/sys/fs/binfmt_misc/register
fi
# disable device file creation in recent debootstrap versions as we bind mount /dev
if [ -f "${ROOTDIR}"/debootstrap/functions ]; then
sed -ri "s/^\s+setup_devices_simple\s*$/echo disabled_mknod/" "${ROOTDIR}"/debootstrap/functions
fi
mount -o bind /dev "${ROOTDIR}"/dev || errcheck
mount -o bind /dev/pts "${ROOTDIR}"/dev/pts || errcheck
mount -t sysfs /sys "${ROOTDIR}"/sys || errcheck
mount -t proc /proc "${ROOTDIR}"/proc || errcheck
cp /proc/mounts "${ROOTDIR}"/etc/mtab || errcheck
# we do not pass --keyring as gpgv is not available in the chroot yet
echo "
#! /bin/sh
echo \"Entered deboostrap chroot\"
if [ -f /debootstrap/debootstrap ]; then
/debootstrap/debootstrap --second-stage
else
echo \"Second deboostrap stage already ran\"
fi
" > "${ROOTDIR}"/tmp/chroot_script
chmod +x "${ROOTDIR}"/tmp/chroot_script
echo "Starting deboostrap chroot"
LC_ALL=C chroot "${ROOTDIR}" /tmp/chroot_script
echo "Preparing system configuration"
echo "Initializing sources.list"
echo "
deb ${UBUNTU_MIRROR}/${UBUNTU_MIRROR_PATH} ${RELEASE_NAME} main restricted universe multiverse
deb ${UBUNTU_MIRROR}/${UBUNTU_MIRROR_PATH} ${RELEASE_NAME}-updates main restricted universe multiverse
deb ${UBUNTU_MIRROR}/${UBUNTU_MIRROR_PATH} ${RELEASE_NAME}-security main restricted universe multiverse
deb http://rpibuntu.kicherer.org/repos/${RELEASE_NAME}/ ${RPIBUNTU_ARCH}/
#deb http://rpibuntu.kicherer.org/repos/${RELEASE_NAME}/ ${RPIBUNTU_ARCH}-testing/
" > "${ROOTDIR}"/etc/apt/sources.list
if [ "$(grep "/boot" "${ROOTDIR}"/etc/fstab)" == "" ]; then
echo "Creating /etc/fstab"
BOOT_UUID=$(blkid ${BOOTDEV} -o value -s UUID)
ROOT_UUID=$(blkid ${ROOTDEV} -o value -s UUID)
echo "
UUID=${BOOT_UUID} /boot vfat defaults 0 2
UUID=${ROOT_UUID} / btrfs defaults,relatime 0 1
"> "${ROOTDIR}"/etc/fstab
fi
echo "rpibuntu" > "${ROOTDIR}"/etc/hostname
sed -i "s/localhost/localhost rpibuntu/" "${ROOTDIR}"/etc/hosts
echo "[Network]
DHCP=both
" > "${ROOTDIR}"/etc/systemd/network/dhcp.network
# make sure these directories are mounted (again)
# mount -o bind /dev/pts "${ROOTDIR}"/dev/pts || errcheck
# mount -t sysfs /sys "${ROOTDIR}"/sys || errcheck
# mount -t proc /proc "${ROOTDIR}"/proc || errcheck
cp /proc/mounts "${ROOTDIR}"/etc/mtab || errcheck
echo "#! /bin/bash
echo \"Entered chroot\"
echo \"adding gpg key to verify rpibuntu repo signature\"
echo \"-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1
mQENBFcbqjMBCADA7XregAr0FoPE9WN34PBH1ALN6HJFPi36yO53KMoS4xzTOYy/
3vJBoLOkGmL5aaEsJn6+67Yktee9I1c0Pxp0mRhO5bs/ggClW2Aoba7tzo3SvKVV
8KKfpAaXofNy0ltooxZEJkDF6Rcjw+T5bSWWAiaGv09s5c6IFJ5Tse5H1OXZ0r78
fxyjOwB17RiZfBR+NuZpJkrNYRXcgbe9N3clPlyTEageIS3KuvUT47v4aKv59ISm
tjFf+NUSZXvY62fZwsDCym+pke0CxE2LPkSlnhIBQ4oX1ByWe5HZsO3h4Dg3cEfN
NWB8kvxvuNmNriqpugP4kp5KbIHA4Mq86mq7ABEBAAG0IU1hcmlvIEtpY2hlcmVy
IDxkZXZAa2ljaGVyZXIub3JnPokBPQQTAQgAJwUCVxuqMwIbAwUJA8JnAAULCQgH
AwUVCgkICwUWAgMBAAIeAQIXgAAKCRDPAXqTidsEdI2nB/9ROc02IZIH1rvuhZ26
k5STlbmPPMvygU7OJTl35075YvAG4/kdcc18OK8UbzdBl9YF9xLHCx2A1zD+tiTQ
88+jZGBWofsYD7DUBowVyMxw2M+Q34EJ62xNPdHxvbneLq+KLPe211i1rBgsvIRB
g0qHDQkgfgavXe+XKLBoOtX3YulR3xG+2Cpev1zUUDNuU4xpyg2+OiJuZmjq3WkI
dIP9swOpNGseuI7uwa6Tb945ffWXfbIgIzDaVPTH2uNI/hny6qOhXJ1fENf2/rSM
DSGk0ukhxS/ROn0cTC7FReck0DrPJW3te2FypAWeo0pRnxl6OqoqSMrt8NGPbsxO
edZZuQENBFcbqjMBCAC6GXQJaETpVfikQAT6fy0hcdWZ8Wb/Sk3N0DxaVVx2Dhtv
4TqzIFH+foy8p92xS8RFYG0HTFPt5DPoFyC0iV8a0aHPaXvUhkySwNXNQhR18Wbx
7zC9sa/k2zB20tlSVRNOiNifZOqX0DaOvHnogJFMPHxlnY/u0HJSgUmqu3VK38b8
N8SFRGD0Ng10+PaXqemWbIEr7jUSTemm5gkEPketdNflTQkjegFKQ6pRCwuc2chY
dORo+FzxxsZ9aaNY0iKQ0AEsOkUbTugpOEWL4YEA9+fzxGStPsbrH4ouvNbJss9q
PUaAY2HnXHomSIeVbT+JWAFJ129HeqPxaOD3V0cbABEBAAGJASUEGAEIAA8FAlcb
qjMCGwwFCQPCZwAACgkQzwF6k4nbBHTX2wf/acDQczdIa1te6g6a6VNH/Pv+CCX1
E6mYOe22w70Fr/5VRlQOlNIxdlCvCPPSRLg6b10AyKQuY4+LRtVSh2lrBTxVOtLe
wNxkihauzcFTq2vteuBEs2rkaDJZurXq1y16q+0kre2mesUoQecC3LJhdSiEMs2w
R5QSrp10/Bd33OTdfZFgrJsAUTZpaH6iSpsuN+NC9U1J6QTM87o6+zWV1pJqVQnF
cq7qpi1bx1Pb22iN/rdXSmN+Xk/ymCk4n6aHisB/g0ML5svJxTyI6sX2tNQh1k1m
+mjI/hIvs4WDxlFGG3OA4mVYx96RIgRpp5F9dJQ0sohb6PORzhgWrowxNQ==
=P0Ky
-----END PGP PUBLIC KEY BLOCK-----\" | apt-key add -
# prevent service startup in chroot
echo 'exit 101' > /usr/sbin/policy-rc.d
chmod +x /usr/sbin/policy-rc.d
echo \"finalize package installation\"
apt-get -y -f install
apt-get update
apt-get -y dist-upgrade
# install additional packages required for RPiBuntu
apt-get install -y u-boot-tools btrfs-tools dosfstools
echo \"setup locales\"
if [ \"\$(locale -a | grep en_US)\" == \"\" ]; then
locale-gen en_US.UTF-8
update-locale LANG=en_US.UTF-8
dpkg-reconfigure locales
fi
echo \"enable DHCP\"
systemctl enable systemd-networkd
systemctl enable systemd-resolved
mkdir -p /run/systemd/resolve/
ln -s ../../resolvconf/resolv.conf /run/systemd/resolve/
rm /etc/resolv.conf; ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
echo \"setup rpibuntu user\"
useradd -m -U -G sudo,video,audio,users -s /bin/bash rpibuntu
echo \"rpibuntu:rpibuntu\" | chpasswd
echo \"installing RPI2 packages\"
apt-get install -y rpi-configs rpi-firmware rpi-tools uboot-bin-rpi
# install kernel later to ensure the update-uboot script is in place
apt-get install -y linux-image-rpi
# setup the firmware config
cp /usr/share/doc/rpi2-configs/config.txt /boot/
echo -e \"\n
# We attach the bluetooth chip to the miniUART port to use the main UART for
# for the serial console.
dtoverlay=pi3-miniuart-bt
enable_uart=1
# Uncomment to signal the firmware that we will use the opensource graphics driver
#dtoverlay=vc4-kms-v3d
#avoid_warnings=2
# RPi2-specific settings
[pi2]
kernel=u-boot-rpi2.bin
# RPi3-specific settings
[pi3]
kernel=u-boot-rpi3_32.bin
# reset filter
[all]
\" >> /boot/config.txt
touch /tmp/.config_chroot
if [ \"${ADDITIONAL_PKGS}\" != \"\" ]; then
# install requested packages by user
apt-get install -y ${ADDITIONAL_PKGS}
fi
" > "${ROOTDIR}"/tmp/chroot_script
chmod +x "${ROOTDIR}"/tmp/chroot_script
if [ ! -f /tmp/.config_chroot ]; then
echo "Starting config chroot"
LC_ALL=C chroot "${ROOTDIR}" /tmp/chroot_script
fi
if [ "${USER_SCRIPT}" != "" ]; then
BASE="$(basename ${USER_SCRIPT})"
cp "${USER_SCRIPT}" "${ROOTDIR}"/tmp/
chmod +x "${ROOTDIR}/tmp/${BASE}"
LC_ALL=en_US.UTF-8 chroot "${ROOTDIR}" /tmp/"${BASE}"
fi
echo ""
echo "Setup finished."
echo ""
if [ "${START_SHELL}" == "1" ]; then
echo "Starting a shell inside the chroot environment. You can make further"
echo "modifications now like installing additional packages."
echo ""
echo "To finish the installation, please enter \"exit\"."
echo ""
LC_ALL=en_US.UTF-8 chroot "${ROOTDIR}" /bin/bash
fi
echo "Cleaning up..."
# LC_ALL=en_US.UTF-8 chroot "${ROOTDIR}" rm /tmp/*
# remove service startup prevention
rm "${ROOTDIR}"/usr/sbin/policy-rc.d
sync && sleep 1
umount -R ${ROOTDIR}
rmdir ${ROOTDIR}
kpartx -d ${LODEV}
if [ "${DIRECT_WRITE}" == "0" ]; then
losetup -d ${LODEV}
fi
echo "Installation finished."
echo
echo "To compress image for publication:"
echo "zip ${IMG_PATH}.zip ${IMG_PATH}"
echo
echo "To decompress and write to card:"
echo "cat ${IMG_PATH}.zip | gunzip -d | dd of=/dev/sdX"