2021-11-24
md
Setting up a Raspberry Pi as a Headless Computer (September 2021)
Home Automation System on a Raspberry Pi-> <-Installation and Configuration of Raspbian Buster Lite old 2019 vers
 Draft of the first part of a projected multi-part guide 

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

  1. Preamble for First Time Readers
    1. Opening a Terminal
    2. Presentation of Sessions
  2. The Raspberry Pi as a Headless Computer
  3. Getting Raspberry Pi Imager
  4. Getting Raspberry Pi OS on an SD card
    1. Choose the Operating System
    2. Choose the Storage Device
    3. Set the Advanced Options
    4. Write the OS
  5. Initial Boot
    1. Older Versions of Windows 10
    2. Possible Login Complications
    3. Possible Failures
  6. Change the Default Password and User Name
  7. Upgrade the Operating System
  8. Static IP Addresses
  9. Extras
    1. Hardware Configuration
    2. Disable IPv6
    3. mDNS Advertising
    4. Network Syslog Server
    5. Virtual Python Environments
    6. Shell Configuration
    7. Further Hardening

Preamble for First Time Readers toc

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 toc

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:

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 toc

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.

michel@hp:~$ ping damus.local -c 4 PING damus.local (192.168.1.139) 56(84) bytes of data. 64 octets de 192.168.1.139 (192.168.1.139) : icmp_seq=1 ttl=64 temps=147 ms ... --- statistiques ping damus.local --- 4 paquets transmis, 4 reçus, 0 % paquets perdus, temps 3005 ms rtt min/avg/max/mdev = 4.492/40.304/147.138/61.680 ms

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:

michel@hp:~$ ping damus.local -c 4Enter

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.

C:\Users\michel>ping damus.local Pinging damus.local [192.168.1.139] with 32 bytes of data: Reply from 192.168.1.139: bytes=32 time=71ms TTL=64 ... Ping statistics for 192.168.1.139: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 5ms, Maximum = 71ms, Average = 22ms

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 toc

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.

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.

What is a Remote Session? Show

Getting Raspberry Pi Imager toc

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

Opening Pi Imager package with GDebi Package Installer in the Caja File Manager

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.

Installing Pi Imager with GDebi Package Installer

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 toc

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.

Opening screen of Raspberry Pi Imager

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 toc

The easiest way to copy the Raspberry Pi OS Lite image onto an SD card is select Raspberry Pi OS (other) option

Operating system menu in Pi Imager

and and then select the Lite OS in the next screen.

Selecting Raspberry Pi OS Lite for on-the-fly installation

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.

WARNING

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 MB
which 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.

So a decision must be made: get the newest Bullseye version of Raspberry Pi OS Lite and struggle with using Raspberry Video modules and perhaps other devices until the teething problems are solved or use the Buster version of the operating system for the time being. Note that both versions are built on the same Linux kernel. Because I always wait until at least the first revision before switching to a new version of Raspberry Pi OS (or Raspbian as it was previously known), I have not worked with Bullseye yet. It will be a while before I update these pages.

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.

Selection of a downloaded OS image to copy to the SD card in the Pi Imager

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 toc

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.

Selection of the destination drive on which to copy the OS image in Pi Imager

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 toc

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.

Avanced Options in Pi Imager

As can be seen above, the following options were set.

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 toc

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 toc

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.

michel@hp:~$ ping damus.local -c 4 PING damus.local (192.168.1.139) 56(84) bytes of data. 64 octets de 192.168.1.139 (192.168.1.139) : icmp_seq=1 ttl=64 temps=147 ms 64 octets de 192.168.1.139 (192.168.1.139) : icmp_seq=2 ttl=64 temps=4.49 ms 64 octets de 192.168.1.139 (192.168.1.139) : icmp_seq=3 ttl=64 temps=4.82 ms 64 octets de 192.168.1.139 (192.168.1.139) : icmp_seq=4 ttl=64 temps=4.77 ms --- statistiques ping damus.local --- 4 paquets transmis, 4 reçus, 0 % paquets perdus, temps 3005 ms rtt min/avg/max/mdev = 4.492/40.304/147.138/61.680 ms

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.

michel@hp:~$ ssh pi@damus.local Warning: Permanently added the ECDSA host key for IP address '192.168.1.139' to the list of known hosts. nostra@damus.local's password: ********** Linux damus 5.10.52-v7+ #1441 SMP Tue Aug 3 18:10:09 BST 2021 armv7l The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Fri Aug 20 18:56:27 2021 from 192.168.1.100

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.

Microsoft Windows [Version 10.0.19041.1165] (c) Microsoft Corporation. All rights reserved. C:\Windows\system32>ping damus.local Pinging damus.local [192.168.1.139] with 32 bytes of data: Reply from 192.168.1.139: bytes=32 time=1ms TTL=64 Reply from 192.168.1.139: bytes=32 time=4ms TTL=64 Reply from 192.168.1.139: bytes=32 time=5ms TTL=64 Reply from 192.168.1.139: bytes=32 time=6ms TTL=64 Ping statistics for 192.168.1.139: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 1ms, Maximum = 6ms, Average = 4ms C:\Windows\system32>ssh pi@damus.local The authenticity of host 'damus.local (192.168.1.139)' can't be established. ECDSA key fingerprint is SHA256:8oqRJhXo+/kL+Oo7r1KEQXSgmtkSy3UyO2H8K+Ko7bb. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added 'damus.local,192.168.1.139' (ECDSA) to the list of known hosts. nostra@damus.local's password: ********** Linux damus 5.10.52-v7+ #1441 SMP Tue Aug 3 18:10:09 BST 2021 armv7l The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law.

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 toc

If using a Windows 10 desktop or portable in which ping does not find the Raspberry Pi given its host name, as shown here:

C:\Users\michel\Documents>ping damus.local Ping request could not find host smith.local. Please check the name and try again.

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.

@echo off IF "%~1"=="-?" GOTO usage IF "%~1"=="?" GOTO usage IF "%~1"=="/?" GOTO usage IF "%~1"=="-h" GOTO usage IF "%~1"=="h" GOTO usage IF "%~1"=="/h" GOTO usage IF "%~3"=="" GOTO defaultsub set sub=%~3 GOTO subdone :defaultsub set sub=192.168.0 :subdone IF "%~2"=="" GOTO defaultlast set /A last=%~2 GOTO lastdone :defaultlast set /A last=254 :lastdone IF "%~1"=="" GOTO defaultfirst set /A first=%~1 GOTO firstdone :defaultfirst set /A first=1 :firstdone FOR /L %%A in (%first%,1,%last%) DO ( ping -n 1 -w 250 %sub%.%%A > NUL @echo pinging %sub%.%%A ) @echo Arp entries for Raspberry Pi's arp -a | findstr b8-27-eb GOTO fini :usage @echo Find Raspberry Pi's connected to a LAN @echo. @echo Syntax @echo %0 [first [last [subnet]]] @echo 'first' and 'last' values of range of IP addresses to ping @echo 'subnet' is the subnet of IP addresses to ping @echo. @echo Examples: @echo %0 @echo Will ping 192.168.0.1 to 192.168.0.254 and then show the relevant arp table @echo In other words the @echo default value of first is 1 @echo default value of last is 254 @echo default value subnet is 192.168.0 @echo. @echo %0 100 200 192.168.1 @echo Will ping 192.168.1.100 to 192.168.1.200 and then show the relevant arp table @echo Note the abscences of a trailing period in the subnet. :fini

The batch file can be downloaded with the following link: findrpis.bat.

ARP and IP Addresses - How the Script Works Show

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.

C:\Users\michel\Documents>findrpis 100 200 192.168.1 pinging 192.168.1.100 pinging 192.168.1.101 ... pinging 192.168.1.199 pinging 192.168.1.200 Arp entries for Raspberry Pi's 192.168.1.114 b8-27-eb-11-11-11 dynamic 192.168.1.139 b8-27-eb-22-22-22 dynamic

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.

C:\Users\michel\Documents>ssh nostra@192.168.1.139 nostra@192.168.1.139's password: ********** Linux damus 5.10.52-v7+ #1441 SMP Tue Aug 3 18:10:09 BST 2021 armv7l The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Thu Aug 26 20:45:15 2021 from 192.168.1.147

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 toc

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.

michel@hp:~$ ssh pi@damus.local The authenticity of host 'damus.local (192.168.1.139)' can't be established. ECDSA key fingerprint is SHA256:8oqRJhXo+/kL+Oo7r1KEQXSgmtkSy3UyO2H8K+Ko7bb. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added 'damus.local' (ECDSA) to the list of known hosts. Warning: the ECDSA host key for 'damus.local' differs from the key for the IP address '192.168.1.139' Offending key for IP in /home/michel/.ssh/known_hosts:55 Are you sure you want to continue connecting (yes/no)? yes pi@damus.local's password: ********** Linux damus 5.10.17-v7+ #1414 SMP Fri Apr 30 13:18:35 BST 2021 armv7l The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. pi@damus:~ $

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.

michel@hp:~$ ssh nostra@192.168.1.139 nostra@192.168.1.139's password: ********** Linux damus 5.10.52-v7+ #1441 SMP Tue Aug 3 18:10:09 BST 2021 armv7l ... Last login: Sun Aug 22 18:14:57 2021 from 192.168.1.16

Possible Failures toc

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 toc

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.

pi@damus:~ $ sudo raspi-config

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.

pi@damus:~ $ passwd Changing password for pi. Current password: ********* New password: yyyyyyyyyy Retype new password: yyyyyyyyyy passwd: password updated successfully

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

pi@damus:~ $ sudo useradd -m safeuser -s /bin/bash pi@damus:~ $ sudo passwd safeuser New password: xxxxxxxx Retype new password: xxxxxxxx passwd: password updated successfully pi@damus:~ $ sudo usermod -a -G sudo safeuser pi@damus:~ $ grep sudo /etc/group sudo:x:27:pi,safeuser pi@damus:~ $ exit logout Connection to damus.local closed.

Log in as safeuser and check the user id

michel@hp:~$ ssh safeuser@damus.local ... safeuser@damus:~ $ id uid=1001(safeuser) gid=1001(safeuser) groups=1001(safeuser),27(sudo)

Create a backup archive of files that are about to be modified

safeuser@damus:~ $ cd /etc safeuser@damus:~ $ sudo tar -cvf authfiles.tar passwd group shadow gshadow sudoers subuid subgid systemd/system/autologin@.service sudoers.d/010_pi-nopasswd sudoers.d/010_pi-nopasswd [sudo] password for safeuser: xxxxxxxx passwd group shadow gshadow sudoers subuid subgid systemd/system/autologin@.service sudoers.d/010_pi-nopasswd

Change the default user name pi to nostra in all those files

safeuser@damus:~ $ sudo sed -i.$(date +'%y%m%d_%H%M%S') 's/\bpi\b/nostra/g' passwd group shadow gshadow sudoers subuid subgid systemd/system/autologin@.service sudoers.d/010_pi-nopasswd safeuser@damus:/etc $ grep nostra /etc/group adm:x:4:nostra dialout:x:20:nostra cdrom:x:24:nostra sudo:x:27:nostra,safeuser audio:x:29:nostra video:x:44:nostra plugdev:x:46:nostra games:x:60:nostra users:x:100:nostra input:x:105:nostra netdev:x:109:nostra

Rename the pi home directory and create a symbolic link to /home/pi

safeuser@damus:/etc $ sudo mv /home/pi /home/nostra safeuser@damus:/etc $ sudo ln -s /home/nostra /home/pi safeuser@damus:/etc $ ls -l /home total 8 drwxr-xr-x 3 nostra nostra 4096 Aug 17 18:15 nostra lrwxrwxrwx 1 root root 12 Aug 20 18:53 pi -> /home/nostra drwxr-xr-x 3 safeuser safeuser 4096 Aug 20 18:24 safeuser michel@hp:~$ safeuser@damus:/etc $ exit logout Connection to damus.local closed.

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

michel@hp:~$ ssh nostra@damus.local Warning: the ECDSA host key for 'damus.local' differs from the key for the IP address '192.168.1.139' Offending key for IP in /home/michel/.ssh/known_hosts:55 Matching host key in /home/michel/.ssh/known_hosts:65 Are you sure you want to continue connecting (yes/no)? yes nostra@damus.local's password: ********** Linux damus 5.10.52-v7+ #1441 SMP Tue Aug 3 18:10:09 BST 2021 armv7l The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Fri Aug 20 18:13:24 2021 from 192.168.1.100

It is possible to remove user safeuser as long as the account is not being used.

nostra@damus:~ $ sudo userdel safeuser

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 toc

The operating system should be upgraded to ensure that the latest version of all the installed packages is being used.

pi@damus:~ $ sudo apt update && sudo apt full-upgrade -y Get:1 http://archive.raspberrypi.org/debian buster InRelease [32.6 kB] ... Fetched 13.5 MB in 13s (1,022 kB/s) Reading package lists... Done Building dependency tree Reading state information... Done 44 packages can be upgraded. Run 'apt list --upgradable' to see them. pi@damus:~ $ sudo apt full-upgrade Reading package lists... Done ... 44 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. Need to get 146 MB of archives. After this operation, 7,724 kB of additional disk space will be used. ...

About apt, apt-get, update, upgrade and all that Show

Static IP Addresses toc

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.

  1. 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.
  2. 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:

  1. 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 and 192.168.1.129. That will leave IP addresses 192.168.1.1 to 192.168.1.49 and then 192.168.1.130 to 192.168.1.254 available as static addresses.
  2. 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.

nostra@damus:~ $ nano /etc/dhcpcd.conf

# A sample configuration for dhcpcd. # See dhcpcd.conf(5) for details. ... interface wlan0 static ip_address=192.168.1.139/24 static routers=192.168.1.1 static domain_name_servers=8.8.8.8 8.8.8.4

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

nostra@damus:~ $ ip route default via 192.168.1.1 dev wlan0 src 192.168.1.139 metric 303 192.168.1.0/24 dev wlan0 proto dhcp scope link src 192.168.1.139 metric 303

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

interface eth0

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.

# A sample configuration for dhcpcd. # See dhcpcd.conf(5) for details. ... interface eth0 static ip_address=192.168.1.138/24 static routers=192.168.1.1 static domain_name_servers=8.8.8.8 8.8.8.4 interface wlan0 static ip_address=192.168.1.139/24 static routers=192.168.1.1 static domain_name_servers=8.8.8.8 8.8.8.4

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.

nestor@domus:~ $ ip a ... 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether b8:27:eb:11:22:33 brd ff:ff:ff:ff:ff:ff inet 192.168.1.65/24 brd 192.168.1.255 scope global dynamic noprefixroute eth0 ... 3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether b8:27:eb:10:20:30 brd ff:ff:ff:ff:ff:ff inet 192.168.1.139/24 brd 192.168.1.255 scope global noprefixroute wlan0 ...

Of course the IP address of the eth0 interface could be different at another time because it is dynamic.

Extras toc

While the above consitutes a minimum configuration for a headless Raspberry Pi system, there are other steps that I like to take.

Hardware Configuration toc

Now start the configuration utility.

pi@raspberrypi:~ $ sudo raspi-config

This is the opening screen of the configuration.

Opening screen of the raspi-config utility

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.

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 toc

In all likelihood the IP version 6 stack is running on the Raspberry Pi. This is easily checked.

nostra@damus:~ $ ifconfig ... wlan0: flags=4163<tUP,BROADCAST,RUNNING,MULTICAST> mtu 1500 ... inet6 2618:8abf:d820:c868::9 prefixlen 128 scopeid 0x0<global> inet6 68d8::8821:4b9a:2f6811ab prefixlen 64 scopeid 0x20<link> ...

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

net.ipv6.conf.all.disable_ipv6 = 1

in the sysctl configuration file. You will need root privileges for this:

nostra@damus:~ $ sudo nano /etc/sysctl.conf

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 toc

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.

michel@hp:~$ avahi-resolve -n damus.local damus.local 192.168.1.139

The same thing can be done on a macOS system or on a Windows system on which Bonjour is installed.

MacBook:~ michel$ dns-sd -G v4 damus.local DATE: ---Mon 30 Aug 2021--- 15:42:41.822 ...STARTING... Timestamp A/R Flags if Hostname Address TTL 15:42:41.824 Add 40000002 4 damus.local. 192.168.1.139 120 ^C

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.

nostra@doumus:~ $ sudo nano /etc/avahi/avahi-daemon.conf

#publish-workstation=no to publish-workstation=yes

After restarting the avahi service on the Pi

nostra@damus:~ $ sudo systemctl restart avahi-daemon.service

it will advertise itself and thus can be found with avahi-browse.

michel@hp:~$ avahi-browse _workstation._tcp -r ... + enp4s0 IPv4 damus [b8:27:eb:11:11:11] Workstation local ... = enp4s0 IPv4 damus [b8:27:eb:11:11:11] Workstation local hostname = [damus.local] address = [192.168.1.139] port = [9] txt = []

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.

nostra@damus:~$ sudo nano /etc/avahi/services/ssh.service

<?xml version="1.0" standalone="no"?> <!DOCTYPE service-group SYSTEM "avahi-service.dtd"> <service-group> <name replace-wildcards="yes">%h - SSH</name> <service> <type>_ssh._tcp</type> <port>22</port> </service> <service> <type>_sftp-ssh._tcp</type> <port>22</port> </service> </service-group>

After the file is created and the avahi-daemon has been restarted, then the Pi will show up three times:

michel@hp:~$ avahi-browse --all ... + enp4s0 IPv4 damus [b8:27:eb:11:11:11] Workstation local ... + enp4s0 IPv4 damus - SSH SSH Remote Terminal local + enp4s0 IPv4 damus - SSH SFTP File Transfer local ...

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.

MacBook:~ michel$ dns-sd dns-sd -B _ssh._tcp Browsing for _ssh._tcp DATE: ---Mon 30 Aug 2021--- 21:32:17.212 ...STARTING... Timestamp A/R Flags if Domain Service Type Instance Name ... 21:32:17.643 Add 2 4 local. _ssh._tcp. damus - SSH ^C MacBook:~ michel$ dns-sd dns-sd -B _workstation._tcp Browsing for _workstation._tcp DATE: ---Mon 30 Aug 2021--- 21:34:15.165 ...STARTING... Timestamp A/R Flags if Domain Service Type Instance Name 21:34:15.604 Add 2 4 local. _workstation._tcp. damus [b8:27:eb:11:11:11] ^C

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 toc

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.

nostra@goldberg:~/pythons $ sudo nano /etc/rsyslog.conf

# /etc/rsyslog.conf Configuration file for rsyslog. # # For more information see # /usr/share/doc/rsyslog-doc/html/rsyslog_conf.html ################# #### MODULES #### ################# module(load="imuxsock") # provides support for local system logging module(load="imklog") # provides kernel logging support #module(load="immark") # provides --MARK-- message capability # provides UDP syslog reception module(load="imudp") <-- enabled by removing leading '#' input(type="imudp" port="514") <-- enabled by removing leading '#' # provides TCP syslog reception #module(load="imtcp") #input(type="imtcp" port="514")

Logs in Linux Show

Virtual Python Environments toc

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.

nostra@damus:~ $ sudo apt install python3-dev python3-venv -y Reading package lists... Done ... Need to get 49.8 MB of archives. After this operation, 75.8 MB of additional disk space will be used. ...

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.

nostra@damus:~ $ mkdir -p .local/bin nostra@damus:~ $ wget http://sigmdel.ca/michel/program/python/dnld/mkvenv.ubuntu -O .local/bin/mkvenv nostra@damus:~ $ chmod +x .local/bin/mkvenv

Creating a virtual environment named say penv will then be as simple as

nostra@damus:~ $ .local/bin/mkvenv penv creating virtual environment /home/nostra/penv updating virtual environment /home/nostra/penv

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 toc

Let's check that .local/bin will be added to the PATH environment variable when opening a session on the Pi.

nostra@damus:~ $ nano .profile

The file should contain the following.

# if it exists include ~.local/bin in the PATH if [ -d "$HOME/.local/bin" ] ; then PATH="$HOME/.local/bin:$PATH" fi

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.

nostra@damus:~ $ nano .bashrc

ve() { source $1/bin/activate; } alias ev='deactivate'

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.

nostra@damus:~ $ mkvenv test/penv1 test/penv2 creating virtual environment /home/nostra/test/penv1 updating virtual environment /home/nostra/test/penv1 creating virtual environment /home/nostra/test/penv2 updating virtual environment /home/nostra/test/penv2 nostra@damus:~ $ ve test/penv1 (penv1) nostra@damus:~ $ ... (penv1) nostra@damus:~ $ ev nostra@damus:~ $ ve /home/nostra/test/penv2 penv2) nostra@damus:~ $ ... (penv2) nostra@damus:~ $ ev

Note that the ve macro takes the relative or absolute path to the virtual environment.

Further Hardening toc


This is a rewrite of this section. The original version, which involved modification of the configuration file /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.

pi@damus:~ $ sudo useradd -m safeuser -s /bin/bash pi@damus:~ $ sudo passwd safeuser New password: xxxxxxxx Retype new password: xxxxxxxx passwd: password updated successfully safeuser@damus:~ $ sudo adduser safeuser sudo [sudo] password for safeuser: xxxxxxxx Adding user `safeuser' to group `sudo' ... Adding user safeuser to group sudo Done.

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.

nostra@damus:~ $ sudo nano -B /etc/pam.d/sshd

Why the -B parameter? Show

Here is the beginning of the modified sshd file in which the extra entry and accompanying comment are shown in bold.

# PAM configuration for the Secure Shell service # Lock out for 5 minutes anyone (except root) that fails an ssh login 2 times auth required pam_tally2.so onerr=fail deny=2 unlock_time=300 audit # Standard Un*x authentication. @include common-auth ...

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.

michel@hp:~$ ssh safeuser@damus.local safeuser@damus.local's password: <incorrect_password> Permission denied, please try again. safeuser@damus.local's password: <incorrect_password> Permission denied, please try again. safeuser@damus.local's password: <correct_password> safeuser@damus.local: Permission denied (publickey,password).

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.

michel@hp:~$ ssh nostra@damus.local nostra@damus.local's password: xxxxxxxxxxxx Linux damus 5.10.52-v7+ #1441 SMP Tue Aug 3 18:10:09 BST 2021 armv7l ... nostra@damus:~ $ sudo pam_tally2 -u safeuser Login Failures Latest failure From safeuser 3 09/22/21 20:00:09 192.168.1.13

One could also look at the auth.log file.

nostra@damus:~ $ tail /var/log/auth.log ... Sep 22 20:00:01 domus sshd[1184]: Failed password for safeuser from 192.168.1.13 port 49828 ssh2 Sep 22 20:00:05 domus sshd[1184]: Failed password for safeuser from 192.168.1.13 port 49828 ssh2 Sep 22 20:00:09 domus sshd[1184]: pam_tally2(sshd:auth): user safeuser (1001) tally 3, deny 2 Sep 22 20:00:11 domus sshd[1184]: Failed password for safeuser from 192.168.1.13 port 49828 ssh2 Sep 22 20:00:12 domus sshd[1184]: Connection closed by authenticating user safeuser 192.168.1.13 port 49828 [preauth]

User nostra can restore the ability to login immediately for the locked out safeuser by resetting that user's login failure counter.

nostra@damus:~ $ sudo pam_tally2 -u safeuser --reset Login Failures Latest failure From safeuser 3 09/22/21 20:00:09 192.168.1.13 checking : nestor@domus:~ $ sudo pam_tally2 -u safeuser Login Failures Latest failure From safeuser 0

More details than needed? Show

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.

Home Automation System on a Raspberry Pi-> <-Installation and Configuration of Raspbian Buster Lite old 2019 vers