Skip to content

Commit da41e11

Browse files
mrosseelclaude
andcommitted
fix: first-boot service waits for internet and retries on failure
Root cause: network-online.target was unreliable because NetworkManager-wait-online was disabled, so pifinder-first-boot ran before internet was available. - Add curl-based connectivity check with 5-minute retry loop - Add Restart=on-failure with 15s delay - Re-enable NetworkManager-wait-online (with 30s timeout) - Add sudo permissions for systemctl/journalctl (remote recovery) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent f5c7388 commit da41e11

1 file changed

Lines changed: 34 additions & 3 deletions

File tree

nixos/migration.nix

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ in {
1515
# Minimal system packages for migration troubleshooting
1616
# ---------------------------------------------------------------------------
1717
environment.systemPackages = with pkgs; [
18-
nano
18+
vim
1919
htop
2020
e2fsprogs
2121
dosfstools
@@ -117,11 +117,27 @@ in {
117117
Type = "oneshot";
118118
RemainAfterExit = true;
119119
TimeoutStartSec = "30min";
120+
Restart = "on-failure";
121+
RestartSec = "15s";
120122
};
121-
path = with pkgs; [ nix coreutils systemd ];
123+
path = with pkgs; [ nix coreutils systemd curl ];
122124
script = ''
123125
set -euo pipefail
124126
127+
# Wait for actual internet connectivity (network-online.target is unreliable)
128+
echo "Waiting for internet connectivity..."
129+
for i in $(seq 1 60); do
130+
if curl -sf --max-time 5 https://cache.nixos.org/nix-cache-info >/dev/null 2>&1; then
131+
echo "Internet available after ''${i} attempts"
132+
break
133+
fi
134+
if [ "$i" -eq 60 ]; then
135+
echo "ERROR: No internet after 5 minutes"
136+
exit 1
137+
fi
138+
sleep 5
139+
done
140+
125141
STORE_PATH=$(cat /var/lib/pifinder/first-boot-target)
126142
if [ -z "$STORE_PATH" ] || [[ "$STORE_PATH" != /nix/store/* ]]; then
127143
echo "ERROR: Invalid store path: $STORE_PATH"
@@ -158,6 +174,12 @@ in {
158174
if (action.id.indexOf("org.freedesktop.NetworkManager") == 0) {
159175
return polkit.Result.YES;
160176
}
177+
if (action.id == "org.freedesktop.login1.reboot" ||
178+
action.id == "org.freedesktop.login1.reboot-multiple-sessions" ||
179+
action.id == "org.freedesktop.login1.power-off" ||
180+
action.id == "org.freedesktop.login1.power-off-multiple-sessions") {
181+
return polkit.Result.YES;
182+
}
161183
}
162184
});
163185
'';
@@ -169,8 +191,14 @@ in {
169191
users = [ "pifinder" ];
170192
commands = [
171193
{ command = "/run/current-system/sw/bin/shutdown *"; options = [ "NOPASSWD" ]; }
194+
{ command = "/run/current-system/sw/bin/hostnamectl *"; options = [ "NOPASSWD" ]; }
172195
{ command = "/run/current-system/sw/bin/hostname *"; options = [ "NOPASSWD" ]; }
196+
{ command = "/run/current-system/sw/bin/avahi-set-host-name *"; options = [ "NOPASSWD" ]; }
173197
{ command = "/run/current-system/sw/bin/dmesg"; options = [ "NOPASSWD" ]; }
198+
{ command = "/run/current-system/sw/bin/systemctl restart pifinder-first-boot.service"; options = [ "NOPASSWD" ]; }
199+
{ command = "/run/current-system/sw/bin/systemctl restart pifinder*"; options = [ "NOPASSWD" ]; }
200+
{ command = "/run/current-system/sw/bin/systemctl status *"; options = [ "NOPASSWD" ]; }
201+
{ command = "/run/current-system/sw/bin/journalctl *"; options = [ "NOPASSWD" ]; }
174202
];
175203
}];
176204

@@ -245,7 +273,10 @@ in {
245273
};
246274
};
247275

248-
systemd.services.NetworkManager-wait-online.enable = false;
276+
# NetworkManager-wait-online adds ~10s to boot but is needed for
277+
# pifinder-first-boot to have internet. The first-boot script also has
278+
# its own connectivity retry loop as a fallback.
279+
systemd.services.NetworkManager-wait-online.serviceConfig.TimeoutStartSec = "30s";
249280

250281
system.stateVersion = "24.11";
251282
}; # config

0 commit comments

Comments
 (0)