RPi Zero - Headless Setup
Tags: raspberrypi, headless, setup, tutorial
Published: 2018-03-22 18:12:36

---
title: RPi Zero - Headless Setup
published: true
description: 
tags: raspberrypi, headless, setup, tutorial
---

#### Intro

This is my very first post on dev.to, and I hope you find it helpful. I purchased a Raspberry Pi Zero W in December 2017, and aside from plugging in the power adapter to check if the green light comes on, I haven't touched it since.

![alt text](http://raspi.tv/wp-content/uploads/2016/05/Pi-Zero-1.3-top_1500.jpg "Raspberry Pi Zero W ports")

When I first received it, I was surprised that there were two separate micro USB ports for power and USB input. I was also disappointed that it came with a mini HDMI port, because I didn't have mini-to-regular HDMI adapter or cable to connect a monitor. I knew it was possible to do a headless setup, but I never got around to it. I've been wanting to use [Node-RED](https://nodered.org/) for some of my DIY electronics projects for quite some time now, and I figured I'd put off setting up the RPi long enough!

#### What is "headless" setup anyway?

When you want to set up a device like the Raspberry Pi without using a display or a keyboard, you do a "headless" setup. This way of setting it up involves a few extra steps, as compared to how you'd normally go about it (i.e., with a display and input devices). 

#### Step 1: Downloading the OS

I first downloaded the Raspbian Stretch Lite operating system image from the [Raspbian downloads page](https://www.raspberrypi.org/downloads/raspbian/). Having decided that I'm going to do a headless setup, I figured I'd get the "Lite" version, which does not come with any desktop environments. I can always install one later, if necessary. The size of the image is 365.8 MB.

#### Step 2: Write OS image to an SD card

I like to use [Etcher](https://etcher.io/) to write OS images to SD cards/USB drives. The GIF below shows you how quick and easy it is:

![alt text](https://etcher.io/static/screenshot.gif "Using Etcher")

I used an old, class 4 SanDisk 16 GB micro SD card I had lying around with the official Raspberry Pi micro SD adapter. It took about 10 minutes to write the image to the SD card.

![alt text](https://i.imgur.com/ha4Nsn1.png "Micro SD card & adapter")

#### Step 3: Set up WiFi

Without a monitor or any I/O devices connected, how are you supposed to connect the RPi to a wireless network? It's simple. With the SD card still plugged in and mounted, you create a file containing the SSID name and passkey of the network you want to connect to.

Fire up the terminal, navigate to the SD card.

```
cd /media/userName/boot
```

Create a file called `wpa_supplicant.conf`.

```
touch wpa_supplicant.conf
```

Open the file in your favourite text editor. Don't judge, I'm using nano because it's sufficient for doing something as simple as this.

```
nano wpa_supplicant.conf
```

Add the following to the file:

```
country=IN
update_config=1
ctrl_interface=/var/run/wpa_supplicant

network={
    ssid="mySSID"
    psk="my5up3rStr0ngP@sSw0Rd!"
}
```

Now what does all this mean? 

`country=IN`

This is quite self-explanatory. I'm specifying the country I'm using this device in (India) with its [ISO/IEC alpha2 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Decoding_table). 

`update_config=1`

The `update_config` option used to allow wpa_supplicant to overwrite the current configuration, if there is a change in the configuration (e.g., new network block is added with wpa_cli or wpa_gui, or a password is changed). If this option is set to `0`, then wpa_cli/wpa_gui will not be able to save the new settings.

`ctrl_interface=/var/run/wpa_supplicant`

This parameter allows `wpa_supplicant` to have a control interface that external programs (such as `wpa_cli` or `wpa_gui`) will use to read/modify configuration values. On Linux and BSD, a directory exists for UNIX domain sockets to listen to status information or configuration requests from command line or GUI programs. By default, this directory is `/var/run/wpa_supplicant`, and `wpa_cli` will use this path when it tries to connect with `wpa_supplicant`.

`network={`
`    ssid="mySSID"`
`    psk="my5up3rStr0ngP@sSw0Rd!"`
`}`

This section is called the "network block". I've simply specified the SSID and passkey of the wireless network I want the RPi to connect to because my network setup is very simple (a mobile hotspot). However, if your network setup is more complicated, you will need to modify the network block to facilitate the connection. There are several network block options that you can set, as required. If you're interested in the juicy details, check out this [sample wpa_supplicant.conf file](https://w1.fi/cgit/hostap/plain/wpa_supplicant/wpa_supplicant.conf).

What if you have multiple networks you want your RPi to be able to connect to, depending on where it is? You can have multiple network blocks!

```
# Network 1
network={
    ssid="office"
    psk="officePassword"
}

# Network 2
network={
    ssid="home"
    psk="homePassword"
}

.
.
.

# Network N
network={
    ssid="workshop"
    psk="workshopPassword"
}
```

It's not enough if the Raspberry Pi connects to my network. Unless explicitly specified, SSH remains disabled. To enable SSH, simply create an empty file called `ssh` (no extension) in the `boot` folder (`/media/userName/boot`). When the Pi boots, it looks for the `ssh` file. If found, SSH is enabled and the file is automatically deleted.

All set! I ejected the SD card and popped it into my Raspberry Pi.

**Notes**: 

1. I did all this in Linux. If you're on Windows, just open up the SD card in Windows Explorer and follow along. Instead of running the `touch` and `nano` commands, create a new file in a text editor. I strongly recommend you use a program that will convert your file line-endings from DOS to UNIX while saving. A great text editor for Windows that will do this for you is [Notepad++](https://notepad-plus-plus.org/download/v7.5.6.html). Alternately, if you have Cygwin, you can simply run `dos2unix` on the file after saving it. Pay attention to the file extensions - you don't want your files to end up having a ".txt" extension!

2. The `wpa_supplicant.conf` file will be moved to `/etc/wpa_supplicant/` after the RPi boots up for the first time. If you want to add/modify your network settings, you need to make those changes to `wpa_supplicant.conf` as with super user privileges at this location.

#### Step 4: Finding the IP address

I powered up the RPi, switched on my mobile hotspot and waited for a connection. Within a few seconds, the Raspberry Pi was connected. Okay, great. But how am I supposed to SSH to a device whose IP address I don't know? There are different ways to go about this:

##### 1: On Linux, using `arp`

ARP stands for Address Resolution Protocol. The `arp` command displays the Linux kernel's IPv4 network neighbour cache. Using this command, you can add, delete or modify the table. 

So `arp -a` gave me this output:

```
gateway (142.30.10.1) at ac:d3:9f:1c:ff:23 [ether] on wlp6s0
device1 (11.210.123.60) at 9b:4c:5e:65:4d:6e [ether] on enx9ce
? (142.30.10.4) at 23:c2:dc:ae:85:9f [ether] on wlp6s0
device2 (11.210.123.62) at f8:7d:23:8a:80:4e [ether] on enx9ce
device3 (11.210.123.65) at 0f:0f:0d:0e:ca:db [ether] on enx9ce
```

Notice that instead of the standard `eth0` and `wlan0`, the interfaces are being displayed as `wlp6s0` and `enx9ce`. Starting with v197, system/udev started assigning predictable, stable network interface names for all local Ethernet, WLAN and WWAN interfaces. Here's all you need to know about [Predictable Network Interface Names](https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/).

So anything that starts with "wl" is on wireless LAN, and anything that starts with "en" is on Ethernet. The "gateway" in the list above is the mobile phone that I used to create the hotspot. So that's not the IP I want. The only other item whose interface begins with a "wl" is the `?`. I don't care that its name is a solitary `?`, so I tried SSHing to 142.30.10.4. 

The `arp -a` command works on Windows too (surprise!), but unlike Linux, the output shows every other system your computer is aware of or has talked to in the past. Note, the list may not be complete - some devices will get added to the list only after your computer has pinged them and received a response.

##### 2: From your router
    
Another way to go about finding the IP address of the Raspberry Pi would be to open up the router's administration page and look at the list of connected devices. Even if you can't see the actual hostname of the device, you should be able to narrow down the IPs you need to try SSHing to. I set up the hotspot on an iPhone, which unfortunately, does not let you see the IP addresses assigned to the connected devices. If you're using an Android phone, it should be possible to view the IP addresses of each connected device.

#### Step 5: Making the SSH connection

I connected to the RPi as follows:

```
ssh pi@142.30.10.4
```

And I was greeted with this message:

```
The authenticity of host '142.30.10.4 (142.30.10.4)' can't be established.
RSA key fingerprint is 80:6c:7e:a3:cd:2b:60:9d:55:b8:4d:3e:d3:f8:e1:32.
Are you sure you want to continue connecting (yes/no)? 
```

Success! I replied with `yes`.

```
Warning: Permanently added '142.30.10.4' (RSA) to the list of known hosts.
pi@142.30.10.4's password: 
```

The default username and password for a fresh install of Raspbian are `pi` and `raspberry`, respectively. 

#### Step 6: Initial setup

The first thing you want to do after logging in is change the default password. You can do this with the `passwd` command. You will be asked for your current password, after which you will have to enter your new password.

```
pi@raspberrypi:~ $ passwd
Changing password for pi.
(current) UNIX password:
Enter new UNIX password:
Retype new UNIX password:
```

The base OS image is sized such that it takes as little space as possible on the SD card. A full installation of Raspbian comes to around 4 GB. All the extra space available in larger SD cards gets wasted if the filesystem is not explicitly expanded. So, I then ran the command: `sudo raspi-config`, which brings this up:

![alt text](http://42bots.com/wp-content/uploads/2015/03/raspi-config-01.jpg "The raspi-config screen)

Here, I selected the very first option - `Expand Filesystem`. To understand what exactly this does, read the [second answer](https://raspberrypi.stackexchange.com/questions/55857/what-does-raspi-configs-expand-filesystem-option-do) to this question on the Raspberry Pi StackExchange.

Next, I set the locale and timezone as follows:

```
sudo dpkg-reconfigure locales
```

The Raspberry Pi Foundation is a UK-based charity foundation. So, the default locale is English - UK. The default timezone and keyboard layout pertain to the UK as well. In the list of locales displayed, unselect `en_GB.UTF-8 UTF-8`, select `en_US.UTF-8 UTF-8` instead, and hit 'OK'. Confirm your selection and wait for locale generation to complete.

![alt text](http://unix.cafe/wp/wp-content/uploads/2016/09/lc_locales.png "Setting the locale")

![alt text](https://i.imgur.com/Jp795pk.png "Confirming the locale")

```
Generating locales (this might take a while)...
  en_US.UTF-8... done
Generation complete.
```

I then reconfigured the keyboard layout as follows:

```
sudo dpkg-reconfigure keyboard-configuration
```

The locale I just set gets used for this, and there is no output.

Finally, I set the timezone as follows:

```
sudo dpkg-reconfigure tzdata
```

Here, I selected Asia, and then Kolkata.

![alt text](https://abdussamad.com/files/2013/02/tzdata-reconfigure.jpeg "Geographic location")

```
Current default time zone: 'Asia/Kolkata'
Local time is now:      Thu Mar 22 16:32:44 IST 2018.
Universal Time is now:  Thu Mar 22 11:02:44 UTC 2018.
```

And that's about it! 

#### Next steps

I found it very annoying that I needed to run the `arp` command each time I wanted to find the Pi's IP address. Or, I'd have to open up the router administration page to look it up. Or, I'd have to configure it with a static IP address. 

So, I decided that I'd write a script that would run on the RPi, that would send me an email specifying the SSID and IP address as soon as it gets connected. I will talk about how I did this in my next post.

I look forward to your comments/feedback on my post.