install.sh: self-answering ssh login via SSH_ASKPASS_REQUIRE=force

OpenSSH deliberately reads passwords from the terminal only; since 8.4
an askpass helper overrides that even with a tty. The fresh image's
public default now answers both ssh and sudo - the installer runs with
zero typed credentials on any modern distro (older OpenSSH falls back
to one prompt).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jorijn van der Graaf 2026-08-09 02:24:47 +02:00
commit 8f688024b3

View file

@ -33,23 +33,29 @@ command -v ssh >/dev/null || die "ssh not found"
[ -f "$ROOTFS" ] || die "$ROOTFS not found (download it from the release)" [ -f "$ROOTFS" ] || die "$ROOTFS not found (download it from the release)"
fastboot devices 2>/dev/null | grep -q fastboot || \ fastboot devices 2>/dev/null | grep -q fastboot || \
die "no device in fastboot mode (Vol-down + Power, USB connected)" die "no device in fastboot mode (Vol-down + Power, USB connected)"
fastboot oem device-info 2>&1 | grep -q "Device unlocked: true" || \
die "bootloader is LOCKED - nothing was changed. Unlock it first (OEM
unlocking in Android developer settings + Fairphone's unlock code:
https://support.fairphone.com/hc/en-us/articles/10492476238737),
then re-run. Note that unlocking wipes the phone."
cat <<'EOF' cat <<'EOF'
This will REPLACE the operating system on the connected Fairphone 6 This will replace the operating system on the connected Fairphone 6 with catcrafts patched postmarketos. Keep the phone connected on USB for the entirety of this script's duration.
(userdata + boot). The modem's NV storage is preserved - that is the point If this has been usefull please consider donating at https://ca
of this installer. Press Enter to continue, Ctrl-C to abort. WARNING: This is a early version of the install script for power users ahead of the official release, while tested this has not been trough the strict quality control the offical release will have.
Press Enter to continue, Ctrl-C to abort.
EOF EOF
read -r _ read -r _
# --- 1+2: safe fastboot writes ------------------------------------------------- # --- 1+2: safe fastboot writes -------------------------------------------------
say "erasing dtbo (one-time; safe - does not touch modem NV)" say "erasing dtbo"
fastboot erase dtbo fastboot erase dtbo
say "flashing rootfs to userdata (this is the big one, be patient)" say "flashing rootfs to userdata"
fastboot flash userdata "$ROOTFS" fastboot flash userdata "$ROOTFS"
# --- 3: RAM-boot the kernel, no write ----------------------------------------- # --- 3: RAM-boot the kernel, no write -----------------------------------------
say "RAM-booting the new system (nothing is written)" say "RAM-booting the new system"
fastboot boot "$BOOT" fastboot boot "$BOOT"
say "waiting for the phone to come up on the USB network ($PHONE)" say "waiting for the phone to come up on the USB network ($PHONE)"
@ -98,24 +104,27 @@ SSHOPTS="-o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=/dev/null \
-o ControlMaster=auto -o ControlPath=$CTL -o ControlPersist=120" -o ControlMaster=auto -o ControlPath=$CTL -o ControlPersist=120"
SUDO="SUDO_ASKPASS=/tmp/.fp6-install-pw sudo -A" SUDO="SUDO_ASKPASS=/tmp/.fp6-install-pw sudo -A"
if command -v sshpass >/dev/null; then # ssh refuses to read a password from stdin (it wants the terminal), but
say "connecting (default credentials, no typing needed)" # OpenSSH >= 8.4 honors an askpass helper even with a terminal attached via
SSHCMD="sshpass -p $PW ssh $SSHOPTS" # SSH_ASKPASS_REQUIRE=force - so the known fresh-image password answers
else # itself. On older OpenSSH this falls back to one interactive prompt.
say "connecting - type the password ONCE (fresh image default: 147147)" ASKPASS=$(mktemp)
SSHCMD="ssh $SSHOPTS" printf '#!/bin/sh\necho %s\n' "$PW" > "$ASKPASS"
fi chmod 700 "$ASKPASS"
trap 'rm -f "$ASKPASS"' EXIT
export SSH_ASKPASS="$ASKPASS" SSH_ASKPASS_REQUIRE=force DISPLAY="${DISPLAY:-:0}"
say "connecting (fresh-image default credentials answer automatically)"
# shellcheck disable=SC2086 # shellcheck disable=SC2086
$SSHCMD "user@$PHONE" \ ssh $SSHOPTS "user@$PHONE" \
"printf '#!/bin/sh\necho $PW\n' > /tmp/.fp6-install-pw && chmod 700 /tmp/.fp6-install-pw && echo CONNECTED" \ "printf '#!/bin/sh\necho $PW\n' > /tmp/.fp6-install-pw && chmod 700 /tmp/.fp6-install-pw && echo CONNECTED" \
|| die "could not connect to the phone" || die "could not connect to the phone"
say "writing boot.img to boot_a from inside Linux" say "writing boot.img to boot_a"
# shellcheck disable=SC2086 # shellcheck disable=SC2086
cat "$BOOT" | ssh $SSHOPTS "user@$PHONE" \ cat "$BOOT" | ssh $SSHOPTS "user@$PHONE" \
"$SUDO dd of=/dev/disk/by-partlabel/boot_a bs=1M conv=fsync status=none && sync && echo BOOT-WRITTEN" "$SUDO dd of=/dev/disk/by-partlabel/boot_a bs=1M conv=fsync status=none && sync && echo BOOT-WRITTEN"
say "verifying modem NV survived"
# shellcheck disable=SC2086 # shellcheck disable=SC2086
Z=$(ssh $SSHOPTS "user@$PHONE" \ Z=$(ssh $SSHOPTS "user@$PHONE" \
"$SUDO od -An -tx1 -N4096 /dev/disk/by-partlabel/modemst1 | sort -u | wc -l" 2>/dev/null || echo 0) "$SUDO od -An -tx1 -N4096 /dev/disk/by-partlabel/modemst1 | sort -u | wc -l" 2>/dev/null || echo 0)
@ -140,6 +149,6 @@ ssh $SSHOPTS -O exit "user@$PHONE" 2>/dev/null || true
cat <<'EOF' cat <<'EOF'
DONE. The phone reboots into postmarketOS from its own boot partition. DONE. The phone reboots into postmarketOS from its own boot partition.
Log in as user / 147147 (change it!). For VoLTE, write your carrier's Log in as user / 147147. For VoLTE, write your carrier's
P-CSCF into /etc/imsd.env and restart imsd - see the README. P-CSCF into /etc/imsd.env and restart imsd - see the README.
EOF EOF