diff --git a/README.md b/README.md index 23476e0..ff87050 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Deploy Alpine Linux on a headless system [Alpine Linux documentation](https://docs.alpinelinux.org/user-handbook/0.1a/Installing/setup_alpine.html) assumes **initial setup** is carried-out on a system with a keyboard & display to interract with.\ -However, there are many cases where one might want to deploy a headless system, only available through a network connection (ethernet, wifi or as USB ethernet gadget). +However, in many cases one might want to deploy a headless system that is only available through a network connection (ethernet, wifi or as USB ethernet gadget). This repo provides an **overlay file** to initially boot such headless system (leveraging Alpine distro's `initramfs` feature): it starts a basic ssh server to log-into from another Computer, in order to then perform actual system setup. @@ -11,25 +11,23 @@ Please follow [Alpine Linux Wiki](https://wiki.alpinelinux.org/wiki/Installation Tools provided here can be used on any plaform for any install modes (diskless, data disk, system disk). Just add [**headless.apkovl.tar.gz**](https://github.com/macmpi/alpine-linux-headless-bootstrap/raw/main/headless.apkovl.tar.gz)[^1] overlay file at the root of Alpine Linux boot media (or onto any custom side-media) and boot-up the system.\ -With default network interface definitions (and SSID/pass file if using wifi), system can then be accessed under `ssh` with: \ -`ssh root@`\ +With default network interface definitions (and SSID/pass file if using wifi), system can then be remotely accessed with: `ssh root@`\ (system IP address may be determined with any IP scanning tools such as `nmap`). As with Alpine Linux initial bring-up, `root` account has no password initially (change that during setup!).\ -From there, system install can be performed as usual with `setup-alpine` for instance (check [wiki](https://wiki.alpinelinux.org/wiki/Alpine_setup_scripts#setup-alpine) for details). +From there, actual system install can be performed as usual with `setup-alpine` for instance (check [wiki](https://wiki.alpinelinux.org/wiki/Alpine_setup_scripts#setup-alpine) for details). -Add-on files may be added next to `headless.apkovl.tar.gz` to customise boostrapping configuration (sample files are provided): +Extra files may be added next to `headless.apkovl.tar.gz` to customise boostrapping configuration (check sample files): - `wpa_supplicant.conf`[^2] (*mandatory for wifi usecase*): define wifi SSID & password. - `interfaces`[^2] (*optional*): define network interfaces at will, if defaults DCHP-based are not suitable. -- `ssh_host_*_key*` (*optional*): provide custom ssh keys to be injected (may be stored), instead of using bundled ones[^1] (not stored). +- `ssh_host_*_key*` (*optional*): provide custom ssh keys to be injected (may be stored), instead of using bundled ones[^1] (not stored). Providing an empty key file will trigger new keys generation (ssh server may take longer to start). - `unattended.sh`[^2] (*optional*): create custom automated deployment script to further tune & extend actual setup (backgrounded). **Goody:** seamless USB bootstrapping for PiZero devices (or similar supporting USB ethernet gadget networking):\ -Just add `dtoverlay=dwc2` in `usercfg.txt` (or `config.txt`), and plug-in USB cable to Computer port.\ -With Computer set-up to share networking with USB interface as 10.42.0.1 gateway, one can log into device from Computer with:\ -`ssh root@10.42.0.2` +Just add `dtoverlay=dwc2` in `usercfg.txt` (or `config.txt`), and plug USB cable into Computer port.\ +With Computer set-up to share networking with USB interface as 10.42.0.1 gateway, one can log into device from Computer with: `ssh root@10.42.0.2` Main execution steps are logged in `/var/log/messages`. diff --git a/headless.apkovl.tar.gz b/headless.apkovl.tar.gz index 802c8a8..8d78f9f 100644 Binary files a/headless.apkovl.tar.gz and b/headless.apkovl.tar.gz differ diff --git a/overlay/etc/local.d/headless.start b/overlay/etc/local.d/headless.start index e7c783e..ba671c6 100755 --- a/overlay/etc/local.d/headless.start +++ b/overlay/etc/local.d/headless.start @@ -82,7 +82,7 @@ rc-service networking start ## Setup temporary SSH server (root login, no password) -## we use some bundled or optionaly provided keys to avoid generation at boot and save time +## we use some bundled or optionaly provided keys to avoid generation at startup and save time apk add openssh cp /etc/ssh/sshd_config /etc/ssh/sshd_config.orig cp /etc/conf.d/sshd /etc/conf.d/sshd.orig @@ -94,22 +94,30 @@ cat <<-EOF >> /etc/ssh/sshd_config Banner /tmp/.trash/banner EOF -cat <<-EOF >> /etc/conf.d/sshd - sshd_disable_keygen=yes - EOF - -# banner file +# Banner file cat <<-EOF > /tmp/.trash/banner Alpine Linux headless bootstrap v$VERSION by macmpi EOF -# bundled temporary keys are moved in RAM /tmp so they won't be stored +# Bundled temporary keys are moved in RAM /tmp so they won't be stored # within permanent config later (new ones will then be generated) +KEYGEN_STANCE="sshd_disable_keygen=yes" mv /etc/ssh/ssh_host_*_key* /tmp/.trash/. -# inject optional custom keys (those might be stored) -if ! install -m600 "${ovlpath}"/ssh_host_*_key* /etc/ssh/; then + +# Inject optional custom keys (those might be stored) +if install -m600 "${ovlpath}"/ssh_host_*_key* /etc/ssh/; then + # check for empty key within injected ones: generate new keys if found + if find /etc/ssh/ -maxdepth 1 -type f -name 'ssh_host_*_key*' -empty | grep -q .; then + rm /etc/ssh/ssh_host_*_key* + KEYGEN_STANCE="" + logger -st ${0##*/} "Will generate new SSH keys..." + else + chmod 644 /etc/ssh/ssh_host_*_key.pub + logger -st ${0##*/} "Using injected SSH keys..." + fi +else logger -st ${0##*/} "Using bundled ssh keys from RAM..." cat <<-EOF >> /etc/ssh/sshd_config HostKey /tmp/.trash/ssh_host_ed25519_key @@ -117,6 +125,7 @@ if ! install -m600 "${ovlpath}"/ssh_host_*_key* /etc/ssh/; then EOF fi +echo "$KEYGEN_STANCE" >> /etc/conf.d/sshd rc-service sshd start ## Prep for final post-cleanup