1. Headless set-up

1.1. Intro

Every time I deploy a new pi, something has changed. This makes it difficult to create a simple set-up that works every time. It also means that almost all instructions you find on the internet are outdated. Google is great in finding set-up instructions from back in 2012, but those do not work anymore. And most instructions do not have a date in them, so you're completely lost why it doesn't work.

This instruction is made for people that have Linux running. It is updated after each time I (re-)install a Pi.

installed psi
installed blueberry

1.2. Burning the image

First get the latest Raspian:

wget http://downloads.raspberrypi.org/raspbian_latest

What you'll get is a zip-file with the latest raspian-image. Unzip and burn on the SD-card.

Many tutorials go into great length on how to identify your SD-card. In most cases, it is /dev/mmcblk0 or one of the /dev/sd* devices.

mv raspbian_latest raspbian_latest.zip
unzip raspbian_latest.zip
sudo dd if=2020-02-13-raspbian-buster.img  of=/dev/mmcblk0 status=progress

Of course, this takes a long time; that is why the status=progress is on the command line. Total is about 3.6G.

Remove the card and plug it back in. Normally, it will be mounted automatically, and you will see:

/dev/mmcblk0p1 on /run/media/ljm/boot type vfat 
/dev/mmcblk0p2 on /run/media/ljm/5c01c1ce-fe60-428a-8e68-0be0e8ed6b7a type ext4 

Otherwise, mount by hand.

For raspian-stretch and buster, the root file system will be called rootfs instead of the big number.

1.3. The networking

Because from Jessie on, it is now using systemd, everything you knew about the configuration of networking is now of no value. In previous releases, networking was done via /etc/network/interfaces but now, dhcpcd is used. It also means that all tutorials and howto's are now obsolete.

The main configuration file for dhcpcd is /etc/dhcpcd.conf. For every connection that you want to have a fixed IP address add a block, of course with your own IP addresses:

interface eth0

static ip_address=
static routers=
static domain_name_servers=

interface wlan0

static ip_address=
static routers=
static domain_name_servers=

For some dark and unknown reason, you sometimes need to edit /etc/network/interfaces to add

allow-hotplug eth0

Next, setup the wpa-supplicant in etc/wpa_supplicant/wpa_supplicant.conf

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev


You will need to copy the wpa_supplicant.conf file for your particular wireless network in the boot folder, and when the Pi first boots, it will copy that file into the correct location in the Linux root file system and use those settings to start up wireless networking. After the Pi is connected to power, make sure to wait a few (up to 5) minutes for it to boot up and register on the network. The Pi's IP address will not be visible immediately after power on, so this step is crucial to connect to it headlessly. Depending on the OS and editor you are creating this on, the file could have incorrect newlines or the wrong file extension so make sure you use an editor that accounts for this.

1.4. Enable ssh

Enabling ssh requires an ssh file in the boot directory. Normally, you see a directory

/dev/mmcblk0p1     /run/media/username/boot

if you query all mounts. So do a

touch /run/media/username/boot/ssh

and ssh will start at boot-time.

But you don't want to type passwords, so we'll distribute the keys:

cd $piroot/root
mkdir .ssh
chown root.root .ssh
chmod 700 .ssh
cp  ~/.ssh/id_rsa.pub  .ssh/authorized_keys
chmod 600 .ssh/authorized_keys

1.5. Connecting and manual actions.

If you do it in this way, everything should run and the pi should be accessible under your WiFi IP address.

Try a ssh root@ (use your own IP address) and voila.

There are some manual actions to take before everything works. First, make your users that need to be present on the system. In my case, that is "ljm":

adduser ljm
mkdir /home/ljm
cp -r /root/.ssh ~ljm
chown -R ljm.ljm ~ljm/.ssh

Next item on the list: raspi-config. Use the menus to set the host name. But more importantly, under 7 Advanced Options you will find A1 Expand File system which will allow you to use the complete sd card.

Under Buster, you will need to set under

    4 Localisation Options

the Wifi country

I4 Change Wi-fi Country

Do not reboot after this!

Make vi our default editor:

update-alternatives --set editor /usr/bin/vim.tiny

you will also need to add the users in the sudoers-file:


If you want to manage your pi via Ansible, you may want to

sudo apt-get install -y aptitude

And to be up-to-date, do:

apt-get update
apt-get upgrade

This may take a very long time. You will may see a lot of lines

 Removing 'diversion of /boot/bootcode.bin to /usr/share/rpikernelhack/bootcode.bin by rpikernelhack'
 Removing 'diversion of /boot/start4.elf to /usr/share/rpikernelhack/start4.elf by rpikernelhack'
 Removing 'diversion of /boot/start4cd.elf to /usr/share/rpikernelhack/start4cd.elf by rpikernelhack'
 Removing 'diversion of /boot/start4db.elf to /usr/share/rpikernelhack/start4db.elf by rpikernelhack'
 Removing 'diversion of /boot/start4x.elf to /usr/share/rpikernelhack/start4x.elf by rpikernelhack'

which take a while to complete. When I did this, it took about two hours.

And now: reboot

1.6. Security

With this set-up you can add the pi to your local network. Not to the Internet. There are a lot of security implications that we have not considered. One of the most important is that the user pi is still present and having his default password. Also the NOPASSWD in the sudoers is practical, but a bad idea security-wise.

The goal of this part was to get the pi working; not to make it secure.

1.7. note

Raspberry Pi is a trademark of the Raspberry Pi Foundation.