#!/usr/bin/env bash # deploy-secrets-phone.sh — make souveraine-secrets the Pixel 3's Secret # Service, replacing gnome-keyring's secrets component. # # Idempotent: every step converges to the same state fresh or re-run. The # binary is cross-built on archdev (never this laptop) by # SOUVERAINE_AARCH64_SYSROOT=~/aarch64-sysroot ./scripts/build-cross.sh \ # --features secrets --bin souveraine-secrets # and pulled from there unless SECRETS_BIN points at a local copy. # # What "replace" means here, precisely: # * our binary in /usr/local/bin, our user unit in /etc/systemd/user, # enabled at default.target — the name is claimed at login, before any # client asks; # * a D-Bus activation file in /usr/local/share/dbus-1/services shadows # gnome-keyring's copy in /usr/share (XDG_DATA_DIRS order, verified on # the phone) for on-demand activation; # * gnome-keyring-daemon.{service,socket} masked, its autostart entries # hidden per-user — pacman-owned files in /usr/share are never touched, # so a gnome-keyring package upgrade cannot resurrect it. # # Verified at the end with a live secret-tool round-trip against the running # provider; the script fails loudly if the name is owned by anything else. set -euo pipefail cd "$(dirname "$0")/.." SSH=(ssh -F /dev/null -i "$HOME/.ssh/ani" -o BatchMode=yes -o ConnectTimeout=5) SCP=(scp -F /dev/null -i "$HOME/.ssh/ani" -o BatchMode=yes) USB_IP=172.16.42.1 WIFI_IP=10.10.20.154 ARCHDEV="${ARCHDEV:-casey@10.10.20.123}" ARCHDEV_BIN="Projects/souveraine/target/aarch64-unknown-linux-gnu/release/souveraine-secrets" LOCAL_CACHE="target/phone/souveraine-secrets" # --- binary: pull the archdev cross-build unless one was handed to us --- BIN="${SECRETS_BIN:-}" if [[ -z "$BIN" ]]; then mkdir -p "$(dirname "$LOCAL_CACHE")" echo "== pulling cross-built binary from $ARCHDEV ==" "${SCP[@]}" "$ARCHDEV:$ARCHDEV_BIN" "$LOCAL_CACHE" BIN="$LOCAL_CACHE" fi file "$BIN" | grep -q aarch64 || { echo "$BIN is not an aarch64 binary" >&2; exit 1; } # --- reach the phone --- ip="" for cand in "$USB_IP" "$WIFI_IP"; do if ping -c1 -W1 "$cand" >/dev/null 2>&1; then ip="$cand"; break; fi done [[ -n "$ip" ]] || { echo "phone unreachable (tried $USB_IP, $WIFI_IP)" >&2; exit 1; } PHONE="casey@$ip" echo "== phone: $ip ==" # --- ship binary + units --- "${SCP[@]}" "$BIN" "$PHONE:/tmp/souveraine-secrets-xdev" "${SCP[@]}" packaging/souveraine-secrets.service "$PHONE:/tmp/souveraine-secrets.service" "${SCP[@]}" packaging/org.freedesktop.secrets.service "$PHONE:/tmp/org.freedesktop.secrets.service" "${SSH[@]}" "$PHONE" 'bash -s' <<'EOF' set -euo pipefail sudo install -Dm755 /tmp/souveraine-secrets-xdev /usr/local/bin/souveraine-secrets sudo install -Dm644 /tmp/souveraine-secrets.service /etc/systemd/user/souveraine-secrets.service sudo install -Dm644 /tmp/org.freedesktop.secrets.service /usr/local/share/dbus-1/services/org.freedesktop.secrets.service rm -f /tmp/souveraine-secrets-xdev /tmp/souveraine-secrets.service /tmp/org.freedesktop.secrets.service # Retire gnome-keyring's secrets component: mask its units, hide its # autostart entries per-user. /usr/share stays pacman's. systemctl --user mask --now gnome-keyring-daemon.service gnome-keyring-daemon.socket >/dev/null 2>&1 || true mkdir -p ~/.config/autostart for entry in gnome-keyring-secrets gnome-keyring-pkcs11; do printf '[Desktop Entry]\nType=Application\nName=%s (disabled: souveraine-secrets is the provider)\nHidden=true\n' \ "$entry" > ~/.config/autostart/$entry.desktop done # Stop any live gnome-keyring instances (dbus-activated transients included). systemctl --user stop 'dbus-:*org.freedesktop.secrets*' >/dev/null 2>&1 || true pkill -u "$(id -u)" -f gnome-keyring-daemon >/dev/null 2>&1 || true systemctl --user daemon-reload systemctl --user enable souveraine-secrets.service >/dev/null systemctl --user restart souveraine-secrets.service # --- verify: name ownership --- sleep 1 owner_pid=$(busctl --user status org.freedesktop.secrets 2>/dev/null | awk -F= '/^PID=/{print $2}') # /proc//comm truncates to 15 chars → "souveraine-secr" owner_comm=$(cat /proc/"$owner_pid"/comm 2>/dev/null || echo unknown) if [[ "$owner_comm" != souveraine-secr* ]]; then echo "FAIL: org.freedesktop.secrets is owned by '$owner_comm' (pid $owner_pid), not souveraine-secrets" >&2 systemctl --user status souveraine-secrets.service --no-pager | tail -20 >&2 exit 1 fi echo "== org.freedesktop.secrets owned by $owner_comm (pid $owner_pid) ==" # --- verify: live round-trip through the standard client --- printf 'deploy-probe' | secret-tool store --label='souveraine deploy probe' app souveraine-deploy probe roundtrip got=$(secret-tool lookup app souveraine-deploy probe roundtrip) if [[ "$got" != "deploy-probe" ]]; then echo "FAIL: secret-tool round-trip returned '$got'" >&2 exit 1 fi secret-tool clear app souveraine-deploy probe roundtrip echo "== secret-tool round-trip OK ==" EOF echo "== deployed: souveraine-secrets is the phone's Secret Service =="