> ## Content Index
> Fetch the complete content index at: https://linuxhandbook.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Complete Guide to Install Raspberry Pi Headless and Wireless
- URL: https://linuxhandbook.com/raspberry-pi-headless-setup/
- Published: 2018-03-20T22:43:34.000Z
- Updated: 2024-02-16T14:16:42.000Z
- Description: A step by step guide showcasing how to install Raspberry Pi without a keyboard and monitor, i.e., headless setup of Raspberry Pi using Linux.
- Author: Sylvain Leroux
- Tags: Tutorial

Installing [Raspbian](https://www.raspbian.org/?ref=linuxhandbook.com) on Raspberry Pi from a Linux system is not a difficult task. And the Raspberry Pi foundation provides the [necessary pieces of information to do that](https://www.raspberrypi.org/documentation/installation/installing-images/linux.md?ref=linuxhandbook.com) unless you need to install your Raspberry Pi headless (aka, without an attached monitor and keyboard) and wireless (aka, through Wi-Fi). And this happens to be just my case.

I am going to show you how I performed headless setup of Raspberry Pi in this tutorial. I have also created a video of the steps to help you see things in action.

## Headless setting up Raspberry Pi

I presume that since you are going for headless installation, you are a bit familiar with Linux command line because you are going to use it extensively here. I have used Debian Linux in this tutorial.

### Step 1: Importing the Raspberry Pi Foundation download Signing key into your key ring

Since I don’t like installing software without checking their authenticity, let’s first add into your [GPG](https://en.wikipedia.org/wiki/GNU%5FPrivacy%5FGuard?ref=linuxhandbook.com) keyring the necessary key to validate the Raspbian image.

As of today, the Raspberry Pi Foundation downloads Signing key fingerprint is 54C3DD610D9D1B4AF82A37758738CD6B956F460C. Something **I strongly encourage you to cross-check using other sources**. Since the key expires the 2019-04-10 if you read this article after that this date it will be different.

```
gpg --recv-key 54C3DD610D9D1B4AF82A37758738CD6B956F460C
```

### Step 2: Downloading the Raspberry OS image and its signature

The latest version of Raspberry OS (earlier known as Raspbian) is always available at [this address](https://downloads.raspberrypi.org/raspbian%5Flite%5Flatest?ref=linuxhandbook.com).

![](https://linuxhandbook.com/content/images/2020/07/rpi-download-raspbian-image.png)

But this is only a redirection. You need the **real* address so you can download both the image and the corresponding detached signature file.

The best way of doing that is by using some advanced `curl` black magic:

```
URL=https://downloads.raspberrypi.org/raspbian_lite_latest
EFFECTIVE_URL=$(curl -w "%{url_effective}\n" -I -L -s -S $URL -o /dev/null)
echo $EFFECTIVE_URL
```

I must admit I always have some hard time remembering that command, so for interactive usage, I often fall back to a simple `wget` command with a limited [redirection](https://linuxhandbook.com/redirection-linux/) count:

```
URL=https://downloads.raspberrypi.org/raspbian_lite_latest
EFFECTIVE_URL=$(wget --max-redirect=0 $URL 2>&1 | sed -En 's/Location: ([^ ]*).*$/\1/p')
echo $EFFECTIVE_URL
```

(Actually, it should be `--max-redirect=1` in that particular case, nevertheless only going through the first level of redirection is sufficient for our needs)

At this point, you have the valid URL required to download both the image and its detached signature:

```
wget "$EFFECTIVE_URL"{,.sig}
```

If you have an unreliable Internet connection like mine, you may consider explicitly adding a much more aggressive timeout than the default 900 seconds like I did [while recording the video](https://youtu.be/-lKGUQXsZbo?t=114&ref=linuxhandbook.com))

### Step 3: Checking the signature

After a moment, the download is completed and you should have those two files in the current directory:

```
ls *raspbian*
2017-11-29-raspbian-stretch-lite.zip  2017-11-29-raspbian-stretch-lite.zip.sig
```

You may now use GPG to check both if the signature is corresponding to the file **and* if the signature was issued by an authority you can trust:

```
gpg --verify 2017-11-29-raspbian-stretch-lite.zip{.sig,}
gpg: Signature made Thu 30 Nov 2017 02:48:51 PM CET
gpg:                using RSA key 8738CD6B956F460C
gpg: Good signature from "Raspberry Pi Downloads Signing Key" [full]
```

At this stage, anything else than **Good signature from “Raspberry Pi Downloads Signing Key”* should warn you that something odd is happening.

As an example to satisfy our curiosity, let’s fake the file to see what exactly would GPG report in that case:

```
# Add just one byte to the file
(cat 2017-11-29-raspbian-stretch-lite.zip; echo) > 2017-11-29-raspbian-stretch-lite.zip.fake
gpg --verify 2017-11-29-raspbian-stretch-lite.zip{.sig,.fake}
gpg: Signature made Thu 30 Nov 2017 02:48:51 PM CET
gpg:                using RSA key 8738CD6B956F460C
gpg: BAD signature from "Raspberry Pi Downloads Signing Key" [full]
```

**Why didn’t I use the sha256 file fingerprint instead?**

You may have noticed the Raspbian download page displays the [sha256 checksum](https://en.wikipedia.org/wiki/SHA-2?ref=linuxhandbook.com) of the file. You may use that to check the file [integrity](https://en.wikipedia.org/wiki/Data%5Fintegrity?ref=linuxhandbook.com) against innocent download errors. But, in that context, it can’t be used to check for the file [authenticity](https://en.wikipedia.org/wiki/Message%5Fauthentication?ref=linuxhandbook.com). So it will not protect you against malicious behavior. For example, if an attacker has subverted the server storing the Raspbian images, there are chances it could have gained control of the web server to display the sha256 sum of his choice. On the other hand, the GPG signature will check both for the file integrity and for its authenticity.

### Step 4: Copying the image

Once you are pretty sure the Raspbian image is the genuine one it is time to copy it onto your memory card.

But, first, you need to know the [device name](https://en.wikipedia.org/wiki/Device%5Ffile?ref=linuxhandbook.com) used by the kernel to identify the memory card. So, ensure your memory card is not in the card reader. Then, launch the `[dmesg](https://linux.die.net/man/1/dmesg?ref=linuxhandbook.com)` utility in watch mode:

```
sudo dmesg -w
```

And now, put the card into the card reader. At this point, dmesg displays some information about the card, including its device name:

```
mmc0: new SDHC card at address e624
mmcblk0: mmc0:e624 SC16G 14.8 GiB
mmcblk0: p1
```

Here, you can see my memory card is accessible through the name `/dev/mmcblk0`. And it currently contains just one partition (`p1`) you can access as `/dev/mmcblk0p1`.

If your version of dmesg does not support the -w flag, do the things the other way around: put the card into the card reader first, and use dmesg to see the message afterward.

Some systems might “automount” your card, so it’s safer to explicitly check that before going further:

```
sudo umount /dev/mmcblk0*
```

Finally, it’s time to copy the file per se:

```
unzip -p 2017-11-29-raspbian-stretch-lite.zip |
  sudo dd of=/dev/mmcblk0 conv=fsync
```

It may be pretty long to copy the file, so, don’t panic if your terminal seems to hang for long minutes.

Once the copy has finished, it is safer to ask the kernel to reload the partition table of the device, since it has changed in the process. That will avoid some hard to diagnose issues later where you will be unable to mount the memory card partitions onto your system:

```
sudo partprobe /dev/mmcblk0
```

### Step 5: Enabling ssh at startup

To enable SSH at startup you just need to create a sentinel file onto the card boot partition. The content of the file is meaningless. It just has to be present.

```
sudo mount /dev/mmcblk0p1 /mnt -o umask=000
touch /mnt/ssh
```

### Step 6: Enabling Wi-Fi at startup

wpa\_supplicant is the software used by your computer to gain access to your Wi-Fi access point. It is pre-installed on Raspbian, but it needs a little bit of configuration to work.

The most basic wpa\_supplicant.conf file only contains the [country code](https://en.wikipedia.org/wiki/ISO%5F3166-1%5Falpha-2?ref=linuxhandbook.com#Officially%5Fassigned%5Fcode%5Felements) of your location to ensure compliance with the local regulations:

```
cat > /mnt/wpa_supplicant.conf << EOT
country=FR
EOT
```

Depending on if you want to allow non-root software (like [wpa\_cli](https://linux.die.net/man/8/wpa%5Fcli?ref=linuxhandbook.com)) to alter the configuration, you may add the `ctrl_interface=…​` option, and eventually the `update=1` option to allow non-root clients to overwrite [wpa\_supplicant.conf](https://linux.die.net/man/5/wpa%5Fsupplicant.conf?ref=linuxhandbook.com) to make their changes permanent. Check the [accompanying video](https://youtu.be/-lKGUQXsZbo?t=429&ref=linuxhandbook.com) for an example of the former, and you may easily find on the web an example of the later.

Finally, for a reference of all possible configuration settings, check here:  
[https://w1.fi/cgit/hostap/plain/wpa\_supplicant/wpa\_supplicant.conf](https://w1.fi/cgit/hostap/plain/wpa%5Fsupplicant/wpa%5Fsupplicant.conf?ref=linuxhandbook.com)

In all cases, you need to add the necessary credentials, so `[wpa_supplicant](https://linux.die.net/man/8/wpa%5Fsupplicant?ref=linuxhandbook.com)` can connect to the access point. I don’t like storing a password as plain text so I will use `[wpa_passphrase](https://linux.die.net/man/8/wpa%5Fpassphrase?ref=linuxhandbook.com)` to do that:

```
SSID=my_wifi # This is your Wi-Fi AP SSID (the "name" of your Wi-Fi)
(
  # Disable echoing
  stty_orig=$(stty -g);
  trap 'stty $stty_orig' EXIT;
  stty -echo;
  # Read password from the terminal
  read -rp 'Enter your password: ';
  echo $REPLY
) | wpa_passphrase $SSID | sed '/^[[:space:]]*#/d' >> /mnt/wpa_supplicant.conf
```

I let you check if all is in order:

```
cat /mnt/wpa_supplicant.conf
```

And if this is OK, just `umount` the card and remove it from the card reader:

```
sudo umount /mnt
```

### Step 7: Booting the board

You are almost ready to boot the board.

But to access it through SSH, you will need its IP address. There are different solutions to obtain that piece of information. You could use a static IP address on the board. 

Or you could check in the DHCP server’s log to identify the lease associated with the board once it had gained it. 

Or you could scan the entire network with `nmap`.

Here I will use `[tcpdump](https://linux.die.net/man/8/tcpdump?ref=linuxhandbook.com)` since this is less intrusive and somewhat educative.

So, before booting the board, launch `tcpdump` on a network attached computer:

```
sudo tcpdump -lenqti any port 68 or arp | grep "^ B"
```

Here I ask `tcpdump` to watch for [DHCP](https://en.wikipedia.org/wiki/Dynamic%5FHost%5FConfiguration%5FProtocol?ref=linuxhandbook.com) (port 68) and [ARP](https://en.wikipedia.org/wiki/Address%5FResolution%5FProtocol?ref=linuxhandbook.com) related traffic. I took the “lazy” approach of listening on **any* interfaces. This has some drawbacks like not being able to filter for broadcast packets directly from `tcpdump`–hence the need for the extra `grep` process. But this shouldn’t be a serious issue here unless you have a very high ARP and DHCP traffic directly targeting your computer.

With the packet capture tool ready, you may now boot the board. After a few seconds `tcpdump` would capture some traffic coming from the board. First to locate a DHCP server, and later to check if the DHCP provided IP address is available, and finally to advertise itself as the new owner of that IP address.

![Capture of the broadcast packets send by the Raspberry Pi at startup](https://linuxhandbook.com/content/images/2020/07/tcpdump-dhcp-arp-raspberry-pi-startup-capture-1024x504.png)

I strongly encourage you to watch the [corresponding part of the video](https://youtu.be/-lKGUQXsZbo?t=554&ref=linuxhandbook.com) to see the live stream of events.

Once you’ve identified the IP address of the board, you can now connect to it through SSH as usual:

```
ssh pi@IP_OF_THE_BOARD
```

At this point, the board is still running with the default stock password, so changing it should be one of your very first tasks:

```
passwd
```

And you’ve done: your board is completely set up, accessible through SSH via your local Wi-Fi network, and ready for all you might want to do with it. But that is **your* part of the job! So, don’t hesitate to let us know what you’ve done with your Raspberry Pi, and the eventual difficulties you might had while setting it up. And stay tuned for more!