|
|
(19 intermediate revisions by 3 users not shown) |
Line 1: |
Line 1: |
| {{TOC right}}
| | This page documents an easy installation procedure for Alpine Linux on a headless host i.e a system without keyboard, mouse & display to interact with but otherwise available only through a network connection. Somebody has to insert the Install media and power up the headless host. This procedure applies to '''all''' platforms. |
|
| |
|
| {{Delete|Although most of the below is still valid, there's an effort in progress to consolidate and expand this functionality. See the latest script updates on [github.](https://github.com/macmpi/alpine-linux-headless-bootstrap) .}}
| | == Headless bootstrap overlay file == |
|
| |
|
| = Introduction =
| | The [https://github.com/macmpi/alpine-linux-headless-bootstrap Headless bootstrap] repo provides a ready-to-use overlay file to bootstrap a headless system. |
| This wiki describes a modified version of the original method I posted for [https://wiki.alpinelinux.org/wiki/Raspberry_Pi_-_Headless_Installation Headless installation on a Raspberry Pi.] While the original version worked for other architectures, like x86_64, it was targeted at and posted in the Raspberry Pi section since that was my primary focus at the time. Revisions to that page by other authors removed the mention of x86_64 altogether so this version will be more generally written in the hopes that it will be easier to find and that it's applicability will be clearer.
| |
|
| |
|
| Additionally, this version improves upon the original (in my opinion) by automatically logging in the root user and optionally running a shell script. This provides a means to perform unattended installations or other scripted tasks and does not require modification of the stock Alpine installation media / files.
| | While straightforward in default use-case, many optional settings and advanced modes are detailed on repo homepage (unattended installs scripting, secured logon, ssh keys configuration, gadget-modes, etc). |
|
| |
|
| The following functionality is provided: | | {{Note|The author of above repo macmpi also maintains a number of {{pkg|raspberrypi*|arch=|maintainer=macmpi}} packages for Alpine Linux.}} |
| * Automatic DHCP configuration of a network interface, either wired or wireless
| |
| * Automatic configuration of sshd with password-less root login enabled
| |
| * Automatic login of the root user on tty7
| |
| * Automatic script execution (optional) | |
|
| |
|
| This is accomplished by using an overlay file that Alpine extracts at boot. [http://www.sodface.com/repo/headless.apkovl.tar.gz Download a pre-built overlay file here.]
| | To Install Alpine Linux on a headless host, just add [https://github.com/macmpi/alpine-linux-headless-bootstrap headless.apkovl.tar.gz] overlay file as-is (along with optional config files) at the root of [[Create a Bootable Device|customizable boot device]], or of a side media. |
|
| |
|
| {{Note|The draft notice has been removed from the top of this page but additional testing is needed. Use at your own risk.}} | | If using wifi networking, create a file {{Path|wpa_supplicant.conf}} in the same location as follows:{{Cat|wpa_supplicant.conf|<nowiki>country=FR |
|
| |
|
| = Basic Use = | | network={ |
| For Alpine supported Raspberry Pi models:
| | key_mgmt=WPA-PSK |
| # Download the applicable [https://alpinelinux.org/downloads/ Alpine installation tarball] and extract it to an SD card formatted with a single FAT partition.
| | ssid="mySSID" |
| # Copy the [http://www.sodface.com/repo/headless.apkovl.tar.gz headless.apkovl.tar.gz] file to the root of the SD card.
| | psk="myPassPhrase" |
| # Optionally, create a file named '''wifi.txt''' in the root of the SD card. See below for file format.
| | }</nowiki>}} |
| # Optionally, create a file named '''unattended.sh''' in the root of the SD card. See below for an example.
| |
| # Boot the Pi with the SD card.
| |
|
| |
|
| For other architectures (tested on various x86_64 hardware and a Qemu VM)
| | Alternately, <code>wpa_passphrase</code> utility from {{pkg|wpa_supplicant}} package can be used to create the encrypted version of the above file as follows:{{Cmd|$ wpa_passphrase 'mySSID' 'myPassPhrase' > wpa_supplicant.conf}} |
| # Download the applicable [https://alpinelinux.org/downloads/ Alpine installation file] and write it to usb stick or other media as needed.
| | The above encrypted version of the {{Path|wpa_supplicant.conf}} file may be placed in the same location. |
| # Copy the [http://www.sodface.com/repo/headless.apkovl.tar.gz headless.apkovl.tar.gz] file to a second usb stick or other media separate from the installation media.
| |
| # Optionally, create a file named '''wifi.txt''' in the root of second media. See below for file format.
| |
| # Optionally, create a file named '''unattended.sh''' in the root of the second media. See below for an example.
| |
| # Boot the device with both the installation and the secondary media connected.
| |
|
| |
|
| For basic interactive ssh access, only the headless.apkovl.tar.gz file is required. The '''wifi.txt''' file can be omitted if wired ethernet is used. The '''unattended.sh''' file can be omitted.
| | Boot the system with the above setup: usual [[Installation#Installation_Step_Details|Installation steps]] can then be performed remotely using {{ic|ssh}} |
|
| |
|
| = Wifi Support =
| | To find the ip of your headless host, one may use the {{ic|nmap}} tool from {{pkg|nmap}} package as follows: {{Codeline|$ nmap -v -sn 192.168.1.0/24}} |
| Create a text file named '''wifi.txt''' with the SSID and Password on the first line of the file:
| |
|
| |
|
| <code>SSID Password</code>
| | == Alternative custom install media preparation steps== |
|
| |
|
| = Example Scripts =
| | A Custom install media for a headless host can be created using a [[Create a Bootable Device|customizable boot device]] as per the below process. |
| If a shell script named '''unattended.sh''' is found in the root of the same media that contains the [http://www.sodface.com/repo/headless.apkovl.tar.gz headless.apkovl.tar.gz] file, it will be executed (sourced) by the root user after the auto login occurs on tty7. This can be used to script the installation of Alpine to local disk for example. Note too, that since network is available, the '''unattended.sh''' script can also just fetch and execute another script from the local network or internet, if available.
| |
|
| |
|
| I've experimented with different installation scripts. The first is derived from the [https://gitlab.alpinelinux.org/alpine/alpine-conf/-/blob/master/setup-alpine.in setup-alpine] script. It skips the sshd and network interface setup scripts as they are already configured and running. Tested on a Raspberry Pi 4.
| | {{Note|Instead of [[Create a Bootable Device|customizable boot device]], if a read-only boot media is used, then storing the configs require either a separate storage media or server location.}} |
|
| |
|
| | * Booting the [[Create a Bootable Device|customizable boot device]] on some computer with a display and keyboard attached, or in a virtual machine, and doing an intermediate "diskless" setup of just the boot media (more details below), i.e. using the offical <code>[[Alpine_setup_scripts#setup-alpine|setup-alpine]]</code> to configure the system's network, possibly for dhcp if needed, a ssh server, and a login user. |
| | * Choosing "disks=none" for now, yet, configure to store configs on the customizable boot device. |
| | * Use <code>[[Alpine_local_backup|lbu commit]]</code> to store the configs as local backup. Then your completed setup, including its securely created own private keys, will readily get (re)loaded on every subsequent (headless) boot from your custom-build <code><hostname>.apkovl.tar.gz</code> stored on the customizable boot device. |
|
| |
|
| {{Cat|unattended.sh|
| | ==See also== |
| <nowiki>KEYMAPOPTS="us us"
| | * [[Create a Bootable Device|Customizable boot device page]] |
| HOSTNAMEOPTS="-n rpi4"
| | * [[Diskless Mode#Apkovl|Diskless page with information on apkovl]] |
| TIMEZONEOPTS="-z UTC"
| | * [[Alpine local backup]] |
| NTPOPTS="-c busybox"
| | * [https://github.com/macmpi/alpine-linux-headless-bootstrap/ Bootstrap Alpine Linux on a headless system] using pre-built <code>apkovl</code> overlay file. |
| APKREPOSOPTS="-r"
| |
| DISKOPTS="-m sys /dev/mmcblk0"
| |
| | |
| source /lib/libalpine.sh
| |
| setup-keymap ${KEYMAPOPTS}
| |
| setup-hostname ${HOSTNAMEOPTS}
| |
| setup-timezone ${TIMEZONEOPTS}
| |
| rc-update add networking boot
| |
| rc-update add urandom boot
| |
| for svc in acpid cron crond; do
| |
| if rc-service --exists $svc; then
| |
| rc-update add $svc
| |
| fi
| |
| done
| |
| rc-service hostname restart
| |
| _dn=$(sed -n \
| |
| -e '/^domain[[:space:]][[:space:]]*/{s///;s/\([^[:space:]]*\).*$/\1/;h;}' \
| |
| -e '/^search[[:space:]][[:space:]]*/{s///;s/\([^[:space:]]*\).*$/\1/;h;}' \
| |
| -e '${g;p;}' /etc/resolv.conf 2>/dev/null)
| |
| _hn=$(hostname)
| |
| _hn=${_hn%%.*}
| |
| sed -i -e "s/^127\.0\.0\.1.*/127.0.0.1\t${_hn}.${_dn:-$(get_fqdn my.domain)} ${_hn} localhost.localdomain localhost/" /etc/hosts
| |
| setup-ntp ${NTPOPTS}
| |
| sleep 3; date
| |
| setup-apkrepos ${APKREPOSOPTS}
| |
| modloop_media=$(find_modloop_media)
| |
| DO_UMOUNT=1 modloop_media=$modloop_media copy-modloop
| |
| yes | setup-disk -q ${DISKOPTS}
| |
| poweroff</nowiki>
| |
| }}
| |
| | |
| | |
| The next one creates an answer file and runs setup-alpine. Note that sshd and network interface setup are included this time, even though they are both already up. It seems to work but not without complaint. More experimentation is required.
| |
| | |
| | |
| {{Cat|unattended.sh|
| |
| <nowiki>cat <<-EOF > /root/answerfile
| |
| KEYMAPOPTS="us us"
| |
| HOSTNAMEOPTS="-n alpine-test"
| |
| TIMEZONEOPTS="-z UTC"
| |
| PROXYOPTS="none"
| |
| NTPOPTS="-c busybox"
| |
| APKREPOSOPTS="-r"
| |
| SSHDOPTS="-c openssh"
| |
| DISKOPTS="-m sys /dev/vda"
| |
| INTERFACESOPTS="auto lo
| |
| iface lo inet loopback
| |
| | |
| auto eth0
| |
| iface eth0 inet dhcp
| |
| "
| |
| empty_root_password="true"
| |
| EOF
| |
| | |
| yes | setup-alpine -f /root/answerfile</nowiki>
| |
| }}
| |
| | |
| | |
| The third is like the second except without the separate answer file and using cat to set the INTERFACEOPTS variable based on the interface currently in use.
| |
| | |
| | |
| {{Cat|unattended.sh|
| |
| <nowiki>set -a
| |
| | |
| KEYMAPOPTS="us us"
| |
| HOSTNAMEOPTS="-n alpine-test"
| |
| TIMEZONEOPTS="-z UTC"
| |
| PROXYOPTS="none"
| |
| NTPOPTS="-c busybox"
| |
| APKREPOSOPTS="-r"
| |
| SSHDOPTS="-c openssh"
| |
| DISKOPTS="-m sys /dev/mmcblk0"
| |
| INTERFACESOPTS=$(cat /etc/network/interfaces)
| |
| empty_root_password="true"
| |
| | |
| yes | setup-alpine</nowiki>
| |
| }}
| |
| | |
| | |
| The above scripts need to be improved, tested, and tailored for your own use. Edits welcome!
| |
| | |
| = Overlay File Reference =
| |
| | |
| The [http://www.sodface.com/repo/headless.apkovl.tar.gz headless.apkovl.tar.gz] file has the following structure:
| |
| | |
| {{Cmd|└── etc
| |
| ├── .default_boot_services
| |
| ├── local.d
| |
| │ └── headless.start
| |
| └── runlevels
| |
| └── default
| |
| └── local -> /etc/init.d/local
| |
| }}
| |
| | |
| | |
| | |
| {{Cat|headless.start|
| |
| <nowiki>#!/bin/sh | |
| | |
| # Configure network
| |
| ovlpath=$(find /media -name *.apkovl.tar.gz -exec dirname {} \;)
| |
| read ssid psk < "${ovlpath}/wifi.txt"
| |
| | |
| if [ ${ssid} ]
| |
| then
| |
| for dev in /sys/class/net/*
| |
| do
| |
| if [ -e "${dev}"/wireless -o -e "${dev}"/phy80211 ]
| |
| then
| |
| iface="${dev##*/}"
| |
| fi
| |
| done
| |
| apk add wpa_supplicant
| |
| | |
| cat <<-EOF > /etc/wpa_supplicant/wpa_supplicant.conf
| |
| ap_scan=1
| |
| autoscan=periodic:10
| |
| disable_scan_offload=1
| |
| network={
| |
| ssid="${ssid}"
| |
| psk="${psk}"
| |
| }
| |
| EOF
| |
| | |
| rc-service wpa_supplicant start
| |
| else
| |
| iface="eth0"
| |
| fi
| |
| | |
| cat <<-EOF > /etc/network/interfaces
| |
| auto lo
| |
| iface lo inet loopback
| |
| | |
| auto ${iface}
| |
| iface ${iface} inet dhcp
| |
| EOF
| |
| | |
| rc-service networking start
| |
|
| |
| # Enable sshd
| |
| setup-sshd -c openssh
| |
| cp /etc/ssh/sshd_config /etc/ssh/sshd_config.orig
| |
| echo "PermitEmptyPasswords yes" >> /etc/ssh/sshd_config
| |
| echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
| |
| rc-service sshd restart
| |
| mv /etc/ssh/sshd_config.orig /etc/ssh/sshd_config
| |
| | |
| # Clean up
| |
| rc-update del local
| |
| rm /etc/local.d/headless.start
| |
|
| |
| # Login root
| |
| cat <<-EOF > /root/.profile
| |
| rm -f /root/.profile
| |
| if [ -e ${ovlpath}/unattended.sh ] && [ \$(tty) = /dev/tty7 ]
| |
| then
| |
| tmpfile="\$(mktemp)"
| |
| cp "${ovlpath}/unattended.sh" "\${tmpfile}"
| |
| source "\${tmpfile}"
| |
| fi
| |
| EOF
| |
| | |
| openvt -s -c 7 -- /bin/login -f root</nowiki>
| |
| }}
| |
|
| |
|
| [[Category:Installation]] | | [[Category:Installation]] |
This page documents an easy installation procedure for Alpine Linux on a headless host i.e a system without keyboard, mouse & display to interact with but otherwise available only through a network connection. Somebody has to insert the Install media and power up the headless host. This procedure applies to all platforms.
Headless bootstrap overlay file
The Headless bootstrap repo provides a ready-to-use overlay file to bootstrap a headless system.
While straightforward in default use-case, many optional settings and advanced modes are detailed on repo homepage (unattended installs scripting, secured logon, ssh keys configuration, gadget-modes, etc).
Note: The author of above repo macmpi also maintains a number of raspberrypi* packages for Alpine Linux.
To Install Alpine Linux on a headless host, just add headless.apkovl.tar.gz overlay file as-is (along with optional config files) at the root of customizable boot device, or of a side media.
If using wifi networking, create a file wpa_supplicant.conf in the same location as follows:
Contents of wpa_supplicant.conf
country=FR
network={
key_mgmt=WPA-PSK
ssid="mySSID"
psk="myPassPhrase"
}
Alternately, wpa_passphrase
utility from wpa_supplicant package can be used to create the encrypted version of the above file as follows:
$ wpa_passphrase 'mySSID' 'myPassPhrase' > wpa_supplicant.conf
The above encrypted version of the wpa_supplicant.conf file may be placed in the same location.
Boot the system with the above setup: usual Installation steps can then be performed remotely using ssh
To find the ip of your headless host, one may use the nmap
tool from nmap package as follows: $ nmap -v -sn 192.168.1.0/24
Alternative custom install media preparation steps
A Custom install media for a headless host can be created using a customizable boot device as per the below process.
Note: Instead of customizable boot device, if a read-only boot media is used, then storing the configs require either a separate storage media or server location.
- Booting the customizable boot device on some computer with a display and keyboard attached, or in a virtual machine, and doing an intermediate "diskless" setup of just the boot media (more details below), i.e. using the offical
setup-alpine
to configure the system's network, possibly for dhcp if needed, a ssh server, and a login user.
- Choosing "disks=none" for now, yet, configure to store configs on the customizable boot device.
- Use
lbu commit
to store the configs as local backup. Then your completed setup, including its securely created own private keys, will readily get (re)loaded on every subsequent (headless) boot from your custom-build <hostname>.apkovl.tar.gz
stored on the customizable boot device.
See also