fix(nix-on-droid): fiabilise l'auto-réparation (wake-lock borné, retries sshd, watchdog 2 min, precmd auto-réparation, alias up, phone-update)

This commit is contained in:
Hermes Agent
2026-11-03 01:21:45 -05:00
parent b8b657a366
commit 4b98a6e013
+66 -34
View File
@@ -5,10 +5,16 @@
#
# - sshd local (port 8023, clé hermes@tower autorisée, sftp) ;
# - `phone-tunnel-loop` : boucle `ssh -R 127.0.0.1:2224:127.0.0.1:8023 root@marcpartensky.com` ;
# - `phone-up` : démarrage idempotent (sshd + tunnel + wake-lock), accroché à chaque
# session via ~/.zprofile, ~/.zshrc, ~/.profile et ~/.bashrc ;
# - `phone-watchdog` : rejoue `phone-up` toutes les 5 min (filet de sécurité) ;
# - `phone-status` : diagnostic (pids + logs).
# - `phone-up` : démarrage idempotent (sshd + tunnel + watchdog + wake-lock borné),
# accroché à chaque session (.zprofile/.zshrc/.profile/.bashrc) ET à chaque prompt
# zsh (precmd rate-limité 60s : n'importe quelle touche dans l'app répare) ;
# - `phone-watchdog` : rejoue `phone-up` toutes les 2 min (filet de sécurité) ;
# - `phone-update` : met à jour la conf (switch nix-on-droid, tarball-ttl 0) ;
# - `phone-status` : diagnostic (verdicts + pids + logs).
#
# IMPORTANT (fiabilité Xiaomi/HyperOS) : accorder à l'app Nix la permission
# « Afficher des fenêtres pop-up en arrière-plan » (display over other apps),
# sinon le wake-lock échoue et MIUI tue les process d'arrière-plan.
#
# La clé privée du tunnel vit uniquement sur le tel (~/.ssh/relay_ed25519), jamais ici.
# Côté rack, l'entrée restreinte :
@@ -72,16 +78,33 @@ let
exec 9>"$lock" || exit 0
if [ -x "$flock" ]; then "$flock" -n 9 || exit 0; fi
# 1) sshd
if [ -f ${sshdDir}/sshd.pid ] && kill -0 "$($core/cat ${sshdDir}/sshd.pid)" 2>/dev/null; then
alive() {
[ -f "$1" ] && kill -0 "$($core/cat "$1" 2>/dev/null)" 2>/dev/null
}
# 1) sshd (retries : le demarrage peut echouer sur un port encore occupe)
if alive ${sshdDir}/sshd.pid; then
:
else
$core/rm -f ${sshdDir}/sshd.pid
${pkgs.openssh}/bin/sshd -f ${sshdDir}/sshd_config >> ${sshdDir}/up.log 2>&1 || true
n=0
while [ "$n" -lt 3 ]; do
n=$((n + 1))
${pkgs.openssh}/bin/sshd -f ${sshdDir}/sshd_config >> ${sshdDir}/up.log 2>&1
$core/sleep 1
if alive ${sshdDir}/sshd.pid; then
echo "[up $(date 2>/dev/null)] sshd demarre (essai $n)" >> ${sshdDir}/up.log
break
fi
$core/sleep 2
done
if ! alive ${sshdDir}/sshd.pid; then
echo "[up $(date 2>/dev/null)] ECHEC sshd apres 3 essais" >> ${sshdDir}/up.log
fi
fi
# 2) tunnel inverse (nécessite la clé posée au bootstrap)
if [ -f ${sshdDir}/tunnel.pid ] && kill -0 "$($core/cat ${sshdDir}/tunnel.pid)" 2>/dev/null; then
if alive ${sshdDir}/tunnel.pid; then
:
elif [ -f ${relayKey} ]; then
$core/rm -f ${sshdDir}/tunnel.pid
@@ -89,48 +112,53 @@ let
echo $! > ${sshdDir}/tunnel.pid
fi
# 3) wake lock (anti-gel Android ; demande la permission "superposition d'écran")
wl=/nix/var/nix/profiles/nix-on-droid/nix-on-droid-path/bin/termux-wake-lock
if [ -x "$wl" ]; then
"$wl" || true
fi
# 4) watchdog : rejoue phone-up toutes les 5 min (relance ce qui est mort)
wd=${sshdDir}/watchdog.pid
if [ -f "$wd" ] && kill -0 "$($core/cat "$wd")" 2>/dev/null; then
# 3) watchdog : rejoue phone-up en boucle (relance ce qui est mort)
if alive ${sshdDir}/watchdog.pid; then
:
else
$core/rm -f "$wd"
$core/rm -f ${sshdDir}/watchdog.pid
$core/nohup ${phoneWatchdog}/bin/phone-watchdog >> ${sshdDir}/watchdog.log 2>&1 &
echo $! > "$wd"
echo $! > ${sshdDir}/watchdog.pid
fi
# 4) wake lock (anti-veille Android ; permission « fenêtres pop-up » requise),
# borné par timeout et en dernier : ne doit JAMAIS bloquer up.lock.
wl=/nix/var/nix/profiles/nix-on-droid/nix-on-droid-path/bin/termux-wake-lock
if [ -x "$wl" ]; then
$core/timeout 8 "$wl" >/dev/null 2>&1 || true
fi
'';
phoneWatchdog = pkgs.writeScriptBin "phone-watchdog" ''
#!${pkgs.runtimeShell}
while true; do
${pkgs.coreutils}/bin/sleep 300
${pkgs.coreutils}/bin/sleep 120
/nix/var/nix/profiles/nix-on-droid/nix-on-droid-path/bin/phone-up || true
done
'';
phoneUpdate = pkgs.writeScriptBin "phone-update" ''
#!${pkgs.runtimeShell}
export PATH=/nix/var/nix/profiles/nix-on-droid/nix-on-droid-path/bin:$PATH
cd ${home}
exec nix-on-droid switch --flake "git+https://github.com/MarcPartensky/nixos" --option tarball-ttl 0
'';
phoneStatus = pkgs.writeScriptBin "phone-status" ''
#!${pkgs.runtimeShell}
echo "== sshd"
if [ -f ${sshdDir}/sshd.pid ]; then
${pkgs.procps}/bin/ps -p "$(cat ${sshdDir}/sshd.pid)" -o pid,etime,args || true
else
echo "no pidfile"
fi
echo "== tunnel"
if [ -f ${sshdDir}/tunnel.pid ]; then
${pkgs.procps}/bin/ps -p "$(cat ${sshdDir}/tunnel.pid)" -o pid,etime,args || true
else
echo "no pidfile"
fi
echo "== tunnel.log"
check() {
if [ -f "$2" ] && kill -0 "$(cat "$2" 2>/dev/null)" 2>/dev/null; then
echo "$1: UP (pid $(cat "$2"))"
else
echo "$1: DOWN"
fi
}
check sshd ${sshdDir}/sshd.pid
check tunnel ${sshdDir}/tunnel.pid
check watchdog ${sshdDir}/watchdog.pid
echo "== tunnel.log (5 dernieres lignes)"
${pkgs.coreutils}/bin/tail -n 5 ${sshdDir}/tunnel.log 2>/dev/null || true
echo "== up.log"
echo "== up.log (5 dernieres lignes)"
${pkgs.coreutils}/bin/tail -n 5 ${sshdDir}/up.log 2>/dev/null || true
'';
in
@@ -142,6 +170,7 @@ in
tunnelLoop # référencés ici -> installés sur le tel
phoneUp
phoneWatchdog
phoneUpdate
phoneStatus
];
@@ -184,6 +213,9 @@ in
printf '\n# nod-phone-autostart2\nif [ -x /nix/var/nix/profiles/nix-on-droid/nix-on-droid-path/bin/phone-up ]; then /nix/var/nix/profiles/nix-on-droid/nix-on-droid-path/bin/phone-up >/dev/null 2>&1 || true; fi\n' >> "$f"
fi
done
if ! grep -q nod-phone-autorepair3 ${home}/.zshrc 2>/dev/null; then
printf '\n# nod-phone-autorepair3\nalias up="phone-up"\n_nod_autorepair() {\n local p=/nix/var/nix/profiles/nix-on-droid/nix-on-droid-path/bin/phone-up\n [ -x "$p" ] || return 0\n local s="$HOME/sshd/.up-stamp" now last\n now=$(date +%s 2>/dev/null) || return 0\n last=0\n [ -f "$s" ] && last=$(stat -c %%Y "$s" 2>/dev/null || echo 0)\n if [ "$((now - last))" -gt 60 ]; then\n : > "$s"\n ( "$p" >/dev/null 2>&1 & )\n fi\n}\nprecmd_functions+=(_nod_autorepair)\n' >> ${home}/.zshrc
fi
fi
'';
};