#! /bin/bash set -ex # runs setup commands inside the arm64 image rootfs. sudo tee mnt/root/tmp/image-build.sh >/dev/null <<'EOF' #! /bin/bash set -ex export DEBIAN_FRONTEND=noninteractive mkdir -p /etc/apt/apt.conf.d/disabled for f in \ /etc/apt/apt.conf.d/*command-not-found* \ /etc/apt/apt.conf.d/*appstream* \ /etc/apt/apt.conf.d/*packagekit* do [ -e "$f" ] && mv "$f" /etc/apt/apt.conf.d/disabled/ done rm -rf /var/lib/apt/lists/* mkdir -p /var/lib/apt/lists/partial # The preinstalled image may contain packages from noble-updates while only # noble and noble-security are enabled. Enable noble-updates before installing # -dev packages so apt can resolve exact-version dependencies. if grep -q '^Suites: noble$' /etc/apt/sources.list.d/ubuntu.sources; then sed -i 's/^Suites: noble$/Suites: noble noble-updates/' /etc/apt/sources.list.d/ubuntu.sources fi echo "====> updating apt" apt-get update echo "====> installing apt packages" apt-get install -y \ ca-certificates \ curl \ jq \ git \ locales \ wpasupplicant \ iproute2 \ isc-dhcp-client \ libcap2-bin \ pkg-config \ libdbus-1-dev \ avahi-daemon \ avahi-utils \ libavahi-client-dev \ bluez \ python3-pip \ sox \ alsa-utils \ libasound2-plugins \ swh-plugins \ i2c-tools \ device-tree-compiler \ unzip \ openssh-server \ sudo # setup locale locale-gen en_US.UTF-8 update-locale LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 echo "====> setting hostname" printf 'toes\n' >/etc/hostname if grep -q '^127\.0\.1\.1' /etc/hosts; then sed -i 's/^127\.0\.1\.1.*/127.0.1.1 toes/' /etc/hosts else printf '127.0.1.1 toes\n' >>/etc/hosts fi mkdir -p /etc/cloud/cloud.cfg.d printf 'preserve_hostname: true\n' >/etc/cloud/cloud.cfg.d/99-preserve-hostname.cfg echo "====> enabling mdns hostname advertisement" systemctl enable avahi-daemon.service echo "====> configuring bluetooth for Matter commissioning" mkdir -p /etc/systemd/system/bluetooth.service.d cat >/etc/systemd/system/bluetooth.service.d/10-matter.conf <<'EOBT' [Service] ExecStart= ExecStart=/usr/libexec/bluetooth/bluetoothd -E -P battery EOBT systemctl enable bluetooth.service echo "====> configuring wlan0 for wpa_supplicant + systemd-networkd" apt-get purge -y network-manager || true systemctl disable NetworkManager.service NetworkManager-wait-online.service NetworkManager-dispatcher.service || true systemctl mask NetworkManager.service NetworkManager-wait-online.service NetworkManager-dispatcher.service || true mkdir -p /etc/wpa_supplicant cat >/etc/wpa_supplicant/wpa_supplicant-wlan0.conf <<'EOWPA' ctrl_interface=DIR=/run/wpa_supplicant GROUP=netdev update_config=1 EOWPA chmod 0600 /etc/wpa_supplicant/wpa_supplicant-wlan0.conf mkdir -p /etc/systemd/system/wpa_supplicant.service.d cat >/etc/systemd/system/wpa_supplicant.service.d/10-wlan0.conf <<'EOSD' [Unit] Requires=sys-subsystem-net-devices-wlan0.device After=sys-subsystem-net-devices-wlan0.device [Service] ExecStart= ExecStart=/usr/sbin/wpa_supplicant -u -s -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant-wlan0.conf -O "DIR=/run/wpa_supplicant GROUP=netdev" Restart=on-failure RestartSec=2s EOSD mkdir -p /etc/systemd/network cat >/etc/systemd/network/00-wlan0.network <<'EONET' [Match] Name=wlan0 [Link] RequiredForOnline=no [Network] DHCP=yes IPv6AcceptRA=yes [DHCPv4] RouteMetric=600 EONET systemctl enable wpa_supplicant.service systemctl enable systemd-networkd.service systemctl enable systemd-resolved.service echo "====> creating toes user" groupadd -f audio if id -u toes >/dev/null 2>&1; then usermod -aG sudo,audio toes else useradd -m -s /bin/bash -G sudo,audio toes fi echo 'toes:nicetrywiseguy' | chpasswd printf 'toes ALL=(ALL) NOPASSWD:ALL\n' >/etc/sudoers.d/90-toes chmod 0440 /etc/sudoers.d/90-toes visudo -cf /etc/sudoers.d/90-toes echo "====> configuring ssh password login" mkdir -p /etc/ssh/sshd_config.d cat >/etc/ssh/sshd_config.d/10-toes-password-login.conf <<'EOSSH' PasswordAuthentication yes EOSSH printf 'ssh_pwauth: true\n' >/etc/cloud/cloud.cfg.d/99-ssh-password-auth.cfg mkdir -p /run/sshd sshd -t sshd -T | grep -qx 'passwordauthentication yes' systemctl enable ssh.service # enable serial over usb echo 'g_serial' >/etc/modules-load.d/usb-serial-gadget.conf systemctl enable serial-getty@ttyGS0.service echo "====> building audio overlay" /tmp/build-audio.sh systemctl enable init-audio.service echo "====> installing rgbled" curl -fsSL https://git.nose.space/nakajima/rgbled/releases/download/v0.1.1/install.sh | bash echo "====> installing matter stack" curl -fsSL https://git.nose.space/nakajima/toes-matter/releases/download/latest/install.sh | sh if [ ! -x /usr/local/bin/toes-matter ]; then echo "missing /usr/local/bin/toes-matter after install" >&2 exit 1 fi systemctl enable toes-matter.service TOES_HOME="$(getent passwd toes | cut -d: -f6)" mkdir -p "$TOES_HOME" chown toes:toes "$TOES_HOME" echo "====> installing bun" runuser -u toes -- env HOME="$TOES_HOME" USER=toes LOGNAME=toes bash -c \ 'curl -fsSL https://bun.sh/install | bash >/dev/null 2>&1' BUN="$TOES_HOME/.bun/bin/bun" if [ ! -x "$BUN" ]; then echo "missing bun after install: $BUN" >&2 exit 1 fi ln -sf "$BUN" /usr/local/bin/bun setcap 'cap_net_bind_service=+ep' "$BUN" echo "====> installing toes app as toes" runuser -u toes -- env HOME="$TOES_HOME" USER=toes LOGNAME=toes bash <<'EOSU' set -ex export PATH="$HOME/.bun/bin:/usr/local/bin:/usr/bin:/bin:$PATH" quiet() { "$@" } REPO="https://git.nose.space/defunkt/toes" DEST="$HOME/toes" APPS_DIR="$HOME/apps" DATA_DIR="$HOME/data" echo "====> installing baudy" if [ ! -d "$HOME/baudy" ]; then git clone https://git.nose.space/nakajima/baudy "$HOME/baudy" fi if [ -d "$DEST/.git" ]; then echo "====> Pulling latest toes" git -C "$DEST" fetch origin main git -C "$DEST" reset --hard origin/main else echo "====> Cloning toes" git clone "$REPO" "$DEST" fi mkdir -p "$APPS_DIR" "$DATA_DIR" "$DATA_DIR/toes" cd "$DEST" echo "====> Installing dependencies" bun install echo "====> Building" bun run build for app in $BUNDLED_APPS; do [ -d "$DEST/apps/$app" ] || continue echo " $app" cp -r "$DEST/apps/$app" "$APPS_DIR/" if [ -f "$APPS_DIR/$app/package.json" ]; then quiet bun install --frozen-lockfile --cwd "$APPS_DIR/$app" || quiet bun install --cwd "$APPS_DIR/$app" fi done EOSU echo "====> Installing toes service" install -m 644 "$TOES_HOME/toes/scripts/toes.service" /etc/systemd/system/toes.service systemctl enable toes.service echo "====> setting initial volume" amixer -c toesaudio sset 'Speaker Analog' 80% amixer -c toesaudio sset 'DAC' 50% amixer -c toesaudio sset 'Speaker Driver' 0 alsactl store EOF sudo chmod +x mnt/root/tmp/image-build.sh sudo chroot mnt/root /bin/bash /tmp/image-build.sh sudo rm -f mnt/root/tmp/image-build.sh if [ ! -s mnt/boot/overlays/toesaudio.dtbo ]; then echo "missing mnt/boot/overlays/toesaudio.dtbo after chroot build" >&2 exit 1 fi