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
update_config=1
country=au
network={
ssid="PrettyFlyForWiFi"
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:
logout
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_username='ted'
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!
passwd
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.. |
+----[SHA256]-----+
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.