Skip to content

Commit ae70313

Browse files
authored
Fix race condition causing sshd start failure during provisioning (#460)
* Fix race condition causing sshd start failure during provisioning * Run first-boot tasks via systemd so sshd never races with host-key regeneration. The old `rc.local` script ran after network.target, but in parallel with other regular system services, like ssh.service. Therefore, ssh.service often started (and restarted) while `/root/firstboot.sh` was deleting keys. cloud-init’s set-passwords module made this worse by restarting ssh mid-run. * Replace `rc.local` with a oneshot firstboot.service (delete keys, create new keys, reconfigure sysstat) that runs Before=ssh.service and leaves the `/root/firstboot_done` file as a marker. * Add a cloud-config.service drop-in so cloud-init's config stage waits for firstboot.service, and * Update walinuxagent.service to wait for firstboot.service, ensuring ssh keys have been regenerated. This guarantees sshd, cloud-init, and WALinuxAgent all start only after the first-boot tasks succeed. * Invoke firstboot script in firstboot.service * Move multiple firstboot commands back into a firstboot script in case we need to extend this in the future. * Use systemd's `ConditionFirstBoot` native option to ensure the script is only run on firstboot, which allows us to get rid of the file-based approach.
1 parent d7fe17e commit ae70313

8 files changed

Lines changed: 36 additions & 34 deletions

File tree

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
[Unit]
2-
ConditionPathExists=/root/firstboot_done
2+
Wants=firstboot.service
3+
After=firstboot.service

stemcell_builder/stages/base_ubuntu_firstboot/apply.sh

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ set -e
55
base_dir=$(readlink -nf $(dirname $0)/../..)
66
source $base_dir/lib/prelude_apply.bash
77

8-
cp $assets_dir/etc/rc.local $chroot/etc/rc.local
9-
cp $assets_dir/root/firstboot.sh $chroot/root/firstboot.sh
10-
chmod u+x "${chroot}/etc/rc.local"
11-
chmod 0755 $chroot/root/firstboot.sh
8+
install -D -m 0755 \
9+
$assets_dir/root/firstboot.sh \
10+
$chroot/root/firstboot.sh
11+
12+
install -D -m 0644 \
13+
$assets_dir/etc/systemd/system/firstboot.service \
14+
$chroot/etc/systemd/system/firstboot.service
15+
16+
run_in_chroot $chroot "systemctl enable firstboot.service"

stemcell_builder/stages/base_ubuntu_firstboot/assets/etc/rc.local

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[Unit]
2+
Description=Run first boot tasks
3+
ConditionFirstBoot=yes
4+
Before=ssh.service
5+
6+
[Service]
7+
Type=oneshot
8+
ExecStart=/root/firstboot.sh
9+
RemainAfterExit=yes
10+
11+
[Install]
12+
WantedBy=multi-user.target
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/bin/sh
2+
set -e
23

34
rm -f /etc/ssh/ssh_host*key*
5+
ssh-keygen -A -v
46

5-
dpkg-reconfigure -fnoninteractive -pcritical openssh-server
67
dpkg-reconfigure -fnoninteractive sysstat

stemcell_builder/stages/system_azure_init/apply.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,16 @@ cat > $chroot/etc/logrotate.d/waagent <<EOS
4646
}
4747
EOS
4848

49-
#setup cloud-init
49+
# Setup cloud-init
5050
rm $chroot/etc/cloud/*.cfg
5151
rm $chroot/etc/cloud/cloud.cfg.d/*.cfg
5252
cp -f $dir/assets/etc/cloud-init/cloud.cfg $chroot/etc/cloud/cloud.cfg
5353
cp -f $dir/assets/etc/cloud-init/*-*.cfg $chroot/etc/cloud/cloud.cfg.d/
5454

55+
# Ensures that cloud-init waits until host keys have been regenerated.
56+
mkdir -p $chroot/etc/systemd/system/cloud-config.service.d
57+
cp -f $dir/assets/etc/systemd/system/cloud-config.service.d/firstboot-blocker.conf \
58+
$chroot/etc/systemd/system/cloud-config.service.d/firstboot-blocker.conf
5559

5660
# this will append the following two relevant lines (plus a few commented out lines)
5761
# to the default-conf:
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[Unit]
2+
Wants=firstboot.service
3+
After=firstboot.service

stemcell_builder/stages/system_azure_init/assets/etc/waagent/walinuxagent.service

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,15 @@
77
[Unit]
88
Description=Azure Linux Agent
99

10-
After=network-online.target
11-
Wants=network-online.target ssh.service sshd-keygen.service
10+
# NON-DEFAULT: Must run after the firstboot.service, which regenerates the ssh keys
11+
After=firstboot.service network-online.target cloud-init.service
12+
Wants=network-online.target sshd.service sshd-keygen.service
1213

1314
ConditionFileIsExecutable=/usr/sbin/waagent
1415
ConditionPathExists=/etc/waagent.conf
1516

1617
[Service]
1718
Type=simple
18-
# stemcells on Azure re-generate the SSH Hostkey upon first reboot
19-
# waagent has to wait until the file was recreated
20-
ExecStartPre=/bin/bash -c "while [ ! -f /root/firstboot_done ]; do sleep 1; done"
2119
ExecStart=/usr/bin/python3 -u /usr/sbin/waagent -daemon
2220
Restart=always
2321
Slice=azure.slice

0 commit comments

Comments
 (0)