Changes
Created page with "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 initia..."
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 (e.g. using avahi-daemon). 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.
== Existing solutions ==
[https://github.com/raspberrypi/noobs NOOBS] has some facilities to make unattended installations and [https://pihw.wordpress.com/guides/pi-kitchen/ Pi-Kitchen] can be used to customize it further (e.g. by installing package, configuring and launching services after the first boot).
[https://github.com/debian-pi/raspbian-ua-netinst 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 <code>raspi-config</code> 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, <code>raspi-autoconfig</code> 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 [https://www.raspberrypi.org/downloads/ Raspbian] image and follow the [https://www.raspberrypi.org/documentation/installation/installing-images/linux.md official installation procedure].
TL;DR: <code>dd bs=4M if=/path/to/raspbian-image of=/dev/sdX; sync</code>
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 <code>$SD</code>, NOT your file system root <code>/</code>):
<pre>
mkdir $SD/home/pi/.ssh
cat ~/.ssh/id_rsa.pub >> $SD/home/pi/.ssh/authorized_keys
</pre>
(note that the default raspbian user is <code>pi</code>)
Then configure sshd to prevent password login by editing <code>$SD/etc/ssh/sshd_config</code> with the following options:
<pre>
ChallengeResponseAuthentication no
PasswordAuthentication no
UsePAM no
</pre>
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 <code>chroot</code> into the SD card and execute <code>apt-get</code> to pull additional packages, because your running computer probably runs on an x86/x86-64 architecture and your RPi uses ARM (and <code>chroot</code> works only when the architectures [http://unix.stackexchange.com/a/41890 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 <code>apt</code> install them from the file system instead of downloading them, but this won't be covered here.
By placing a script in <code>$SD/etc/networks/if-up.d/</code>, 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.
<pre>
#!/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"
</pre>
=== 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:
<pre>
apt-get -q update
apt-get -qy install avahi-daemon
insserv avahi-daemon
</pre>
You should be able to replace <code>insserv avahi-daemon</code> by <code>update-rc.d avahi-daemon defaults</code>, 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 <code>raspberrypi</code> on all fresh Raspbian installations. To achieve this, change the hostname in <code>$SD/etc/hostname</code> and in <code>$SD/etc/hosts</code> at the <code>127.0.1.1</code> line (which is exactly what <code>raspi-config</code> 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 <code>ssh pi@<hostname></code> (or <code>pi@<hostname>.local</code> 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 <code>sudo raspi-config</code> 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 <code>ddclient</code> on your RPi by replacing the "your code here" section of the script above with:
<pre>
apt-get -q update
apt-get -qy install ddclient
</pre>
and configuring the client by editing <code>$SD/etc/ddclient.conf</code> with:
<pre>
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
</pre>
''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 <code>sendmail</code>. You might have to configure the SMTP server before <code>sendmail</code> 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.
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 (e.g. using avahi-daemon). 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.
== Existing solutions ==
[https://github.com/raspberrypi/noobs NOOBS] has some facilities to make unattended installations and [https://pihw.wordpress.com/guides/pi-kitchen/ Pi-Kitchen] can be used to customize it further (e.g. by installing package, configuring and launching services after the first boot).
[https://github.com/debian-pi/raspbian-ua-netinst 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 <code>raspi-config</code> 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, <code>raspi-autoconfig</code> 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 [https://www.raspberrypi.org/downloads/ Raspbian] image and follow the [https://www.raspberrypi.org/documentation/installation/installing-images/linux.md official installation procedure].
TL;DR: <code>dd bs=4M if=/path/to/raspbian-image of=/dev/sdX; sync</code>
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 <code>$SD</code>, NOT your file system root <code>/</code>):
<pre>
mkdir $SD/home/pi/.ssh
cat ~/.ssh/id_rsa.pub >> $SD/home/pi/.ssh/authorized_keys
</pre>
(note that the default raspbian user is <code>pi</code>)
Then configure sshd to prevent password login by editing <code>$SD/etc/ssh/sshd_config</code> with the following options:
<pre>
ChallengeResponseAuthentication no
PasswordAuthentication no
UsePAM no
</pre>
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 <code>chroot</code> into the SD card and execute <code>apt-get</code> to pull additional packages, because your running computer probably runs on an x86/x86-64 architecture and your RPi uses ARM (and <code>chroot</code> works only when the architectures [http://unix.stackexchange.com/a/41890 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 <code>apt</code> install them from the file system instead of downloading them, but this won't be covered here.
By placing a script in <code>$SD/etc/networks/if-up.d/</code>, 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.
<pre>
#!/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"
</pre>
=== 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:
<pre>
apt-get -q update
apt-get -qy install avahi-daemon
insserv avahi-daemon
</pre>
You should be able to replace <code>insserv avahi-daemon</code> by <code>update-rc.d avahi-daemon defaults</code>, 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 <code>raspberrypi</code> on all fresh Raspbian installations. To achieve this, change the hostname in <code>$SD/etc/hostname</code> and in <code>$SD/etc/hosts</code> at the <code>127.0.1.1</code> line (which is exactly what <code>raspi-config</code> 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 <code>ssh pi@<hostname></code> (or <code>pi@<hostname>.local</code> 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 <code>sudo raspi-config</code> 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 <code>ddclient</code> on your RPi by replacing the "your code here" section of the script above with:
<pre>
apt-get -q update
apt-get -qy install ddclient
</pre>
and configuring the client by editing <code>$SD/etc/ddclient.conf</code> with:
<pre>
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
</pre>
''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 <code>sendmail</code>. You might have to configure the SMTP server before <code>sendmail</code> 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.