It is long past the time to update my posts about setting up a Raspberry Pi as a server. Changes to Debian based operating systems such as the Raspberry Pi OS (formally called Raspbian) are usually incremental, so most of the late 2019 three-part guide starting with Installation and Configuration of Raspbian Buster Lite remains valid. However there are some changes. The most important is the arrival of the Raspberry Pi Imager which greatly simplifies installing the OS on a headless Pi right from the start. Although this post is mostly Linux centric, I have included more hints for Windows 10 users and even some information for macOS users. Of course, these operating systems are on a desktop or portable computer that will be used to communicate with the Raspberry Pi. Almost always the latter runs a version of Linux.
The first section of this post is for those unfortunate souls that have never been to this site. It explains how I present procedures and material in my posts. This is very basic stuff, probably obvious from the start and it can be skipped by the vast majority of readers. The same is true for the second section unless "headless computer" or "server" are terms that mean nothing. That second section does contain a second part with a cursory description of what a remote session is. Because it is really meant for beginners with a minimum of knowledge of Linuxy things, it is presented as a sidebar (actually a drop-down block of text) in the hope that it will not interfere too much with the flow of the main text. There are other similar sidebars later in the post. Sections 3, 4 and 5 are considerably different from the previous post by taking full advantage of Raspberry Pi Imager. I also provide different strategies for finding the IP address of the Raspberry Pi. For Windows 10 users that may not have the very latest version of the OS, there is a novel fallback method ("novel" as in new for this site). The rest of the post is pretty much the same as before except for a less frequently used approach to protect the Pi from brute force login attacks.
Table of Contents
- Preamble for First Time Readers
- The Raspberry Pi as a Headless Computer
- Getting Raspberry Pi Imager
- Getting Raspberry Pi OS on an SD card
- Initial Boot
- Change the Default Password and User Name
- Upgrade the Operating System
- Static IP Addresses
- Extras
Preamble for First Time Readers
This post, along with most others on this site, attempts to provide information in a format that newcomers to the world of digital electronics tinkering can easily follow. Hopefully, the post will be a useful mix of instructions and explanations that summarize what I have just learned on a topic. This is a compromise that will be unpalatable for the impatient, that only want the minimum steps to arrive at a desired result, and the theorist that wants to achieve full understanding before committing to action. Such is the pitfall of compromise.
Opening a Terminal
Most of what is presented here is done with commands entered using the keyboard at a shell prompt in a terminal. You will need to know how to start a terminal in your desktop environment.
In Linux
On many Linux systems the keyboard shortcut AltCtrlT starts a new terminal window. On my Mint 20.1 Mate desktop, I also have a terminal icon on the toolbar and there is a terminal menu entry in the main menu under system tools
. Also, both the builtin Caja file manager and DoubleCommander file manager that I install on all my systems have menu options to start a terminal in a given directory.
In Windows 10
There are at least two different terminals in Windows 10:
- Command: use the keyboard shortcut WindowR and then to type
cmd
in theOpen
text box, - Power Shell: click on the start menu icon with the right mouse button and select
Windows PowerShell
in the menu.
One could even open a Linux terminal in Windows 10 if WSL is enabled on the machine. However, if you know how to do that then you do not need to be reading this.
In macOS
There are many ways to start the terminal in macOS, perhaps the easiest is to use the keyboard shortcut cmd<space> and then to type terminal
in the Spotlight search box. If the terminal is to be used regularly, it might be easier to add it to the dock so that it remains one click away.
Presentation of Sessions
Here is an example, taken from later on in the post, of how a session or part of a session is presented on this site. It shows how to use a ping
command on a Linux desktop machine to find a Raspberry Pi located on the local area network.
When the output printed on the terminal by a command is too long, parts of it will be removed and replace by a single line containing an ellipsis (to be precise, three consecutive periods in lieu of an ellipsis). In this example only the first ping
result is shown, the other three are replaced with the ellipsis.
The host name of my desktop is hp
and my user name is michel
, hence the shell starts each command line with michel@hp:
. After the colon, comes the present working directory (pwd
in the jargon). In this case it is initially ~
which is short for the current user home directory which here is /home/michel
. Finally, the shell writes the prompt which here is $
. It can be different dependant on the user and the shell being used. That's Linux for you, there is more than one shell.
The command shown on a greenish background is the part that I entered using the keyboard. As each key is struck, the shell "prints" the corresponding character on the screen. Unfortunately, there is an implied key stroke at the end of the command. The Enter key has to be pressed on the keyboard to signal that text entry is completed and that the shell should then try to make sense of what has been entered. Perhaps I should have adopted a more complete representation of the command such as this one:
Unfortunately, there is no universal label or symbol for the Enter key, so I never settled on a satisfactory way to indicate that key stroke. Besides, I am too lazy to type in the particular string needed to display that implied keypress: <span class="key" style="background: gray">Enter</span>
.
Here is how the same command in a Windows 10 terminal (PowerShell or not). It is not uncommon to find very similar command line utilities in Windows 10, Linux and macOS sometimes with slightly different command line parameters (as in this case) or sometimes with different names such as findstr
and grep
.
Hint
If following along, it is not necessary to type the commands shown. The screen images shown above are not screen captures and it is possible to copy any command with the green background into the clipboard and then to paste it at the prompt in a terminal window. Assuming that I did not make any mistake when recording the command from my terminal into the source file of this post, you will avoid typing mistakes using copy/paste. Again, just remember to press the Enter key after typing each command so that the shell knows that you are done and that it is time for it to do its job.
The Raspberry Pi as a Headless Computer
Given that the combined cost of a monitor, keyboard and mouse can be a multiple of the cost of a Raspberry Pi, it makes sense to forego them whenever possible. Of course the absence of these commonly used peripherals to control the Pi does limit its possible uses, but there are numerous tasks which lend themselves to such an arrangement. Here are some headless server configurations that I have with the Raspberry Pi and other single-board computers.
- A CUPS printer server which turned an old HP USB printer no longer supported in Windows into a network printer accessible from any computer on the local area network.
- A Domoticz based home automation server.
- An MQTT broker which is the glue between Domoticz and my IoT devices.
- An HTTP server used to upload firmware updates to IoT devices
- A centralized system log server
- An audio media server using MPD or MOC
Once the decision has been made to use a single-board computer as a headless server, it seems natural to want to set up the server without connecting a monitor, keyboard and mouse to it. In that case, control of the Raspberry Pi will have to be done remotely using the SSH protocol. That means that the Pi must be connected to the same local network (LAN) as the desktop computer and SSH must be enabled on the Raspberry Pi. If the Pi will have only a wireless connection to the LAN then it must know the Wi-Fi network name and password right from the start. All this can now be done very easily as explained below.
Getting Raspberry Pi Imager
As instructed in Installing the Operating System in the new look (as of August 2021) Raspberry Pi Documentation, I used Raspberry Pi Imager to copy the operating system image onto an SD card. In the past, I used balenaEtcher (previously Etcher) and the dd
utility before that. However, the relatively new Raspberry Pi Imager greatly simplifies this task, especially when creating a headless system.
Use the above link to download the appropriate Imager
for the machine that will be used to write the operating system to an SD card. Once the package has been downloaded, it will need to be installed.
Linux
Right click on the downloaded .deb
file (currently named imager_1.6.2_amd64.deb
for Ubuntu x86) with the right mouse button in a file browser and choose the option to Open with GDebi Package Installer
As can be seen, the installer will take care of all the dependencies. In other words it will install 10 other packages that are needed by Imager.
Click on the Install Package button.
Actually I used the exact same procedure to update from version 1.6 already present on my desktop to version 1.6.2 of the Imager.
Windows 10
Double click on the downloaded file in the file browser (currently the file is imager_1.6.2.exe
) and then click on the Install button. Click on the Finish button once the installation is complete.
Getting Raspberry Pi OS on an SD Card
The first step is to launch the Raspberry Pi Imager
.
Linux
In my Mint 20.1 Mate desktop, it can be found in the Accessories
menu or it can be found by searching for imager
in the main menu search box. In all Linux systems, it should be possible to start the application from a terminal with the rpi-imager
command.
Windows 10
In Windows 10, the program, called oddly enough Raspberry Pi Imager
can be found in the start menu under the letter R. It is also possible to start it from the Run
utility (right click on the Start menu or press the WindowR keyboard combination). Enter rpi-imager
in the Open
text box.
No matter how the program is started here is its start screen.
While it does looks like copying the operating system is a three-step procedure, setting some options in a fourth step will make it possible to open SSH sessions with the headless Raspberry Pi connected to the LAN with Wi-Fi.
Choose the Operating System
The easiest way to copy the Raspberry Pi OS Lite image onto an SD card is select Raspberry Pi OS (other)
option
and and then select the Lite OS in the next screen.
In this fashion, Imager will obtain the latest compressed image from the Raspberry Pi site on the fly and then proceed to install it on an SD card as instructed in the last step described below.
When I wrote these notes back in September 2021, I was installing
Raspberry Pi OS Lite Release date: May 7th, 2021 Kernel version: 5.10 Size: 444 MBwhich is based on Debian Buster. This version is no longer directly downloadable with Image as shown above. This is because a newer version of Raspberry Pi OS (Lite or Desktop) based Debian Bullseye is available.
Raspberry Pi OS Lite Release date: October 30th, 2021 Kernel version: 5.10 Size: 463 MB
One month on (2021-11-24), I would not yet use the Bullseye version. I have noticed that many who use video cameras with the Pi have run into problems with the new version. As I warned in the third part of the series, "... raspistill
and raspivid
are both based on the legacy Raspicam camera stack that may soon be deprecated" (source). Well, "soon" is now and the utilities are not in the October version of the operating system.
I prefer to download the operating system image and then use Imager to copy the downloaded image file to an SD card. If you are willing to risk being to the "bleeding edge" then download the October 30th version of Raspberry Pi OS Lite onto your desktop (please read the above note on why you may not want to do that). If you want to replicate what is shown in this multipart guide, download the May 7th version of Raspberry Pi OS Lite. By the way, https://downloads.raspberrypi.org/ contains most if not all OS images released by the Pi Foundation.
To use an already downloaded operating system image, select the last option (Use custom
) in the initial CHOOSE OS
screen.
The wanted image can then be specified with a file selection dialog whose appearance will depend on the operating system of the desktop.
Of course, the full desktop version of Raspberry Pi OS could be installed and it will be possible to do everything described in this guide. However the guide will always show how to proceed with an SSH session which is in effect a remote terminal so it will not provide any instructions for those operations that could be done in the Raspberry Pi graphic user interface.
Choose the Storage Device
The drive containing the SD card onto which the operating system will be installed has to be identified. Click on the CHOOSE STORAGE button in the initial screen of the Imager
. It will then display a list of target drives.
In my case it was particularly easy to find the drive since only one was displayed. Be careful in this step, because whichever drive is chosen its content will be obliterated when the OS is written.
Set the Advanced Options
If a keyboard and monitor is to be connected to the Raspberry Pi which will be connected to the local network with an Ethernet cable, then this step can be skipped because everything done in this step can be done with the raspi-config
utility on the Raspberry Pi once it is running. However, the Raspberry Pi which hosts my home automation system is not easily accessible and can only be connected to the local network by Wi-Fi. It makes much more sense to run this Pi as a headless machine from the very start. In that case, it is necessary to define the WiFi credentials before the first boot of the machine.
To get to the Advanced options
, press the CtrlShiftx keyboard combination (on a MAC use the cmdShiftx combination). This will bring up a new window with a list of options.
As can be seen above, the following options were set.
- Hostname
- SSH
- Wi-Fi
- locale (time zone only)
Host names should be unique on a network, so it is best to change it from the very start, especially as we rely on the hostname to connect to the Raspberry Pi. I suppose the time zone does not strictly need to be set, but my home automation server, Domoticz, is rather finicky about time, so again it is worthwhile to set that value correctly. Just find a city near you that is in the same time zone. Since a keyboard will never be connected to the Pi, there was no point in changing the keyboard layout even if I do not use the standard US QWERTY layout.
If the Pi can be connected to the local area network with an Ethernet cable, then there is no need to configure the Wi-Fi interface at this point. However, in my case it does make things a lot simpler to enable Wi-Fi before the first boot. Of course the correct Wi-Fi network name (SSID
) and password must be entered if relying on a wireless connection. Do not forget to set the Wifi country
code. It has to do with channels (radio frequencies) that can be used which are not all the same in all countries.
Finally, it is essential that SSH be enabled in a headless system, otherwise there will be no way to access the Pi. Keep track of the password because the Pi will be a paperweight if it is lost.
Write the OS
Once the operating system and the storage device have been defined in Imager
, the WRITE option is enabled. Click on that button and wait until the utility has finished copying the image to the SD card.
Initial Boot
It is now time for the initial boot. Safely eject the SD card from the desktop reader, then place it in the SD slot of the Raspberry Pi. Power up the Pi and let it complete its boot sequence. Remember that the first boot will probably take longer than usual because the Pi will perform some one-time-only housekeeping tasks such as expanding the file system. So it is best to wait until furious activity on the green LED stops and the red LED is steadily on before trying to connect to the device.
If using a Linux or a MAC desktop or portable, then after a while it will be possible to ping
the Pi using its local hostname. If using a recent version of Windows 10 then almost the same can be done, but see the discussion below for more details about that OS.
That successful ping proves that the Pi connected to the LAN over Wi-Fi as well as reveal its IP address. Therefore, it is now possible to open an SSH session with the PI using either the IP address or, as shown next, using the hostname.
In recent versions of Windows 10 Pro the procedure is almost exactly the same, the only difference is that the count option in the ping
command should not be set.
Which password should be given? If the Raspberry Pi is connected by Wi-Fi to the local network, then the password should be the one explicitly entered in the Imager Advanced options
. If Wi-Fi was not enabled and the Pi is connected to the local network with an Ethernet cable, then the default raspberry
password must be used.
One will truly appreciate the Raspberry Pi Imager if this simple procedure is compared with the numerous, long-winded and not entirely satisfactory approaches to do the same type of thing in my previous posts. Sometimes things do go wrong. The next two sections provide some information about what could be the cause of problems.
Older Versions of Windows 10
If using a Windows 10 desktop or portable in which ping
does not find the Raspberry Pi given its host name, as shown here:
then the OS needs to be updated. Native support for multicast (mDNS
) was added to Windows only quite recently, in version 10.0.19041 I believe. Indeed I do not know if the most recent version of Windows 10 Home supports mDNS
, I have only tested with Windows 10 Pro.
If it is not possible or practical to update Windows, then it will be necessary to connect to the Raspberry Pi with its IP address instead of its host name. There are a number of ways of obtaining that IP address, such as checking the router web admin site to obtain the list of connected devices or using an IP scanner. Note that the first 3 bytes of the MAC address of Raspberry Pi Ethernet and wireless interfaces are always b8:27:eb
. The following batch file, exploits that fact when it attempts to display the IP address of all Raspberry Pi connected to a local network.
The batch file can be downloaded with the following link: findrpis.bat.
The router assigns dynamic IP addresses in the range 192.168.1.100 to 192.168.1.200 on my local network, so it was a simple matter to use the batch file to scan that range of IP addresses and then display all devices entered into the ARP table with a MAC address that corresponds to a Raspberry Pi.
According to the script, only two devices needed to be investigated. I already knew that 192.168.1.114
was an older Pi, so it was possible to log into the Pi using the other IP address.
The discussion about the correct password applies here also: use raspberry
if the Pi is wired to the local network or use the set password if the connection is through a Wi-Fi access point. Even if the correct IP address is used, it may not be possible to open an SSH session or there may be some complications during the initial login as explained in the next two subsections.
Possible Login Complications
If an SSH connection was previously established with the same IP address as the Pi has then the ssh
client will complain and ask for confirmation as shown below.
Exit and open a new SSH session using the IP address: ssh pi@192.168.1.139 and go through a similar routine to open the session. Read carefully the message displayed because it may suggest using the ssh-keygen
command to remove the host key from the client know hosts file (~./ssh/known_hosts
).
If another machine had the damus
hostname, then the ssh
client will complain even more and it will be necessary to remove the old host key using ssh-keygen
before an SSH session can be opened. In any case, the long message from ssh
will say precisely what has to be done.
Once these problems with conflicting SSH keys are resolved, opening an SSH session will be a simple matter of entering the password.
Possible Failures
If the ping
worked but it was impossible to open an SSH session then SSH was probably not correctly enabled in the Imager Advanced options
. If the SSH login was reached meaning that the Pi asked for the user password, but the login failed, then either the user name was incorrectly entered (it has to be a lowercase pi
) or the password entered does not correspond to the value given in the Advanced options
. In all likelihood, the easiest solution is to copy the OS onto the SD card once more, being very careful to enable SSH and to record the user password for pi
.
If ping
cannot find the Raspberry Pi, then double-check the host name. Remember that if there is already a device on the local area network with the same hostname, then the hostname of the new Raspberry Pi will be changed to avoid a name conflict. Had there been another device with the damus
hostname on my LAN, then the Raspberry Pi would be assigned something similar to damus-2.local
as a hostname. Unfortunately, the Raspberry Pi does not advertise itself which means it will not be seen with the avahi-browse --all
command.
It may be that ping
does not work because the Wi-Fi credentials were incorrectly specified in the Imager Advanced options
so that the Raspberry Pi never connected to the Wi-Fi network. In that case then try to connect it to the LAN with an Ethernet cable. Assuming that SSH was correctly enabled in the Advance Options
it should then be possible to open an SSH session and to fix the Wi-Fi credentials with the raspi-config
utility. I have no idea which password will work in this case.
If a Wi-Fi USB dongle is used on a Raspberry Pi that does not have built-in Wi-Fi capability, then there is a possibility that the new version of Raspberry Pi OS does not support the dongle. The only solution in this case is to try with a newer dongle hoping that it is supported by the OS or to connect the Pi to the LAN with an Ethernet cable. In the later case, there is a chance that drivers for the old dongle can be obtained from the Internet (see USB Wi-Fi Dongle in my post entitled Various Hardware with Raspbian Buster Lite.
Finally do not discount the possibility that the SD card is defective. Try to copy the OS image onto a different SD card. It is possible to test SD cards (see Micros SD Cards in my post entitled New Hardware: Micro SD Cards, ReSpeaker 2-Mics Pi HAT and Xiaomi 3G Router.
Change the Default Password and User Name
The first order of business should be to change the pi
user password if it is currently set to the default raspberry
.
This can be done with the raspi-config
utility.
Select 1 System Options - Configure system settings
in the first menu and then S3 Password -; Change password for 'pi' user
in the second menu to change the password. It is actually just as easy to change the password directly.
For added security, it is not a bad idea to change the default user. In
the past, I would simply add a new user and eventually removed the
default user pi
. But that was a hit-or-miss approach which usually
meant hunting down a missing group membership for the new user when something
new did not work. The Raspberry Pi documentation provides the correct procedure to do this: Changing your Username. Instead of following those recommended steps, I followed the procedure outlined by Jim McDonnell at Unix etc. in the article How to Rename the Default Raspberry Pi User. I made a few changes to the procedure to avoid a couple of error messages that occur in the Lite version of the Raspberry Pi OS. So here are the steps in glorious detail.
Create a new (temporary) user, safeuser
Log in as safeuser
and check the user id
Create a backup archive of files that are about to be modified
Change the default user name pi
to nostra
in all those files
Rename the pi
home directory and create a symbolic link to /home/pi
That symbolic link from home/pi
to home/nostra
is just to prevent a problem with downloaded scripts expecting to find something in the /home/pi
.
Log in with the new user name
It is possible to remove user safeuser
as long as the account is not being used.
I left the account in place, just in case something goes horribly wrong and it becomes impossible to open an SSH session as nostra
. Just maybe it would then be possible to fix things by opening an SSH session as safeuser
.
Upgrade the Operating System
The operating system should be upgraded to ensure that the latest version of all the installed packages is being used.
Static IP Addresses
This not strictly necessary but it is highly recommended to set static addresses for the network interfaces that will be used. Recall that Raspberry Pi will be a headless system hosting services such as Domoticz a home automation system and its installation script says:
Domoticz is a SERVER so it needs a STATIC IP ADDRESS to function properly.
I will make two points before going on to show how to proceed.
- Make absolutely sure that the static address about to be assigned to the Raspberry Pi is not used by another device connected to the local network.
- Make absolutely sure that the static address about to be assigned to the Raspberry Pi is not used by another device connected to the local network.
The corollary, is that the static address must be chosen outside of the pool of dynamic IP addresses used by the DHCP server which for most will be the router/gateway provided by the Internet service provider. It is best to do all this within the router/gateway. Here is how one should proceed:
- Make sure that there is a range of IP addresses that cannot be assigned to devices by the DHCP server. On my router this is done by setting the DHCP start IP and DHCP end IP addresses to
192.168.1.50
and192.168.1.129
. That will leave IP addresses192.168.1.1
to192.168.1.49
and then192.168.1.130
to192.168.1.254
available as static addresses. - Assign a static IP address to the PI using the latter's MAC address. In my router, I can go to a
DHCP Reservation
screen that displays a list of connected clients. On finding the Raspberry Pi in that list, I can click on a button which adds the device to a list of clients with a reserved address and then I can manually change the reserved IP address from the current dynamic address to the desired static IP address.
There is no point in being more precise about how to do this, each router will have different procedures. Nevertheless, one should really try to do this because it is totally transparent. As far as the Pi is concerned it is getting a dynamic IP address in the usual fashion, it just happens that it will always be the same (static) address.
If for some reason it is not possible to have the DHCP server assign a fixed IP address to the Raspberry Pi, then one can configure the Raspberry Pi to use a given IP address which my router will call a self-assigned IP address. The static address of a network interface is defined in the dhcpcd
configuration file. I used the Raspberry Pi nano
editor to add four lines at the end of that file defining the static address to be assigned to the Wi-Fi interface.
Of course these values will need to be adjusted depending on the IP subnet of the local network and the IP address of the router/gateway. If not too sure what the IP address of the gateway is and the size of the subnet bit mask (that /24
after the static ip address) then try the running the following command
We can see that the default route of the wlan0
interface (i.e. the Wi-Fi interface) is 192.168.1.1
which is the value assigned to static routers
. The next line says that the subnet is 192.168.1.0/24
which means it has a 24-bit subnet mask (i.e. 255.255.255.0
).
Just which domain name servers should be used can be a bit of a problem. As shown above, the Google public DNS servers (main and backup) are explicitly selected. Some may prefer to use the DNS servers recommended by their Internet service provider (ISP). In that case, the static IP address assigned to domain_name_servers
should be the same as that assigned to routers
. Some care has to be taken here, because using the gateway IP address for DNS purposes may not work depending on the router settings. I learned the hard way that setting the router to use the Google DNS servers and then setting the static domain_name_servers
to 192.168.1.1
will not work. On thinking about it, I realized that the router forwards DNS server addresses to a device only when it requests a dynamic IP address. This does not happen when the PI has a static IP address. You will know very quickly that there is a DNS server problem if pinging Google does not work (i.e., if no reply is obtained when the following command is entered: ping google.com).
If the wired (Ethernet) interface is used to connect the Pi to the local network then its IP address can be set just as before except that the first added line should be
instead of inteface wlan0
. The rest of the entry could be as before.
It is certainly possible to assign static IP addresses to both the Ethernet and wireless interfaces, although the addresses have to be different.
Frankly, I see no reason to do this. If a wired connection is possible then I would use it instead of a Wi-Fi connection as it should be faster and more reliable. My preference is to leave the Ethernet interface configuration unchanged. By default this means that when the Pi is booted, a dynamic IP address is obtained from the LAN DHCP server for the Ethernet interface if the cable is connected. Should the Wi-Fi network become unavailable, because of changed credentials perhaps, then it should then be possible to open an SSH session over the wire to fix the Wi-Fi problem. Just to be clear, the Ethernet interface is not "hot-pluggagle", meaning that it will not be brought up automatically when the cable is connected to a running Pi. So networking has to be restarted after the Ethernet cable is plugged in, but that means it will be necessary to turn the power off and then back on because a Wi-Fi connection is presumably unavailable.
Here is how both the interfaces are brought up by the dhcpcd
service when only the Wi-Fi interface is assigned a static IP address in the configuration file.
Of course the IP address of the eth0
interface could be different at another time because it is dynamic.
Extras
While the above consitutes a minimum configuration for a headless Raspberry Pi system, there are other steps that I like to take.
Hardware Configuration
Now start the configuration utility.
This is the opening screen of the configuration.
The Navigate Tab key (⇥) to move from one control to the next while
the up ↑ and down ↓ cursor
keys move the selection within a menu or list. Select the highlighted choice by pressing on the
↲ or Enter key. The
selection can also be made by "tabbing" to the <Select>
or
<Finish>
control at the bottom and then pressing the Enter key. I suggest that the following changes be
made.
- 3 Interface Options / P2 SSH:
if not already done in theImager Advanced options
choose <Yes> to enable the SSH server. Of course if you accessed the Pi using an SSH connection then this is already enabled. I recommend enabling SSH even if the full Desktop version of Raspberry Pi OS is installed and a keyboard, monitor and mouse hooked up to the Raspberry Pi. - 5 Localisation Options / L2 Timezone:
if not already done in theImager Advanced options
select your continent or region and then select your city or one nearby in the same time zone. As this is a headless system, there is no real advantage to change the locale or keyboard layout. - 4 Performance Options / P2 GPU Memory:
if this Pi will be used as a server it makes sense to allocate as little memory as possible to the graphic processing unit. This is 16 M bytes.
One can also change the user password, hostname and Wi-Fi settings in the 1 System Options, but presumably this is all set up correctly by this time.
If suggested reboot, and then after a while reconnect to the Raspberry Pi. Even if a keyboard and monitor are connected to the Raspberry Pi, it is a good idea to learn how to connect to a Pi that will be used as a server via SSH.
Disable IPv6
In all likelihood the IP version 6 stack is running on the Raspberry Pi. This is easily checked.
The presence of inet6
addresses for any interface indicates that IPv6 is enabled. If you want to use IP version 4 only, then IPv6 must be disabled which is easily done by adding the following line
in the sysctl
configuration file. You will need root privileges for this:
While issuing the command sudo sysctl -p
will update the Linux kernel parameters at runtime, I prefer to reboot the Pi, then open a new session, and then run ifconfig
again to verify that inet6
addresses are no longer showing up.
This is not an argument for disabling IP version 6. It is merely the simplest means I have found to do that should it be useful later on. Thanks to Andrei Bosco B. Torres (andreibosco) for the gist Disabling IPv6. More details are available in an article by John at How to Raspbery entitled How to Really Disable IPv6 on Raspberry PI.
mDNS Advertising
Ping
was used to verify the occurence of the initial boot of the Raspberry Pi. On a Linux system, the Zeroconf tool avahi-resolve
could have been used.
The same thing can be done on a macOS system or on a Windows system on which Bonjour is installed.
As mentioned before, this will not work if the host name is incorrect and may not work if there are multiple machines with the same hostname on the local network. One could try to discover the Pi using the avahi-browse
utility, however, by default the Raspberry Pi does not advertise itself. If it is possible to open a session with the Pi, then changing a line in the avahi
configuration file will enable mDNS
advertizing.
After restarting the avahi
service on the Pi
it will advertise itself and thus can be found with avahi-browse
.
The Pi only shows up as a workstation. If you want it to advertise itself as an SSH terminal capable of file transfers with the SFTP protocol then create an XML file with the needed information.
After the file is created and the avahi-daemon
has been restarted, then the Pi will show up three times:
Of course, one could remove either the _ssh._tcp
or _sftp-ssh._tpc
service in the XML file if wanted. I do not know of an equivalence to avahi-browse --all in the Apple implementation of mdns
, but browsing by service is certainly possible.
Again this is not a recommendation. If ping
and ssh
have no problem reaching the Pi using its .local
hostname, there is little reason to implement mDNS advertising. But if there are many devices on the local network then it may be a good idea to implement this just in case duplicate host names are created.
Network Syslog Server
The Raspberry Pi can be used as a network log server. I do that to take advantage of the logging capabilities of all the Tasmota based IoT devices
(see Syslog Server on Raspbian). For this work, the UDP module of the log server (rsyslog
) has to be enabled.
Virtual Python Environments
I prefer creating separate virtual Python 3 environments to contain various Python scripts that I find useful. This is done to avoid breaking a script when updating a library because a newer version is needed by another script (see Python 3 virtual environments for details). A couple of packages need to be installed to create virtual environments.
I have written a bash script that automates the creation of virtual environments. This will download it to the bash script directory and make it an executable file.
Creating a virtual environment named say penv
will then be as simple as
Actually, now that .local/bin
has been created, it will be automatically be added to the search path whenever a session is started so a simple mkvenv penv will suffice.
Shell Configuration
Let's check that .local/bin
will be added to the PATH
environment variable when opening a session on the Pi.
The file should contain the following.
If not add, add those lines to the file.
Following a suggestion by AndyG, I added a shell function and alias
in my .bashrc
file to simplify activating and deactivating a Python virtual environment.
Here is an example where two virtual environments were created in a subdirectory named test
of the user directory at once, and then each was activated and deactivated in turn. Note that the test
subdirectory which did not exist was created by the mkvenv
script.
Note that the ve
macro takes the relative or absolute path to the virtual environment.
Further Hardening
/etc/pam.d/common-auth
, caused minor authorization problems with a lua script used in the Domoticz watchdog discussed in the next part of this guide.
To "harden a computer" appears to be a catch phrase for increasing the security of the system. But just what is to be done under that moniker is by no means universally endorsed. Certainly changing the default hostname, password, and user name (already done above) are often mentioned. Often suggested is the use of Fail2Ban which is a utility that scans log files to identify and then block IP addresses after too many password failures. Fail2Ban is a powerful Python script capable of monitory access to the secure shell (SSH), to Web pages (HTTP/HTTPS) and others. However at this point only sshd
is enabled on the Pi and the equivalent blocking function can be done with the built-in systemd
login manager.
It is really, really important to have at least two user accounts that are members of the sudo
group before attempting to follow along with what follows. If you changed the default user as described above in Change the Default Password and User Name and did not remove the temporary user account (named saveuser
) then you are good to go. Otherwise create the user account again and make that account a member of the sudo
group as outlined here.
Just to prove that there are many ways to do things, I used adduser
instead of usermod
to add the user to a group.
Reboot and log in with the new user account and do things that require root privileges (such as upgrading the operating system) to test that the new account is working.
As usual, a configuration file must be modified to lock out a user account after a specified number of consecutive failed SSH login attempts. The file, named sshd
, resides in the /etc/pam.d/
directory which contains many Pluggable Authentication Modules
(PAM) configuration files.
-B
parameter?
Show
Here is the beginning of the modified sshd
file in which the extra entry and accompanying comment are shown in bold.
Apparently restarting the sshd
service will enable these changes when opening SSH sessions, but as usual I prefer rebooting to be sure that the changes will work. Below I'll show how I tested this. Be careful when following these, two different user sessions are involved. First let's try to login as safeuser
giving the wrong password twice, just like someone mounting a brute force attack would try many passwords.
As can be seen it was impossible to open a safeuser
session with the correct password on the third attempt. The lockout will last for the next 5 minutes and it will be impossible to log in as safeuser
even with the correct password. While the lockout is in effect, let's check the status of the user account using another user account of course.
One could also look at the auth.log
file.
User nostra
can restore the ability to login immediately for the locked out safeuser
by resetting that user's login failure counter.
I see this as a temporary measure. In the end, once the server is fully operational, I intend to disable password authentication when opening SSH sessions and allow only key based authentication from know users (see Improving SSH Security).
Here is some further reading about hardening a Pi. Raspberry Pi Hardening Guide by Chris Goff and
Security Setup & Hardening of Raspberry Pi OS {Buster} by Bryce W. Bounds. Both of these propose installing fail2ban
to prevent brute force login attacks. If you decide to go that route instead of the above, I also suggest reading the Installing fail2ban piece in the Raspberry Pi documentation.