├── .gitignore ├── hooks ├── 19-unset-hostname.chroot ├── 999-clean-resolv-conf.chroot ├── 40-remove-pkgs.chroot ├── 90-configure-hook.chroot ├── 700-classic-dir.chroot ├── 18-set-os-release.chroot ├── 00-extra-packages.chroot ├── 20-extra-files.chroot ├── 01-setup_user.chroot ├── 21-snappy-security-policy-stamp.chroot ├── 30-fix-timedatectl.chroot ├── 600-no-debian.chroot ├── 02-spread-support.chroot ├── 900-cleanup-etc-var.chroot └── 03-writable-paths.chroot ├── tests ├── main │ ├── smoke │ │ └── task.yaml │ └── hostname │ │ └── task.yaml └── lib │ ├── .gitignore │ ├── umount-image │ ├── mount-image │ ├── README.md │ ├── Makefile │ └── create-image ├── .travis.yml ├── snapcraft.yaml ├── README.md ├── spread.yaml └── Makefile /.gitignore: -------------------------------------------------------------------------------- 1 | *.snap 2 | parts/ 3 | snap/ 4 | prime/ 5 | stage/ 6 | -------------------------------------------------------------------------------- /hooks/19-unset-hostname.chroot: -------------------------------------------------------------------------------- 1 | #!/bin/sh -ex 2 | 3 | rm -f /etc/hostname 4 | -------------------------------------------------------------------------------- /hooks/999-clean-resolv-conf.chroot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | echo "" > /etc/resolv.conf 6 | -------------------------------------------------------------------------------- /tests/main/smoke/task.yaml: -------------------------------------------------------------------------------- 1 | summary: Smoke test that ensures the system can boot in spread 2 | execute: | 3 | true 4 | -------------------------------------------------------------------------------- /tests/lib/.gitignore: -------------------------------------------------------------------------------- 1 | base-18/ 2 | core-snap/ 3 | core_*.assert 4 | initrd 5 | kernel 6 | kernel-snap/ 7 | pc-kernel_*.assert 8 | -------------------------------------------------------------------------------- /hooks/40-remove-pkgs.chroot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | echo "Remove uneeded packages" 6 | dpkg -r --force-depends dh-python 7 | -------------------------------------------------------------------------------- /tests/main/hostname/task.yaml: -------------------------------------------------------------------------------- 1 | summary: Ensure that there is no hostname set 2 | execute: | 3 | test ! -e /etc/hostname 4 | test "$(hostname)" = localhost 5 | -------------------------------------------------------------------------------- /hooks/90-configure-hook.chroot: -------------------------------------------------------------------------------- 1 | #!/bin/sh -ex 2 | 3 | # add all requirements for bits used by the hooks/configure script 4 | 5 | mkdir -p /etc/systemd/logind.conf.d 6 | -------------------------------------------------------------------------------- /hooks/700-classic-dir.chroot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # create hostfs entry 4 | 5 | set -ex 6 | 7 | echo "I: Adding var/lib/snapd/hostfs" 8 | 9 | install -m755 -d var/lib/snapd/hostfs 10 | 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | os: linux 3 | dist: trusty 4 | sudo: enabled 5 | script: 6 | - sudo apt-get update 7 | - sudo apt-get install --yes --no-install-recommends snapd 8 | - sudo snap install --classic snapcraft 9 | - sudo snapcraft 10 | -------------------------------------------------------------------------------- /hooks/18-set-os-release.chroot: -------------------------------------------------------------------------------- 1 | #!/bin/sh -ex 2 | 3 | cat >/usr/lib/os-release<&2 6 | ln -sf ../proc/self/mounts /etc/mtab 7 | mkdir -p /lib/modules 8 | mkdir -p /lib/firmware 9 | mkdir -p /writable 10 | mkdir -p /var/lib/systemd/rfkill 11 | touch /etc/machine-id 12 | 13 | echo "creating fontconfig mount points" >&2 14 | mkdir -p /usr/share/fonts 15 | mkdir -p /usr/local/share/fonts 16 | mkdir -p /var/cache/fontconfig 17 | 18 | echo "creating snap dirs/files" 19 | mkdir -p /snap /var/snap 20 | mkdir -p /usr/lib/snapd 21 | -------------------------------------------------------------------------------- /hooks/01-setup_user.chroot: -------------------------------------------------------------------------------- 1 | #!/bin/sh -x 2 | 3 | set -e 4 | 5 | # There is no default user anymore, console-conf is responsible 6 | # for creating one 7 | 8 | # setup the required files for extrausers 9 | for name in group gshadow passwd shadow subuid subgid; do 10 | touch /var/lib/extrausers/$name 11 | done 12 | 13 | for name in gshadow shadow; do 14 | chmod 640 /var/lib/extrausers/$name 15 | chown root:shadow /var/lib/extrausers/$name 16 | done 17 | 18 | # Enable libnss-extrusers 19 | sed -i 's/^group:.*compat/\0 extrausers/' /etc/nsswitch.conf 20 | sed -i 's/^passwd:.*compat/\0 extrausers/' /etc/nsswitch.conf 21 | sed -i 's/^shadow:.*compat/\0 extrausers/' /etc/nsswitch.conf 22 | -------------------------------------------------------------------------------- /tests/lib/README.md: -------------------------------------------------------------------------------- 1 | This directory contains support scripts boot-testing the base-18 snap. 2 | The test is very crude as you have to do it interactively. 3 | 4 | After booting move to VT7 by clicking on the qemu window and pressing alt+right 5 | (or left) until you reach the root prompt. If you are running a Wayland session 6 | QEMU may misbehave and print a message mentioning not having some input 7 | keymaps. If that happens you need to log into an X11 session instead. 8 | 9 | Known issues: 10 | - the initrd used for booting is the one from base-16 (aka current core) 11 | 12 | Required tools: 13 | - fdisk 14 | - kpartx 15 | - mkfs.ext4 16 | - mkfs.vfat 17 | - mount and umount 18 | - qemu-img and qemu-system-x86-64 19 | - snap 20 | - sudo 21 | - wipefs 22 | -------------------------------------------------------------------------------- /hooks/21-snappy-security-policy-stamp.chroot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Create the security policy version file. Its important that the file 4 | # content changes every time an of the "apparmor" or "seccomp" policies 5 | # (or its generators) get updated. 6 | # 7 | # snappy will use this file for its "snappy policygen --regenerate-all" 8 | # systemd unit. It will store the security-policy-version file on each 9 | # --regenerate-all call. On each boot it will compare the stored version 10 | # with the version on the image and if they are different regenerate the 11 | # policies 12 | 13 | set -e 14 | 15 | 16 | echo "create security policy version" >&2 17 | mkdir -p /usr/share/snappy/ 18 | apt list --installed apparmor ubuntu-core-security-* > /usr/share/snappy/security-policy-version 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Base 18 snap for snapd 2 | 3 | This is a base snap for snapd that is based on Ubuntu 18.04 4 | 5 | # Building locally 6 | 7 | To build this snap locally you need snapcraft. The project must be built as real root. 8 | 9 | ``` 10 | $ sudo snapcraft 11 | ``` 12 | 13 | # Testing locally 14 | 15 | Once built you can boot it for testing inside qemu and spread. You will need 16 | additional tool (see tests/lib/README.md for details). In order to prepare an 17 | image for either exploratory manual tests or for spread tests run this command: 18 | 19 | ``` 20 | $ make update-image 21 | ``` 22 | 23 | With this available you can either run: `spread -debug -v` or `make -C 24 | tests/lib just-boot`, depending on what you want to do. The interactive (just 25 | boot) test should allow you to move to VT7 where a root shell awaits. 26 | -------------------------------------------------------------------------------- /hooks/30-fix-timedatectl.chroot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | mv /usr/bin/timedatectl /usr/bin/timedatectl.real 6 | 7 | cat >/usr/bin/timedatectl<<'EOF' 8 | #!/bin/sh 9 | 10 | # wrapper to make sure timedatectl works with the 11 | # writable-paths setup on ubuntu core (making the symlink 12 | # absolute instead of using a relative path) 13 | # LP: #1650688 for details 14 | 15 | set -e 16 | 17 | TIMEDATECTL=/usr/bin/timedatectl.real 18 | 19 | case $1 in 20 | set-timezone) 21 | $TIMEDATECTL set-timezone $2 22 | # make a .tmp link and mv it to have "kind of" atomic 23 | # writing here in case of a power loss midway through 24 | ln -s /usr/share/zoneinfo/$2 /etc/writable/localtime.tmp 25 | mv /etc/writable/localtime.tmp /etc/writable/localtime 26 | ;; 27 | *) 28 | $TIMEDATECTL $@ 29 | ;; 30 | esac 31 | EOF 32 | 33 | chmod 755 /usr/bin/timedatectl 34 | -------------------------------------------------------------------------------- /spread.yaml: -------------------------------------------------------------------------------- 1 | project: base-18 2 | environment: 3 | PROJECT_PATH: /tmp/base-18 4 | LANG: "$(echo ${LANG:-C.UTF-8})" 5 | LANGUAGE: "$(echo ${LANGUAGE:-en})" 6 | backends: 7 | local: 8 | type: adhoc 9 | allocate: | 10 | echo "Allocate called" 11 | make -C tests/lib background-start 12 | ADDRESS localhost:8022 13 | discard: | 14 | echo "Discard called" 15 | make -C tests/lib background-stop 16 | systems: 17 | - base-18-amd64: 18 | username: ubuntu 19 | password: ubuntu 20 | path: /tmp/base-18 21 | exclude: 22 | - "*.raw" 23 | - "*.snap" 24 | - Makefile 25 | - README.md 26 | - hooks 27 | - parts 28 | - prime 29 | - snap 30 | - spread.yaml 31 | - stage 32 | kill-timeout: 20m 33 | prepare: | 34 | true 35 | restore: | 36 | true 37 | suites: 38 | tests/main/: 39 | summary: Tests for base-18 snap. 40 | # vim:ts=4:sw=4:et 41 | -------------------------------------------------------------------------------- /hooks/600-no-debian.chroot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # removing debian packaging artifacts 4 | 5 | set -ex 6 | 7 | echo "I: Removing the debian legacy" 8 | 9 | # store manifest of all installed packages 10 | install -m755 -d usr/share/snappy 11 | dpkg -l > usr/share/snappy/dpkg.list 12 | 13 | # dpkg-deb and dpkg purposefully left behind 14 | chroot . dpkg --purge --force-depends apt libapt-pkg5.0 15 | rm -r \ 16 | var/lib/dpkg \ 17 | var/log/apt 18 | rm \ 19 | usr/bin/dpkg \ 20 | usr/bin/dpkg-query \ 21 | usr/bin/dpkg-split \ 22 | usr/bin/dpkg-divert \ 23 | usr/bin/dpkg-trigger \ 24 | usr/bin/dpkg-statoverride \ 25 | usr/bin/dpkg-maintscript-helper 26 | 27 | # remove generated locales for packages we do not use 28 | rm -f usr/share/locale/*/LC_MESSAGES/dpkg* 29 | rm -f usr/share/locale/*/LC_MESSAGES/libapt* 30 | # remove generated logs 31 | rm -f var/log/bootstrap.log \ 32 | var/log/alternatives.log \ 33 | var/log/dpkg.log 34 | # also remove obsolete cron jobs 35 | rm -f /etc/cron.daily/dpkg \ 36 | /etc/cron.daily/passwd 37 | 38 | -------------------------------------------------------------------------------- /hooks/02-spread-support.chroot: -------------------------------------------------------------------------------- 1 | #!/bin/sh -x 2 | set -e 3 | 4 | # XXX: This is just for testing. This MUST NOT be a part of released base-18 5 | # snap. Before we have a way to inject the test support user into the image 6 | # this hack will do. 7 | 8 | # Add an user with know name and password (ubuntu:ubuntu with password ubuntu) 9 | addgroup --gid 1000 ubuntu 10 | adduser --uid 1000 --gid 1000 --disabled-password --gecos "Ubuntu,,," ubuntu 11 | echo "ubuntu:ubuntu" | chpasswd 12 | usermod --append --groups sudo ubuntu 13 | 14 | # Install enable and configure systemd-{networkd,resolved}. 15 | # (They are in the systemd package which is already installed). 16 | systemctl enable systemd-networkd.service 17 | systemctl enable systemd-resolved.service 18 | 19 | cat > /etc/systemd/network/wired.network << __UNIT__ 20 | [Match] 21 | Name=eth* 22 | Name=en* 23 | 24 | [Network] 25 | DHCP=yes 26 | __UNIT__ 27 | 28 | ln -fs ../run/systemd/resolve/stub-resolv.conf /etc/resolv.conf 29 | 30 | # Install and enable ssh so that we can log in remotely. 31 | apt-get install -y openssh-server 32 | systemctl enable ssh.socket 33 | systemctl enable ssh.service 34 | 35 | # Install sudo for interactive poking as root. Spread requires password-less 36 | # sudo so configure that. 37 | apt-get install -y sudo 38 | echo "ubuntu ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/spread 39 | chmod 0444 /etc/sudoers.d/spread 40 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DPKG_ARCH := $(shell dpkg --print-architecture) 2 | BASE := bionic-base-$(DPKG_ARCH).tar.gz 3 | 4 | .PHONY: all 5 | all: check 6 | # nothing 7 | 8 | .PHONY: install 9 | install: 10 | # install base 11 | if [ -z "$(DESTDIR)" ]; then \ 12 | echo "no DESTDIR set"; \ 13 | exit 1; \ 14 | fi 15 | if [ ! -f ../$(BASE) ]; then \ 16 | wget -P ../ http://cdimage.ubuntu.com/ubuntu-base/daily/current/$(BASE); \ 17 | fi 18 | rm -rf $(DESTDIR) 19 | mkdir -p $(DESTDIR) 20 | tar -x -f ../$(BASE) -C $(DESTDIR) 21 | # ensure resolving works inside the chroot 22 | cat /etc/resolv.conf > $(DESTDIR)/etc/resolv.conf 23 | # customize 24 | set -ex; for f in ./hooks/[0-9]*.chroot; do \ 25 | cp -a $$f $(DESTDIR)/tmp && \ 26 | if ! chroot $(DESTDIR) /tmp/$$(basename $$f); then \ 27 | exit 1; \ 28 | fi && \ 29 | rm -f $(DESTDIR)/tmp/$$(basename $$f); \ 30 | done; 31 | # only generate manifest file for lp build 32 | if [ -e /build/base-18 ]; then \ 33 | echo $$f; \ 34 | cp $(DESTDIR)/usr/share/snappy/dpkg.list /build/base-18/base-18-$$(date +%Y%m%d%H%M)_$(DPKG_ARCH).manifest; \ 35 | fi; 36 | 37 | .PHONY: check 38 | check: 39 | # exclude "useless cat" from checks, while useless also 40 | # some things more readable 41 | shellcheck -e SC2002 hooks/* 42 | 43 | 44 | # Display a report of files that are (still) present in /etc 45 | .PHONY: etc-report 46 | etc-report: 47 | cd stage && find etc/ 48 | echo "Amount of cruft in /etc left: `find stage/etc/ | wc -l`" 49 | 50 | .PHONY: update-image 51 | update-image: 52 | sudo snapcraft clean 53 | sudo snapcraft 54 | sudo $(MAKE) -C tests/lib just-update 55 | -------------------------------------------------------------------------------- /hooks/900-cleanup-etc-var.chroot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | # Many things in the generated /etc directory are not really needed and are 6 | # clouding the view towards the work of eventually shipping with empty /etc 7 | echo "Cleaning up unneeded files in /etc" 8 | 9 | # package manager related stuff 10 | rm -rvf /etc/apt 11 | rm -rvf /etc/dpkg 12 | 13 | # misc 14 | rm -rvf /etc/kernel 15 | rm -rvf /etc/opt 16 | rm -rvf /etc/selinux 17 | rm -rvf /etc/binfmt.d 18 | rm /etc/gai.conf 19 | rm /etc/hosts.allow /etc/hosts.deny 20 | rm /etc/magic /etc/magic.mime 21 | rm /etc/mailcap /etc/mailcap.order 22 | rm -rf /etc/modules-load.d 23 | rm /etc/debian_version 24 | rm /etc/pam.conf 25 | rmdir /etc/profile.d 26 | rm /etc/rmt 27 | rm /etc/sysctl.conf 28 | rm -rf /etc/terminfo 29 | rm -rf /etc/tmpfiles.d 30 | rm /etc/wgetrc 31 | 32 | # python3 sets byte-compile default for debian 33 | rm -rf /etc/python3 34 | # python3.6 imports apport 35 | rm -rf /etc/python3.6 36 | 37 | # only provides a symbolic name for "link-local" 38 | rm /etc/networks 39 | 40 | # no need for old style init 41 | rm -rf /etc/rc[0-6S].d 42 | rm -rf /etc/init.d 43 | 44 | # remove alternatives for manual pages (easier) 45 | rm -f /etc/alternatives/*.gz 46 | 47 | # tool configuration (unused) 48 | rm -f /etc/mke2fs.conf 49 | 50 | # python deb install leftovers 51 | rm -rf /usr/local/lib/python* 52 | 53 | # we have no cron daily jobs 54 | rmdir /etc/cron.daily 55 | 56 | # no need for emtpy dirs 57 | rmdir /etc/dbus-1/session.d /etc/dbus-1/system.d 58 | 59 | # undo all symlinks to /etc/alternatives and replace with their real 60 | # counterparts. The alternatives system looks like this: 61 | # 62 | # /usr/bin/pager -> /etc/alternatives/pager -> /bin/more 63 | # 64 | find /etc/alternatives -type l | while read -r f; do 65 | real=$(readlink -f "$f") 66 | alias=$(dirname "$real")/$(basename "$f") 67 | rm -f "$alias" 68 | ln -s "$real" "$alias" 69 | done 70 | rm -rf /etc/alternatives 71 | 72 | # no permanet journal 73 | rm -rf /var/log/journal 74 | 75 | 76 | # FIXME: make /etc/lsb-release point to ../usr/lib/lsb-release 77 | -------------------------------------------------------------------------------- /tests/lib/Makefile: -------------------------------------------------------------------------------- 1 | # XXX: this needs to be in sync with what's in spread.yaml 2 | QEMU_CMD = qemu-system-x86_64 \ 3 | -enable-kvm \ 4 | -smp 2 \ 5 | -m 1500 \ 6 | -netdev user,id=mynet0,hostfwd=tcp::8022-:22,hostfwd=tcp::8090-:80 \ 7 | -device virtio-net-pci,netdev=mynet0 \ 8 | -drive file=base-18/image.raw,format=raw \ 9 | -vga qxl \ 10 | -snapshot \ 11 | -kernel kernel \ 12 | -initrd initrd \ 13 | -append "root=LABEL=writable snap_core=base-18_very-unstable_amd64.snap snap_kernel=pc-kernel.snap ro net.ifnames=0 init=/lib/systemd/systemd console=tty1 systemd.debug-shell=1" 14 | 15 | # Update (or build if missing) and boot the image 16 | .PHONY: update-and-boot 17 | .ONESHELL: update-and-boot 18 | update-and-boot: 19 | $(MAKE) just-update 20 | $(MAKE) just-boot 21 | 22 | # Update (or build if missing) the image. 23 | .PHONY: just-update 24 | .ONESHELL: just-update 25 | just-update: kernel initrd ../../base-18_very-unstable_amd64.snap 26 | if [ ! -e base-18/image.raw ]; then 27 | # Create some files and directories so that they are all owned by us. 28 | mkdir -p base-18/p1 29 | mkdir -p base-18/p2 30 | mkdir -p base-18/p3 31 | touch base-18/image.raw 32 | touch base-18/image.script 33 | sudo ./create-image base-18 34 | fi 35 | # Update (this puts the kernel and new base-18 snap inside) 36 | sudo ./mount-image base-18 37 | sudo cp ../../base-18_very-unstable_amd64.snap base-18/p3/system-data/var/lib/snapd/snaps/ 38 | sudo cp --dereference pc-kernel.snap base-18/p3/system-data/var/lib/snapd/snaps/ 39 | sudo ./umount-image base-18 40 | 41 | # Just boot the image 42 | .PHONY: just-boot 43 | .ONESHELL: just-boot 44 | just-boot: kernel initrd base-18/image.raw 45 | $(QEMU_CMD) 46 | 47 | # Start the image in the background. This is relevant for spread. 48 | .ONESHELL: background-start 49 | .PHONY: background-start 50 | background-start: 51 | $(QEMU_CMD) -nographic /dev/null 2>&1 & # NOTE: The redirects are relevant for spread. 52 | echo $$! >qemu.pid 53 | sleep 10 # ballpark figure, enough to boot. 54 | 55 | # Stop the image that (may be) running in the background. This is relevant for spread. 56 | .ONESHELL: background-stop 57 | .PHONY: background-stop 58 | background-stop: 59 | if [ -e qemu.pid ]; then 60 | kill "$$(cat qemu.pid)" 61 | rm -f qemu.pid 62 | fi 63 | 64 | .PHONY: clean 65 | clean: 66 | rm -f core_*.assert 67 | rm -f core_*.snap 68 | rm -f initrd 69 | rm -f kernel 70 | rm -f pc-kernel_*.assert 71 | rm -f pc-kernel_*.snap 72 | rm -rf base-18 73 | rm -rf kernel-snap 74 | rm -rf core-snap 75 | rm -f core.snap 76 | rm -f pc-kernel.snap 77 | 78 | # Vanilla pc-kernel kernel image 79 | kernel: kernel-snap/kernel.img 80 | ln -sf "$^" "$@" 81 | 82 | # Vanilla base-16 initrd 83 | initrd: core-snap/boot/initrd.img-core 84 | ln -sf "$^" "$@" 85 | 86 | # Vanilla base-16 core snap so that we have an initrd 87 | core.snap: 88 | snap download core 89 | ln -sf "$$(find -name "core_*.snap" | sort | tail -1)" "$@" 90 | 91 | # Vanilla pc-kernel snap for a kernel to boot. 92 | pc-kernel.snap: 93 | snap download pc-kernel 94 | ln -sf "$$(find -name "pc-kernel_*.snap" | sort | tail -1)" "$@" 95 | 96 | # Extract the initrd from the (base-16) core snap 97 | core-snap/boot/initrd.img-core: core.snap 98 | rm -rf core-snap 99 | unsquashfs -dest core-snap -no-progress "$^" '/boot/initrd.img*' >/dev/null 100 | touch "$@" 101 | 102 | # Extract the kernel image from the pc-kernel snap 103 | kernel-snap/kernel.img: pc-kernel.snap 104 | rm -rf kernel-snap 105 | unsquashfs -dest kernel-snap -no-progress "$^" '/kernel.img' >/dev/null 106 | sudo chmod 0644 "$^" 107 | touch "$@" 108 | -------------------------------------------------------------------------------- /tests/lib/create-image: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -uxe 3 | 4 | # This script requires root 5 | test "$(id -u)" -ne 0 && exit 1 6 | 7 | # This script requires an argument (directory name). 8 | test -z "${1:-}" && exit 1 9 | D="$1" 10 | 11 | # Create the directory where everything is kept. 12 | mkdir -p "$D" 13 | 14 | # Create a raw image. 15 | qemu-img create -q -f raw "$D"/image.raw 4G 16 | wipefs --all "$D"/image.raw 17 | 18 | # Describe the disk layout in a sfdisk-compatible script. 19 | cat >"$D"/image.script << __SCRIPT__ 20 | label: gpt 21 | label-id: 00000000-0000-0000-0000-000000000001 22 | device: $D/image.raw 23 | unit: sectors 24 | first-lba: 34 25 | last-lba: 7577566 26 | 27 | $D/image.raw.img1 : start= 2048, size= 2048, type=21686148-6449-6E6F-744E-656564454649, uuid=00000000-0000-0000-0000-000000000002, name="BIOS Boot" 28 | $D/image.raw.img2 : start= 4096, size= 102400, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=00000000-0000-0000-0000-000000000003, name="EFI System" 29 | $D/image.raw.img3 : start= 106496, size= 7471071, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=00000000-0000-0000-0000-000000000004, name="writable" 30 | __SCRIPT__ 31 | 32 | # Partition the disk according to the script. 33 | fdisk "$D"/image.raw << __INTERACTIVE__ 34 | I 35 | $D/image.script 36 | w 37 | q 38 | __INTERACTIVE__ 39 | 40 | # Use three-partition layout: 41 | # p1: bootloader raw partition, irrelevant for quick testing. 42 | # p2: EFI system partition, irrelevant for quick testing. 43 | # p3: writable partition, whole system is here. 44 | mkdir -p "$D"/p1 45 | mkdir -p "$D"/p2 46 | mkdir -p "$D"/p3 47 | 48 | # Expose individual partitions and mount the 3rd partition. 49 | loopNp=$(kpartx -sav "$D"/image.raw | grep -E -o 'loop[0-9]+p' | head -n 1) 50 | mkfs.vfat /dev/mapper/"${loopNp}2" 51 | mkfs.ext4 -U clear /dev/mapper/"${loopNp}3" 52 | e2label /dev/mapper/"${loopNp}3" writable 53 | mount /dev/mapper/"${loopNp}2" "$D"/p2 54 | mount /dev/mapper/"${loopNp}3" "$D"/p3 55 | 56 | # Create some stub directories on the EFI system partition 57 | mkdir -p "$D"/p2/EFI/boot 58 | mkdir -p "$D"/p2/EFI/ubuntu 59 | 60 | # Create some stub directories. 61 | mkdir -p "$D"/p3/system-data/etc 62 | mkdir -p "$D"/p3/system-data/var/lib/apparmor/profiles 63 | mkdir -p "$D"/p3/system-data/var/lib/cloud 64 | mkdir -p "$D"/p3/system-data/var/lib/console-conf 65 | mkdir -p "$D"/p3/system-data/var/lib/dbus 66 | mkdir -p "$D"/p3/system-data/var/lib/dhcp 67 | mkdir -p "$D"/p3/system-data/var/lib/extrausers 68 | mkdir -p "$D"/p3/system-data/var/lib/initramfs-tools 69 | mkdir -p "$D"/p3/system-data/var/lib/logrotate 70 | mkdir -p "$D"/p3/system-data/var/lib/misc 71 | mkdir -p "$D"/p3/system-data/var/lib/systemd 72 | mkdir -p "$D"/p3/system-data/var/lib/waagent 73 | mkdir -p "$D"/p3/system-data/var/log/console-conf 74 | mkdir -p "$D"/p3/system-data/var/log/fsck 75 | mkdir -p "$D"/p3/system-data/var/snap 76 | mkdir -p "$D"/p3/system-data/var/tmp 77 | mkdir -p "$D"/p3/user-data 78 | 79 | # Create snapd directory skeleton. 80 | mkdir -p "$D"/p3/system-data/var/lib/snapd/apparmor/snap-confine.d 81 | mkdir -p "$D"/p3/system-data/var/lib/snapd/assertions 82 | mkdir -p "$D"/p3/system-data/var/lib/snapd/auto-import 83 | mkdir -p "$D"/p3/system-data/var/lib/snapd/cookie 84 | mkdir -p "$D"/p3/system-data/var/lib/snapd/desktop/applications 85 | mkdir -p "$D"/p3/system-data/var/lib/snapd/device 86 | mkdir -p "$D"/p3/system-data/var/lib/snapd/device/private-keys-v1 87 | mkdir -p "$D"/p3/system-data/var/lib/snapd/environment 88 | mkdir -p "$D"/p3/system-data/var/lib/snapd/firstboot 89 | mkdir -p "$D"/p3/system-data/var/lib/snapd/hostfs 90 | mkdir -p "$D"/p3/system-data/var/lib/snapd/lib/gl 91 | mkdir -p "$D"/p3/system-data/var/lib/snapd/mount 92 | mkdir -p "$D"/p3/system-data/var/lib/snapd/repair 93 | mkdir -p "$D"/p3/system-data/var/lib/snapd/seccomp/bpf 94 | mkdir -p "$D"/p3/system-data/var/lib/snapd/seccomp/profiles 95 | mkdir -p "$D"/p3/system-data/var/lib/snapd/seed/assertions 96 | mkdir -p "$D"/p3/system-data/var/lib/snapd/seed/snaps 97 | mkdir -p "$D"/p3/system-data/var/lib/snapd/snaps/partial 98 | mkdir -p "$D"/p3/system-data/var/lib/snapd/void 99 | 100 | umount "$D"/p2 101 | umount "$D"/p3 102 | kpartx -sdv "$D"/image.raw 103 | -------------------------------------------------------------------------------- /hooks/03-writable-paths.chroot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | # XXX: we want to migrate away from writable paths but having _some_ support of 4 | # this for now lets us walk before we run. 5 | mkdir -p /etc/system-image 6 | cat > /etc/system-image/writable-paths << __WRITABLE__ 7 | # -------------------------------------------------------------------- 8 | # 1st column: Mount point 9 | # 2nd column: Path relative to root of persistent storage (or auto) 10 | # 3rd column: type => persistent|synced|temporary 11 | # 4th column: action => none|transition (transition requires persistent) 12 | # 5th column: mount flags 13 | # 14 | # See writable-paths(5) for full details. 15 | # -------------------------------------------------------------------- 16 | /etc/apparmor.d/cache auto persistent none none 17 | /etc/dbus-1/system.d auto persistent transition none 18 | /etc/default/swapfile auto persistent transition none 19 | /etc/hosts auto persistent transition none 20 | /etc/init auto persistent transition none 21 | /etc/iproute2 auto persistent transition none 22 | /etc/modprobe.d auto synced none none 23 | /etc/modules-load.d auto persistent transition none 24 | /etc/netplan auto persistent transition none 25 | /etc/network/if-up.d auto persistent transition none 26 | /etc/network/interfaces.d auto persistent transition none 27 | /etc/rsyslog.d auto persistent transition none 28 | /etc/ssh auto persistent transition none 29 | /etc/sudoers.d auto persistent transition none 30 | /etc/systemd auto persistent transition none 31 | /etc/udev/rules.d auto persistent transition none 32 | /etc/writable auto synced none none 33 | /media none temporary none defaults 34 | /mnt none temporary none defaults 35 | /root auto persistent transition none 36 | /tmp none temporary none defaults 37 | /var/cache/apparmor auto persistent transition none 38 | /var/crash auto persistent none none 39 | /var/lib/apparmor auto persistent transition none 40 | /var/lib/console-conf auto persistent transition none 41 | /var/lib/dbus auto persistent none none 42 | /var/lib/dhcp auto persistent none none 43 | /var/lib/extrausers auto persistent transition none 44 | /var/lib/initramfs-tools auto persistent transition none 45 | /var/lib/logrotate auto persistent none none 46 | /var/lib/misc auto persistent transition none 47 | /var/lib/sudo auto temporary none defaults,mode=0700 48 | /var/lib/system-image auto persistent none none 49 | /var/lib/systemd/random-seed auto persistent transition none 50 | /var/lib/systemd/rfkill auto persistent transition none 51 | /var/lib/upower auto persistent none none 52 | /var/lib/ureadahead auto persistent transition none 53 | /var/lib/waagent auto persistent transition none 54 | /var/lib/whoopsie auto persistent transition none 55 | /var/log auto persistent transition none 56 | /var/tmp auto persistent transition none 57 | __WRITABLE__ 58 | --------------------------------------------------------------------------------