Raspberry Pi: Headless installation
While it is not uncommon to have a headless Raspberry Pi (RPi) server, the installation process is usually done by connecting a monitor and a keyboard to the RPi to do the initial installation and configuration, e.g. using NOOBS or by directly transferring the official Raspbian image on the SD card.
If you don't have an additional monitor and keyboard for your RPi, e.g. you only have a laptop at hands, by installing directly Raspbian and after you have hooked up your RPi to the network you can SSH into it to finalize the installation. But this assumes that you know the IP address of your RPi in order to SSH into it. If you don't, e.g. the IP address is assigned by a DHCP server that you do not control, you can still have some ways to get it, but this can be challenging to novice users.
This article proposes a simple solution to allow the user to SSH into its RPi without having to go above and beyond to get its IP address once hooked to the network. It is assumed that you can modify the content of the SD card once the Raspbian image has been transfered to it, so it won't work natively on Windows.
Among others, the following solutions seem interesting to easily SSH into the RPi:
- Configure the RPi to advertise its hostname with Zeroconf. The hostname can be modified from its default to prevent ambiguities.
- Configure the RPi to advertise itself on a DynDNS service.
- Configure the RPi to send an email to a predetermined address once its network interface is up.
However, none of them are actionable out of the box, and they require some packages to be installed on the RPi in order to work.
Contents
Existing solutions
NOOBS has some facilities to make unattended installations and Pi-Kitchen can be used to customize it further (e.g. by installing package, configuring and launching services after the first boot).
Raspbian-ua-netinstall can be used to create self-downloading unattended installations, and seems very flexible.
All those solutions are however too complex for a simple installation, and do not allow to easily understand what is happening under the hood. The aim of this article is to only install a standard Raspbian distribution and configure it such that it can be SSH'd into without hassle to complete the installation.
The raspi-config
tool (available out of the box) is usually used to do part of this initial configuration, but it must be used interactively so it is not fit for our purpose. Another similar tool, raspi-autoconfig
is a non-interactive pendant of the former, and might be useful for our purpose.
Prerequisites
- An SD card that meets the capacity requirements for Raspbian
- A running computer with an SD card reader (for this guide, it is assumed that it runs a linux distribution)
And as the target for the installed OS, although not absolutely required to follow this guide:
- A powered RPi
- Network access with a DHCP-provided IP address
Installation
All the following steps are done from your running computer, not from your RPi.
Download the latest Raspbian image and follow the official installation procedure.
TL;DR: dd bs=4M if=/path/to/raspbian-image of=/dev/sdX; sync
That's it! Also, an SSH server should be up and running on your RPi once powered-up with the default Raspbian installation.
Although optional, it could be nice to already prevent anyone except you to access the RPi through SSH. In order to do this, even before putting the SD card into the RPi, you can already configure sshd to authorize only access using SSH keys.
Assuming you already have an SSH key pair on your running computer, you just have to authorize your key (paths are relative to the SD card root $SD
, NOT your file system root /
):
mkdir $SD/home/pi/.ssh cat ~/.ssh/id_rsa.pub >> $SD/home/pi/.ssh/authorized_keys
(note that the default raspbian user is pi
)
Then configure sshd to prevent password login by editing $SD/etc/ssh/sshd_config
with the following options:
ChallengeResponseAuthentication no PasswordAuthentication no UsePAM no
Now, something must be done to address the IP address discovery problem.
Bootstrapping packages
Installing additional packages beyond the basic Raspbian installation is not straightforward when you want to do it on your running computer: you cannot just chroot
into the SD card and execute apt-get
to pull additional packages, because your running computer probably runs on an x86/x86-64 architecture and your RPi uses ARM (and chroot
works only when the architectures are the same).
To solve this problem, we will let Raspbian bootstrap the additional packages directly from the RPi once the network is available. It should also be possible to download the packages' and their dependencies' archives and install them manually from your running computer or let apt
install them from the file system instead of downloading them, but this won't be covered here.
By placing a script in $SD/etc/networks/if-up.d/
, it will be executed every time a network interface becomes available, and this will be used to wait for Internet access before downloading additional packages. The following script contains boilerplate code to ensure that Internet access is actually available (e.g. this is not the case with the loopback interface) and prevent the script from being executed several times (e.g. if there are several interfaces with Internet connectivity, such as Ethernet and WiFi) and finally ensure that the script is executed only once, typically the first time the RPi is booted.
#!/bin/sh # Ensures that the script is run only when "useful" network interfaces become # available, e.g. the loopback interface provides no Internet connectivity. case "$IFACE" in lo) exit 0 ;; *) ;; esac # Ensures that the script is run only once, e.g. when several network # interfaces are available FLAGFILE=/var/run/raspi-bootstrap.flag if [ -e $FLAGFILE ]; then exit 0 else touch $FLAGFILE fi ############################################################################### ### Your code goes here, everything before and after is boilerplate ########### ############################################################################### # The file containing this script is removed from the file system, so it won't # be executed again rm "$0"
Using Zeroconf
Assuming that you have a Zeroconf client (e.g. Avahi, Bonjour) on the machine you will use to SSH into your RPi, it would be nice to be able to use it to automatically resolve the IP address of your RPi. If both your computer and the RPi are on the same LAN (Zeroconf does not work across LANs), it would allow to use the hostname of your RPi instead of its IP address.
The problem is that there is no Zeroconf client in the default Raspbian installation, so it will have to be bootstrapped using the script above. Simply replace the "your code goes here" section by the following:
apt-get -q update apt-get -qy install avahi-daemon insserv avahi-daemon
You should be able to replace insserv avahi-daemon
by update-rc.d avahi-daemon defaults
, which is actually the recommended way to manage boot scripts.
You can optionally change the hostname of your RPi in order to prevent ambiguities, as it defaults to raspberrypi
on all fresh Raspbian installations. To achieve this, change the hostname in $SD/etc/hostname
and in $SD/etc/hosts
at the 127.0.1.1
line (which is exactly what raspi-config
does when you ask it to change the hostname).
Once done, you can finally place the SD card into your RPi, connect it to your LAN and power it up. After a few minutes (it can take some time, go get a coffee) you should be able to ssh into your RPi using ssh pi@<hostname>
(or pi@<hostname>.local
depending on the configuration of your machine, if none works check the installation and configuration procedure of the Avahi client for your distribution).
Finally you can execute sudo raspi-config
in your SSH shell to configure your RPi as usual.
Using DynDNS
When you are not on the same LAN as your RPi, you can use a DynDNS service to resolve the IP address of your RPi.
Basically, you have to install a DynDNS client on your RPi using the same technique as above and configure it according to the requirement of the DynDNS service you use.
As an example, using OVH's DynDNS service you can install ddclient
on your RPi by replacing the "your code here" section of the script above with:
apt-get -q update apt-get -qy install ddclient
and configuring the client by editing $SD/etc/ddclient.conf
with:
protocol=dyndns2 use=if, if=eth0 server=www.ovh.com login=raspberrypi password='p455w0rd' # Updates interval (in seconds) daemon=300 # Logging & temp files syslog=yes pid=/var/run/ddclient.pid cache=/tmp/ddclient.cache # Domain name raspberrypi.fixme.ch
Note: if you have not guessed it already, you have to adapt the values for login, password and the domain name to match your case, and the values above are fictional.
Sending a mail
The poor man's version of IP address discovery: make the RPi send an email that containing its IP address to a predefined email address. Yours.
Raspbian does not have an SMTP server installed by default, so again you can use the script above to install sendmail
. You might have to configure the SMTP server before sendmail
can be used in your script (which you can do by directly editing configuration files on the SD card before placing it in the RPi; I won't explain how to do it here because I'm too lazy).
For this solution to be a bit more comfortable, you might want to adapt the script such that it sends the email at regular intervals, and disable it manually once you have SSH'ed into your RPi.