Initial commit

This commit is contained in:
macmpi 2022-07-09 14:34:58 +02:00
parent 225aa62795
commit 292f29ed8d
19 changed files with 294 additions and 2 deletions

View File

@ -1,2 +1,44 @@
# alpine-linux-headless-bootstrap # Deploy Alpine Linux on a headless box
Headless Alpine Linux deployment scripts
The [Alpine Linux documentation](https://docs.alpinelinux.org/user-handbook/0.1a/Installing/setup_alpine.html) assumes one can interract with system directly with a keyboard & display.\
However, there are many cases where one might want to deploy a headless system, only available via a network connection (ethernet, wifi or as USB ethernet gadget).
This repo provides an overaly file headless system can boot with (leveraging Alpine distro's `initramfs` feature): it enables basic ssh server to log-into from another Computer in order to finalize system set-up.
## Install procedure:
Please follow [Alpine Linux Wiki](https://wiki.alpinelinux.org/wiki/Installation#Installation_Overview) to download & create installation media for chosen platform.\
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) overlay file at the root of Alpine Linux boot media (or onto any writeable side-media) and boot the box !
With default network interface definitions (and optional wifi SSID/pass file), one may then access the system under `ssh` with:\
`ssh root@<IP>` (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 after setup!).\
From there, system install can be fine-tuned as usual with `setup-alpine` for instance (check wiki for details).
Optional files can be added next to `headless.apkovl.tar.gz` to customise setup (sample files are provided):
- `wpa_supplicant.conf`: define wifi SSID & password (mandatory for wifi usecase).
- `interfaces`: define network interfaces at will, if [defaults](https://github.com/macmpi/alpine-linux-headless-bootstrap/blob/main/overlay/etc/local.d/headless.start#L26-L64) (DCHP-based) are not suitable.
- `unattended.sh`: make custom automated deployment script to further tune setup automatically (backgrounded).
*Note:* these files are linux text files: Windows/macOS users need to use text editors supporting linux text line-ending (such as [notepad++](https://notepad-plus-plus.org/), BBEdit or any other).
Main steps are logged in `/var/log/messages`.
## How to customize further ?
This repository may be forked/cloned/downloaded.\
Main script file is [`headless.start`](https://github.com/macmpi/alpine-linux-headless-bootstrap/blob/main/overlay/etc/local.d/headless.start).\
Execute `./make.sh` to rebuild `headless.apkovl.tar.gz`.
*Side note:* one nicety for bootstrapping PiZero devices or similar which can support USB ethernet gadget networking.\
Just add `dtoverlay=dwc2` in `config.txt`, and plug-in USB to Computer port.\
With Computer set-up to share networking with USB interface, device will appear at 10.42.0.2 onto Computer's subnet to log into !...
## Credits
Thanks for the original instructions & scripts from @sodface and @davidmytton.

BIN
headless.apkovl.tar.gz Normal file

Binary file not shown.

4
make.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
chmod +x overlay/etc/local.d/headless.start
tar czvf headless.apkovl.tar.gz -C overlay etc --owner=0 --group=0

View File

View File

@ -0,0 +1,124 @@
#!/bin/sh
# Redirect stdout and errors to console as rc.local does not log anything
exec 1>/dev/console 2>&1
mkdir /tmp/.trash
ovlpath=$( find /media -type f -name *.apkovl.tar.gz -exec dirname {} \; | head -1 )
## Setup Network interfaces
if [ -f "${ovlpath}/wpa_supplicant.conf" ]; then
logger -st ${0##*/} "Wifi setup found !"
apk add wpa_supplicant
cp "${ovlpath}/wpa_supplicant.conf" /etc/wpa_supplicant/wpa_supplicant.conf
rc-service wpa_supplicant start
else
logger -st ${0##*/} "Wifi setup not found !"
fi
if ! cp "${ovlpath}/interfaces" /etc/network/interfaces; then
# set default interfaces if not specified by interface file on boot storage
logger -st ${0##*/} "No interfaces file supplied, building default interfaces..."
for dev in $(ls /sys/class/net)
do
case ${dev%%[0-9]*} in
lo)
cat <<-EOF >> /etc/network/interfaces
auto $dev
iface $dev inet loopback
EOF
;;
eth)
cat <<-EOF >> /etc/network/interfaces
auto $dev
iface $dev inet dhcp
hostname localhost
EOF
;;
wlan)
[ -f /etc/wpa_supplicant/wpa_supplicant.conf ] && cat <<-EOF >> /etc/network/interfaces
auto $dev
iface $dev inet dhcp
hostname localhost
EOF
;;
usb)
cat <<-EOF >> /etc/network/interfaces
auto $dev
iface $dev inet static
address 10.42.0.2/24
gateway 10.42.0.1
hostname localhost
EOF
cat <<-EOF > /etc/resolv.conf
nameserver 208.67.222.222
nameserver 208.67.220.220
EOF
;;
esac
done
fi
echo "Using following network interfaces:"
cat /etc/network/interfaces
rc-service networking start
## Setup temporary SSH server (root login, no password)
## we use some bundled keys to avoid generation at boot and save time
## bundled temporary keys are moved in /tmp so they won't be stored
## within permanent config later (new ones will then be generated)
apk add openssh
mv /etc/ssh/ssh_host_* /tmp/.trash/.
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.orig
cat <<-EOF >> /etc/ssh/sshd_config
AuthenticationMethods none
PermitEmptyPasswords yes
PermitRootLogin yes
HostKey /tmp/.trash/ssh_host_dsa_key
HostKey /tmp/.trash/ssh_host_ecdsa_key
HostKey /tmp/.trash/ssh_host_ed25519_key
HostKey /tmp/.trash/ssh_host_rsa_key
EOF
cp /etc/conf.d/sshd /etc/conf.d/sshd.orig
cat <<-EOF >> /etc/conf.d/sshd
sshd_disable_keygen=yes
EOF
rc-service sshd start
if [ -f "${ovlpath}/unattended.sh" ]; then
install -m755 "${ovlpath}/unattended.sh" /tmp/unattended.sh
/tmp/unattended.sh >/dev/console 2>&1 &
logger -st ${0##*/} "/tmp/unattended.sh script launched in the background with PID $!"
fi
## Prep for final post-cleanup
cat <<-EOF > /tmp/.trash/post-cleanup
#!/bin/sh
logger -st ${0##*/} "Cleaning-up..."
mv /etc/ssh/sshd_config.orig /etc/ssh/sshd_config
mv /etc/conf.d/sshd.orig /etc/conf.d/sshd
rm /etc/modules-load.d/g_ether.conf
rm /etc/modprobe.d/g_ether.conf
rc-update del local default
rm /etc/local.d/headless.start
logger -st ${0##*/} "Done !!"
EOF
chmod +x /tmp/.trash/post-cleanup
exec /tmp/.trash/post-cleanup

View File

@ -0,0 +1,3 @@
# added to support USB-Ethernet gadget mode at boot for Pi devices
options g_ether dev_addr=ea:64:2f:e8:19:94 host_addr=f6:67:ce:b3:c0:ea

View File

@ -0,0 +1,6 @@
# added to support USB-Ethernet gadget mode at boot for Pi devices
# also requires dtoverlay=dwc2 is added to usercfg.txt or config.txt
dwc2
g_ether

View File

@ -0,0 +1 @@
/etc/init.d/local

View File

@ -0,0 +1,21 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsQAAAAdzc2gtZH
NzAAAAgQDHKXTtPOsM86zrYXbYx4JpmRlxIipjm1H2ce8YyTWJj3es/rjMXN3bB3LOuXWB
20XzwU8Z/cIOyhzWixsucU60bmiP7y+lR1m9bqYD+GftcmJJD4A5kpz1laivGqRNhpfYrN
TAe7+jGNi7xh80O91L3ScCQArZJdhhNAa9HosV/QAAABUAlZem7iptLcndvpXz3Gj1MXYY
bN0AAACASzMGzrARwRQB1KPxjrwVXVoPi5QGH3bnziaWMiKXxVu2br5lkqu57unXUHX1ec
r3emUbghGQdQmk8ERnxYokbKHihsHoYBY4GYPRuz6WI52PcHFwaw2ceLjCASEJVgzNdn/K
PNS1Qx68XvTwt7+F1ZlRKnG2aIZA+PqpeUCU/IcAAACAdb1dRX6MNPoim9e4JIRVc8QZXs
UNJt0BhzHMMLRBokuqHEsEdOm7sw2uKyh7NlmmbaLH2AcI9B1+XeeK4lxsZpy+D2F1fwV9
X2aQ27oa2p7U/mNmTdKySYuYauLJCZQrfkDcAXi9QWkJzloy/PsRnftCUUj2jM9AAPbEy5
gz5TMAAAHoLcg8tS3IPLUAAAAHc3NoLWRzcwAAAIEAxyl07TzrDPOs62F22MeCaZkZcSIq
Y5tR9nHvGMk1iY93rP64zFzd2wdyzrl1gdtF88FPGf3CDsoc1osbLnFOtG5oj+8vpUdZvW
6mA/hn7XJiSQ+AOZKc9ZWorxqkTYaX2KzUwHu/oxjYu8YfNDvdS90nAkAK2SXYYTQGvR6L
Ff0AAAAVAJWXpu4qbS3J3b6V89xo9TF2GGzdAAAAgEszBs6wEcEUAdSj8Y68FV1aD4uUBh
92584mljIil8Vbtm6+ZZKrue7p11B19XnK93plG4IRkHUJpPBEZ8WKJGyh4obB6GAWOBmD
0bs+liOdj3BxcGsNnHi4wgEhCVYMzXZ/yjzUtUMevF708Le/hdWZUSpxtmiGQPj6qXlAlP
yHAAAAgHW9XUV+jDT6IpvXuCSEVXPEGV7FDSbdAYcxzDC0QaJLqhxLBHTpu7MNrisoezZZ
pm2ix9gHCPQdfl3niuJcbGacvg9hdX8FfV9mkNu6Gtqe1P5jZk3SskmLmGriyQmUK35A3A
F4vUFpCc5aMvz7EZ37QlFI9ozPQAD2xMuYM+UzAAAAFBiKoHh90r3tzH+wk9EBRTiMCE3d
AAAADnJvb3RAbG9jYWxob3N0AQIDBAU=
-----END OPENSSH PRIVATE KEY-----

View File

@ -0,0 +1 @@
ssh-dss AAAAB3NzaC1kc3MAAACBAMcpdO086wzzrOthdtjHgmmZGXEiKmObUfZx7xjJNYmPd6z+uMxc3dsHcs65dYHbRfPBTxn9wg7KHNaLGy5xTrRuaI/vL6VHWb1upgP4Z+1yYkkPgDmSnPWVqK8apE2Gl9is1MB7v6MY2LvGHzQ73UvdJwJACtkl2GE0Br0eixX9AAAAFQCVl6buKm0tyd2+lfPcaPUxdhhs3QAAAIBLMwbOsBHBFAHUo/GOvBVdWg+LlAYfdufOJpYyIpfFW7ZuvmWSq7nu6ddQdfV5yvd6ZRuCEZB1CaTwRGfFiiRsoeKGwehgFjgZg9G7PpYjnY9wcXBrDZx4uMIBIQlWDM12f8o81LVDHrxe9PC3v4XVmVEqcbZohkD4+ql5QJT8hwAAAIB1vV1Ffow0+iKb17gkhFVzxBlexQ0m3QGHMcwwtEGiS6ocSwR06buzDa4rKHs2WaZtosfYBwj0HX5d54riXGxmnL4PYXV/BX1fZpDbuhrantT+Y2ZN0rJJi5hq4skJlCt+QNwBeL1BaQnOWjL8+xGd+0JRSPaMz0AA9sTLmDPlMw== root@localhost

View File

@ -0,0 +1,9 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQQAo6TcIAgnFGCX0HJbqFtwEa/H+NQ1
gQpZf9+gKJcWCNIGkGdSgerERbqx3anjEDKvwzlPrwSaaF0gMSRg/2yfAAAAqLTc/Ou03P
zrAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBACjpNwgCCcUYJfQ
cluoW3ARr8f41DWBCll/36AolxYI0gaQZ1KB6sRFurHdqeMQMq/DOU+vBJpoXSAxJGD/bJ
8AAAAhAJ2Ka8kkJQcRGROSTPW+PBY6hM8K3CUhZsN34HMHVXxTAAAADnJvb3RAbG9jYWxo
b3N0AQ==
-----END OPENSSH PRIVATE KEY-----

View File

@ -0,0 +1 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBACjpNwgCCcUYJfQcluoW3ARr8f41DWBCll/36AolxYI0gaQZ1KB6sRFurHdqeMQMq/DOU+vBJpoXSAxJGD/bJ8= root@localhost

View File

@ -0,0 +1,7 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACCF1PEIbFPSWF5xRx3uqY+AcSgwKn3t8S/jLV3unTJWLgAAAJjeHXU03h11
NAAAAAtzc2gtZWQyNTUxOQAAACCF1PEIbFPSWF5xRx3uqY+AcSgwKn3t8S/jLV3unTJWLg
AAAEBf0MGN5wVf2zA5llczr1s/rZQZgxEC45vUpqMkBGSkW4XU8QhsU9JYXnFHHe6pj4Bx
KDAqfe3xL+MtXe6dMlYuAAAADnJvb3RAbG9jYWxob3N0AQIDBAUGBw==
-----END OPENSSH PRIVATE KEY-----

View File

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIXU8QhsU9JYXnFHHe6pj4BxKDAqfe3xL+MtXe6dMlYu root@localhost

View File

@ -0,0 +1,38 @@
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----

View File

@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDS3eKGoDAB5ZuVtj17zzmwl8MLQSjVshc4ZoF9JGdpEtT6UPV5SG0RFW7j11n6knJPFlZ59druNTy6eBPGTS7E5tofZAuNzD5mpbkcPK6xiGOkhIlYghCnDeKKZzbyZ5aXE91wTVhaCuy5fVV4uY3Q3n9Ew5Wrpb8Ty7lj+zbo9qeMZMLwEKABoATQfrdzD4/NmiMMAWgpeEcghFUt2x3oLn4nsFPxV/m8uwHZ1jzglhIuae89cWAu2xnqgncwUehEXIRJdnwMFJN7xqdZj96KCkAdAVFe9FsLZy1XXII90yOvA2IqFqDabhWPMQ4gypgxdITm+LqgYYyukj8eD47nf3ROXR7MjIzJ/xrRBymu0v8FUkRC2oMjY4c4gCoDFK6bbZp9h6VxydC2ohr+BEVTsZ4BPW7UlycuBQl+N3LQ618Yag7eEJ3l6tGInE2X15ptvNOAsYDtpaH0FQ+EV77VHmPrDksz1xc5UU4tUIQZ9Kp19VqTSNgSN4oICnmJQCE= root@localhost

19
sample_interfaces Normal file
View File

@ -0,0 +1,19 @@
# Sample network interfaces file
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp
hostname localhost
auto wlan0
iface wlan0 inet dhcp
hostname localhost
auto usb0
iface usb0 inet static
address 10.42.0.2/24
gateway 10.42.0.1
hostname localhost

6
sample_unattended.sh Normal file
View File

@ -0,0 +1,6 @@
#/bin/sh
echo hello world !!
sleep 60
logger -st ${0##*/} "Finished unattended script"

View File

@ -0,0 +1,8 @@
# Sample wpa_supplicant.conf
country=FR
network={
key_mgmt=WPA-PSK
ssid="mySSID"
psk="myPassPhrase"
}