Headless With Raspberry Pi

A guide to setting up a headless installation of Raspbian Lite for the first time - securing your user account, enabling and securing SSH with key-based authentication.

The Raspberry Pi is a highly functional bit of kit in a small package, but we have to make sure we’re lite on resource usage to make the most of it’s hardware. If you’re wanting to go headless (no desktop, just plug it in and SSH in), head to the Raspbian flavour section and grab the latest Lite image (Buster as of writing).

Once you’re comfortable with a Debian based distro, give ArchLinux a go for a truly tuned lean OS for the Pi!

Setup Networking for WiFi

If you’re going headless with no wires, configure your wpa_supplicant.conf for your wireless configuration and place it in the boot folder.

An example - make sure the country code conforms to ISO/IEC Alpha2:

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

 psk="<Password for your wireless LAN>"

Make sure your SSID and PSK are valid, some older Pi’s don’t support 5Ghz.

Read more about the RaspberryPi WiFi Configuration.

Changing default Raspberry Pi User

After booting your Pi for the first time, you invariably going to login with the default credentials pi and raspberry but yearn to change it to something a little more you - and highly recommended to avoid a default security login issue! Here’s a quick recipe to get you going.

One way is to create a new user then delete the existing pi user, but here’s an alternative that renames the existing pi user via the root account.

Before you continue…
This is best done straight after you boot your Pi for the first time.

First let’s reset the existing root password:

sudo passwd root 

Then exit the session:


Now login with the root account with the password set above. We’re going to set some shell variables to store our new user data, in my example below, I’m renaming pi to be ted and setting his full name to Ted Crisp.

new_fullname='Ted Crisp'
usermod -l $new_username -d /home/$new_username -m pi
usermod -c "$new_fullname" $new_username
groupmod --new-name $new_username pi

When that’s done, simply logout of root and log back in with ted with the default raspberry password and change it as required. One last thing, disable the root account, you don’t want to get rooted!

sudo passwd -l root

That’s it! Now, aren’t you Better Off Ted?

Update that install

Upgrade that distro to the latest available in tree.

sudo apt update
sudo apt upgrade

If you’ve wondered what the difference is between update, upgrade and dist-upgrade, Tony Wonder no more.

  • update will update the locally stored list of available packages and it’s versions but won’t touch any installed packages.
  • upgrade will install the newest versions of any installed packages on your system but it won’t remove or install any new packages you haven’t already got installed.
  • dist-upgrade will intelligently remove any packages or dependencies that it determines is unnecessary as well as upgrading the most important packages.

It’s common for seasoned users to bunch the two together:

sudo apt update && sudo apt upgrade

And let the apt command do it’s thing.

Change that timezone

By default it’s set to GMT, update it to your location if you’re not GMT via:

sudo dpkg-reconfigure tzdata

Enable SSH to login remotely

Newer releases of Raspbian don’t have SSH enabled by default. We need to enable that whilst logged in with one of two ways.

Via raspi-config

You can enable SSH via the raspi-config tool which you can find in the ‘Interfacing Options’ section.

sudo raspi-config

Via systemctl

sudo systemctl enable ssh
sudo systemctl start ssh

Secure that SSH with Key-Based Auth

Being able to remotely login and manage your Pi is an awesome thing, but it’s also open for abuse if you’re thinking of opening this to the wider internet.

It’s best to enable key-based authentication and disable the default username/password combination (if you do intend to use it, make sure it’s a very secure password).

Setup your public / private key pairs

First step if you haven’t already got yourself a public / private key pair is to generate one - on your main computer you’ll be logging in from. I’m generating this in Debian (and will also work on Mac) but if you’re running Windows and you’ve installed Git, you can run this within Gitbash.

ssh-keygen -b 4096 -t rsa -C "me@tedcrisp.com"

By default ssh-keygen will create a 2048bit RSA Key-Pair, so we’ve opted to generate a stronger 4096bit key above. Follow the prompts and by default it will store the key in /home/ted/.ssh/id_rsa but you can change that after generating.

Generating public/private rsa key pair.
Enter file in which to save the key (/home/ted/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):

The last step is that it asks you for a passphrase which locks down the usage of the key even further - and is recommended.

When that’s done, you’ll get something like this - what a work of art:

Your identification has been saved in /home/ted/.ssh/id_rsa.
Your public key has been saved in /home/ted/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:wIn/g/79LNZViubQpKsMdi5tA4R+fGn3twqPNhS5H1A ted@raspberrypi
The key's randomart image is:
+---[RSA 4096]----+
|                 |
|     o .    E    |
|    ..+    o     |
|    ....  +      |
|   . o. S. +. . .|
|    . +o+ ++.o = |
|     .+=+o+o*.+  |
|     o.=+ooXo..  |
|      .+=++o=o.. |

Now we’re ready to copy the public key (id_rsa.pub in my example above) to the raspberrypi. You can do this a few ways, most common is via the ssh-copy-id command.

ssh-copy-id -i ~/.ssh/id_rsa ted@raspberrypi

This instructs the built in ssh-copy-id command to copy the default id_rsa key to ~/.ssh/authorized_keys file (setting it’s permissions if it’s not already set) on the server after logging in with ted@raspberrypi’s account details. The private key is never touched and should be kept secure. You will be prompted to login to the raspberrypi server.

If you opt to manually copy your public key to your server, you’ll have to setup your SSH folders securely:

mkdir -p $HOME/.ssh
chmod 0700 $HOME/.ssh
nano $HOME/.ssh/authorized_keys
chmod 600 $HOME/.ssh/authorized_keys

You can then paste in the public key from your main machine into the authorized_keys file. For simplicity the environment variables are used above so it will use the current users home folder.

Alternatively, you can allow others to read authorized_keys by replacing the chmod 600 with a chmod 644 as it contains your public keys.

The best practices for the .ssh folder are summarised below - with an example of a github key:

| Directory or File      | Recommended | Alternative |
|                        | Permissions | Permissions |
| ~/.ssh/                |    700      |             |
| ~/.ssh/authorized_keys |    600      |    644      |
| ~/.ssh/known_hosts     |    600      |    644      |
| ~/.ssh/config          |    600      |             |
| ~/.ssh/id_rsa          |    600      |             |
| ~/.ssh/github_rsa      |    600      |             |
| ~/.ssh/id_rsa.pub      |    600      |    644      |
| ~/.ssh/github_rsa.pub  |    600      |    644      |

Keep in mind, that you’ll want to restrict your private keys (id_rsa/github_rsa) with 600 but your public key (ida_rsa.pub/github_rsa.pub) that you share can be 644. If chmod confuses you, you can use the chmod calculator. ACLs can be tricky.

Enforce Key-Based Auth

To enforce key-based authentication and disable password login, modify the sshd_config file with your favourite text editor:

sudo vi /etc/ssh/sshd_config

Find these lines and modify them as below:

PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no

Once you exit, don’t forget to reload the SSH service:

sudo service ssh reload

Wrapping up

Once you’ve done all that, it’s time to head out and explore what you can do with your Pi - make sure you keep that private key secure as it’s the key to get in!

One final tip, if you want to see what’s running on your instance, you could use top but from Buster onwards, we finally have htop (installed by default) which provides a sublime task-manager like process visualisation. One of the first things I always install on any Linux install.

Related Articles