Setting up Packet Radio on a Raspberry Pi (4 thru Zero-W) running Rasbperry Pi OS Bullseye, Buster, Stretch or Jessie

dranch at

This document is intended for new users to both Raspberry Pi SBC computers and the Raspbian based Linux operating system. This doc will help the user create a reliable device that operates as an AX.25 / APRS packet radio system with GPS support. This guide is focused around the Raspbian Linux distribution. This document tries to support any specific quirks around the Bullseye (11.x), Buster (10.0) version of Raspberry Pi OS as well as the now legacy versions like Stretch, Jessie, and Wheezy (non-SystemD based) versions. This document includes optimizations for improved SD card life and OS security hardening for supporting direct connections to the Internet. This setup is also directly manageable via Wifi via say a smartphone/tablet for off-Internet maintenance as well.


0. Intro to setting up a Raspberry Pi and understanding it's quirks

Welcome to the world of the Raspberry Pi, Amateur Radio, and all the possibilities.  No doubt
there is an overwhelming amount of options and many people new to the Raspberry Pi, Linux, etc.
will get confused where to start.  This document hopes to provide some guidance here with a
specific application in mind (see the intro at the beginning of this document of it's goals).

Before you get started, a few thoughts:

   - SD cards: Only use quality, name brand SD cards in your Pi.  It will save you from 
     countless amount lost time, anger of "stability issues with Raspberry Pis" and the overall 
     setup will last a LOT longer (but it won't last forever without backups).

   - Power Supply: Only use a quality USB power supply and not just some old cellphone charger 
     you had laying around the house.  The official Rpi PS is a 5.1volt (not 5.0v) @ 2.5Amp supply 
     with a thick, short and quality made USB cable for many reasons. The new Rpi v4 supply is now 
     3.0 Amp.  Random USB power bricks and cables will not work in your favor.. especially when the 
     Rpi is under load.   If you want to run your Raspberry Pi from a 12v battery, I've had good luck 
     with these inexpensive UBEC DC to DC power bridges:
   - Operating System: Install the Raspberry Pi version of the Linux operating system on it :: 
     This means NEWEST Raspberry Pi OS (was called "Raspbian" before) version to be specific

       - This specific document focuses and RECOMMENDS the use of the Raspberry Pi "Buster" but I'm actively
         validating it with the new "Bullseye" release.  This will take time but it's coming and most things
         should just work.  This document still includes many details for supporting older OS versions 
         like "Buster" or "Stretch" versions but those will be removed over time.   

       - I *highly* recommend you run the newest version of the Raspbian OS available to get the best
         possible support, security fixes, etc.  The current OS release is "Bullseye" as of November

         All older versions such as "Buster", "Stretch", Jessie, Wheezy, etc. are either being phased out or are 
         no longer receiving security patches from the Raspberry Pi Foundation.  For the previous "Buster" release,
         it should continue to receive new kernel updates from the Rpi foundation for a few more months but then
         that will end.  Some updates for non-core OS packages may come from the Debian side but that doesn't mean 
         your Rpi is fully patched.  There are always exceptions to this choice say for people wanting a non 
         non-SystemD enabled OS like Devuan but that's up to you.  

       - New things in various Raspberry Pi OS releases:

            - Bullseye:
                - Display drier for GUI interface now using Linux KMS
                - The LXDE desktop was upgraded from GTK+2 to GTK+3 
                - Dynamic window manager selection based on Rpi hardware
                    >2GB RAM: Mutter
                    <2GB RAM: OpenBox 
                - All Rpi4/CM4 with the "C" revision SOC and the "tri" chip power rail now run each core at 1.8Ghz 
                  vs.  the previous 1.5Ghz
                - New GUI notification system including patches, low voltage, etc
                - GUI tool for OS patching now included
                - Chromium web browser now runs hardware acceleration by default
                - The OS is now using libcamera library instead of previous Broadcom proprietary binary blob
                    - This is evidently a rather disruptive update and all previous commands, tools break
                - The OS has a bit more memory overhead compared to older releases like Buster and earilier

            - Buster
                - LXDE using GTK+2 

       - Code Bloat: It's also worth mentioning that older OS releases might perform better on older Raspberry Pi 
         hardware versions but without bug fixes and security updates, it's just not a good idea to run old
         OS versions unless you can ensure your Raspberry PI isn't connected to any networks, etc.

       - Pre-created SD cards: If you you're starting out with a pre-created microSD card image which was included 
         say in a Raspberry Pi kit and the /etc/os-release file doesn't show "debian 11.x", please consider just 
         re-imaging or replacing the image to have the newest Raspberry Pi OS version available.  Doing this imaging 
         is easy to do as long as you have a micro-SD card reader on an already functioning Windows, Linux, 
         or Mac machine, follow these instructions:


       - Understanding the different versions of Raspberry Pi OS

          - "Desktop with Recommended Software" vs "Desktop" vs "Lite":

                 - The "Raspberry Pi OS with desktop and recommended software" or "full" version of Raspberry Pi OS 
                   includes the full GUI and a full load of additional packages.  If you want a GUI with a desktop 
                   and lots of example programs to use, this "full" version is what you want.  It should be noted 
                   that any GUI version will consume a LOT more RAM and CPU cycles that the non-GUI "Lite" version.

                 - The "Raspberry Pi OS with desktop" or "standard" version of Raspberry Pi OS includes the full GUI
                   interface but does not include a lot of additional packages that I personally find as pretty useless
                   for amateur radio needs.  If you want to run GUI programs via say VNC and what not, this is the version
                   you'll probably want.  It should be noted that any GUI version will consume a LOT more RAM and CPU
                   cycles that the non-GUI "Lite" version.

                 - *RECOMMENDED* : The "Raspberry Pi OS Lite" or "Lite" version of Raspberry Pi OS is the much smaller 
                   and lighter version.  There isn't any offer any GUI support included though it can be added later.  
                   This version is best used for headless operations say running as a packet radio node, etc. and is
                   what I personally use to maximize available RAM, etc.

          - 32bit vs. 64bit:  Raspberry Pi OS Full and Lite versions were traditionally offered as 32bit *only* 
                              which is generally all that's needed on these boards with low memory capacity.  
                              Starting with the Rpi3, the ARM processor was upgraded that supports 64bit instructions.
                              These could offer some performance benefits and address more than 4GB of RAM at the cost 
                              actually increasing the system's average RAM utilization.

                              On the newest Raspberry Pi 4/400/CM4 models, you can get versions with up to 8GB of 
                              RAM to help offset this increased memory usage.  On 02/03/2022, the Raspberry PI Foundation
                              finally made the 64bit version of Bullseye "production grade" from being in BETA for many
                              quarters.  Why did it take so long?  See the comments here for more details:


                              From some of those commentsin that thread, it's clear that the 32bit era is ending as many 
                              programs are dropping 32bit support:

                                 - LibreOffice 7.0 and newer will only be 64bit for the versions released by 
                                   The Document Foundation
                                 - Many published Docker container images are only 64bit now
                                 - Other programs are now only 64bit: Elastic Search, MongoDB, etc

                              Anyway, here are some download URLs for the 64bit BETA images:

                                 Full 64bit GUI version:      none posted as of 03/05/22
                                 Smaller 64bit GUI version:
                                 Lite 64bit CLI-only version:

               Benchmarks with Raspberry Pi OS 64bit from May 2020:

               Some performance benchmarks from Jan 2020:

               As of 5/30/20, the 64bit version of Raspberry Pi OS is in BETA only with various areas of
               hardware acceleration and other items still missing.  If you want to give it a try, see:


        - Why run the Raspberry Pi OS vs other alternative OSes?  

          Yes, there are many other alternative Linux OSes that run on the Raspberry Pi but *none* of them 
          match the focus, support and bug fix cadence of this Raspberry Pi OS / Raspbian for Raspberry Pi hardware.  
          Maybe some distros focused on the Raspberry Pi like DietPi might come to a distant second but it's 
          not going to be to the same level as any OS from the Raspberry Pi Foundation.

          You also might find other pre-made Rpi images from various people for say the DVMega project or other 
          things and I say you should give them a try.  Going with the pre-made image approach makes it easy to 
          try new software stuff by just swapping out different micro-SD flash cards.  Do be wary though...  

           - What is the providence of these images?  Do you trust them?  Why do you trust them?  Are these 
               pre-made images using the official Raspbian OS to benefit from the patches and security?  
           - Were those images built and and secured properly?  
           - Are these images being kept up to date?  

          A quick list of alternative distros (you can find many more here: ):

          Arch Linux : More of a advanced Linux distributions for experienced Linux users

          Debian : This is the basis for Raspberry Pi OS but without many of the useful tools like
                   rasp-config, vcgencmd, and the customized Linux kernel for the Broadcom SOC

          DietPi : This is a Debian based distro focused on the Raspberry Pi but focuses on dramaically reducing
                   it's running RAM utilization and storage requirements

          Devuan : This is debian but not using the SystemD system
          Fedora : A general desktop focused distro

          FreeBSD : FreeBSD for the Raspberry Pi OS

          Gentoo Linux : More of ab advanced Linux distributions for experienced Linux users

          Kali Linux : An advanced security toolkit focused Linux distribution

          OpenSuse: A general desktop focused distro

          RaspBSD : FreeBSD for the Raspberry Pi OS

          Risc OS: A non-Linux kernel based distro

          SARPi / Slackware: A general desktop focused distro

          Ubuntu : A general desktop focused distro

          Windows IOT : A stripped down base Windows kernel for IOT functions
          [There are many others as well]

        There are also other purpose built "appliance" images but I wouldn't call them Linux distributions:  
           - Kodi media player needs: OSMC, OpenElec
           - Retro gaming needs: Batocera, BMC64, Lakka, RetroPie
           - Home automation needs: Domoticz

        Pre-built HAM images:
        - There are some good alternative / pre-configured images that you might consider.  Many of them are 
          not properly maintained IMHO and are getting quite old.  The benefit of using one of these images 
          is that much of the work to get all the packages installed and configured is already done for you.   
          Some even have tools to help with the configuration.  

           .. but a word of Warning on pre-built HAM images:
           I once downloaded a RPI packet radio image from a trustworthy HAM and yet noticed some strange log 
           entries and behavior.  I then did some security investigation and it turns out his Rpi been 
           compromised before he imaged it and then published that image on the Internet!  When I proved this 
           compromise to the image owner, he was shocked and immediately took it down.  It was totally not 
           intended by him but it happened regardless.  There is no free lunch when it comes to easy to install vs. 
           good security here but I bet 95% of the Rpi images out there are good.  Just watch for that last 5%.

   - Security and Patching: 
      - If your Rpi setup is going to be directly connected to the Internet, PLEASE keep the OS patched 
        every week (ideally every day).  Most Raspberry PI OS and even older Raspbian OS releases will follow
        the official Debian LTS patching modeli per Peter Green's post on 11/8/21 @ 8:54pm at .  Debian's LTS schedule is here:

        With that understood, the Raspberry Pi kernel -=* does NOT follow *=- that cadence for it's kernels
        and tools.  Per the above "raspberry-pi-os-debian-bullseye" URL comments, it's understood that when a 
        new Raspberry Pi OS version is released such as Bullseye, all previous OS's will see a significant
        slowdown on getting new updates and will soon stop seeing ANY kernel.  This means that to have the
        most up to date security and bug fixes, you MUST always run the newest OS release from the Raspberry
        Pi Foundation.

      - Other recommended security recommendations:

        - Disable the "pi" account and install an IPTABLES firewall on it

        - Don't expose say SSH (port 22) and other services directly to the Internet if you can help it.  
          If you do need to offer external SSH, at least change the answering port from say TCP/22 to 
          something like TCP/5353.  It's been said that you should NOT use any port number that includes 
          "22" as the common portscaners will look for that.  

         - Another good idea is to ONLY use SSH keys (ideally with passphrases) and disable all password
           authentication if you can compared to just using accounts with passwords.  These few steps alone 
           greatly reduces your security attack surface.  This is covered in a different chapter in this 

  - Safe Shutdown: 
    I recommend to connect a shutdown button so it's easy to turn off your Raspberry Pi safely.  You *MUST NOT* 
    just unplug the Raspberry Pi's power cord when you want to turn it off.  If you do this, you *will* 
    eventually corrupt the OS on the SD.  Adding a shutdown button is very easy and only takes two wires, a 
    resistor, a momentary button, and setting up a simple script).  This is covered in this doc.

I could go on and on here in the intro but I won't.  Instead, that's what the following chapters in
this document is for!  Good luck with the project and if you're new to Linux.. take your time.  There 
is lots to learn and it can be intimidating at times.  Do as much research on Google before becoming too 
frustrated.  At that point, feel free to email me or join some of the various help lists like the 
excellent list.   There are lots of helpful and patient Linux 
HAMs there that are ready to help.

Anyway.. let's get down to it!

1. Differences in Raspberry Pi hardware versions, downloading the SD image and installing it

I first want to highlight the key differences between the Rpi v1, v2, v3, v3+ and now 4 versions of 
the board.  I generally recommend people to either start with the v4 or v3+ due to many of it's 
substantial improvements for the same price UNLESS they have specific power consumption needs:

   - Boards: Overview of the big differences from generation to generation.  Read from the bottom up understanding
     the RPi v1 capabilities and then read about each newer generation with all of it's improvements:
     - Rpi 400
          - A faster Raspberry Pi 4 within a complete keyboard.  I personally don't see this device being 
            useful with this particular amateur radio project but it might be interesting for some people.
          - This is essentially a 1.8Ghz Rpi4 (stock clock is sped up from 1.5Ghz) with 4GB yet everything 
            else is the same except:
               - one less USB 2.0 slot (used by the keyboard)
               - No DSI display or CSI2 camera ribbon connections

     - Rpi4 / CM4 Compute module
          - The Rpi4-compute model departs from the previous sparse offerings and now has much of the same functionality 
            as the regular Rpi4-B (even Wifi, BT, and Gigabit Ethernet) with these notable changes:
             - PCI-Express: Instead of a pair of USB 3.3gen1 ports found on the Rpi4; the CM4+CM4 I/O board offers a 
                            PCIe 2.0 x1 slot on the CM4 I/O board
             - Wifi: This board now has a a u.FL external antenna jack 
             - Storage: Offers 0, 8, 16, or 32GB of eMMC onboard storage (faster than the CM3+ eMMC support)
             - I/O to Compute Module 4 I/O (CM4IO board): This module uses a new connector type to get external I/O
               (No more SO-DIMM connector)

             - CM4IO expansion board offers:
                 - PCIe 2.0 1x slot
                 - POE-capable Gigabit Ethernet with IEEE 1588 timing support
                 - 2 USB 2.0 ports
                 - An 8pin header for two more USB 2.0 ports
                 - A real-time clock with battery backup
                 - 2 full sized HDMI video ports (instead of the original Rpi4 micro-HDMI ports)
                 - 4pin 12v fan header connector (has PWM and TACH)
                 - 2x analog A2D inputs (AIN0 and AIN1) via a MXL7704 chip
                 - A 4pin PSU outbound power connector (similar to a classic 3.5" floppy power connector)
                 - 12-24v DC barrel-style power connector
     - Rpi4 Model B:
          - The Rpi4 has a new USB controller that's directly connected to the SOC Chip via a PCI-Express 
            instead of the previous slow USB 2.0 (480Mbps) link for much improved USB support
          - The Raspberry Pi 4 now has two USB 3.0 (now named USB 3.2 Gen 1) ports and two USB 2.0
            ports each served from their own controllers
          - The Rpi4 now has a true wire-speed wired Gigabit Ethernet via a connection directly from the SOC chip
          - The Rpi4 has added four ADDITIONAL serial port UARTS (but enabling them requires taking other functionality away)
          - The Rpi4 has Bluetooth 5.0 support
          - The Rpi4 has a newer generation video chip supporting dual HDMI displays
          - The Rpi4 now can come in 1GB, 2GB, 4GB, and 8GB of RAM 
          - The Rpi4 now uses a USB-C connector for power in as well as OTG USB support
          - The Rpi4 has newer generation CPU cores that are clocked faster 
          - The Rpi4 now places all Broadcom firmware on a dedicated EEPROM chip (firmware is no longer on the SD card)

     - Rpi3+
          - The Rpi3 now offers a Gigabit Ethernet (1000Mbps) port which is substantially faster 
            than the previous generation board's FastEthernet (100Mbps) but it's still on a shared USB bus
          - The Rpi3+ has dual-band 2.4Ghz and 5.0Ghz Wifi-5 802.11AC Wifi
          - The Rpi3+ has Bluetooth 4.2 support
          - The Rpi3+ adds support for Power over Ethernet (PoE) when an additional HaT board is connected
          - The Rpi3+ has CPU cores that are clocked faster 

     - Rpi3:
          - The Rpi3 adds 2.4Ghz 802.11n Wifi 
          - The Rpi3 adds Bluetooth 4.1 support
          - The Rpi3 now has 64bit processors
          - The Rpi3 has newer generation CPU cores that are clocked faster 

     - Rpi2
          - The Rpi2 now has four CPU cores and each core is clocked faster 
          - The Rpi2 now has 1GB of RAM
          - Now has a 40pin GPIO header

     - Rpi1 or RPi1+
          - Has a 40pin GPIO header instead of the 26pin header
          - Has 4 USB 2.0 ports instead of 2
          - MicroSD friction-slot instead of larger SD card
          - Better power regulators which lowers the power consumption

     - Rpi Zero 2 W 
          - Cheapest and smallest Rpi available with the same 4core CPU and performance as a ~Rpi3 (not a 3B+)
          - Near physically identical to the Zero W
          - Rpi0w has improved Wifi and BT performance over the 0w
          - Has 1 USB 2.0 ports via a micro-USB OTG port (requires an adapter cable)
          - The Bluetooth support on the Rpi0w has hardware flow control wired in so it can
            can go considerably faster than say the Rpi3 which doesn't have the flow control lines
          - 40pin GPIO header being installed is optional 
          - Initial released versions don't come with a GPIO header pre-soldered on
          - Has a CSI camera ribbon input port
          - No wired Ethernet port

     - Rpi Zero W or Rpi Zero
          - Cheapest and smallest Rpi available with the same CPU and performance as a Rpi1
          - Has 1 USB 2.0 ports via a micro-USB OTG port (requires an adapter cable)
          - Rpi0w has Wifi and BT
          - The Bluetooth support on the Rpi0w has hardware flow control wired in so it can
            can go considerably faster than say the Rpi3 which doesn't have the flow control lines
          - 40pin GPIO header being installed is optional 
          - Has a CSI camera ribbon input port
          - No wired Ethernet port

   Much deep details on the improvements in various categories

   - CPU Cores:
        400, CM4, Rpi 4, 3B/A+, CM3, 3, 2, and Zero 2 W : Four ARM cores
        Rpi Zero-W, Zero and v1 A/B                     : One  ARM core

   - CPU core technologies

        Clocking frequencies:
        400                   : 1.8Ghz per core (initial benchmarks say this is 18% faster than an original Rpi4)
        CM4, 4                : 1.8Ghz per core on newest "C" generation of the SOC with the new "triangle" chip complex / power rail
                                1.5Ghz per core on previous version SOCs
        3B+,3A+               : 1.4Ghz per core (below 70 degrees C and 1.2Ghz when above 70 degrees C)
        CM3+                  : 1.2Ghz per core
        3                     : 1.2Ghz per core
        Zero 2 W              : 1.0Ghz per core
        Zero W, Zero          : 1.0Ghz on a single core
        2 v1.2                : 900Mhz per core (underclocked)
        2 v1.1                : 900Mhz per core
        1,1+                  : 700Mhz on a single core

        CPU Generation:
        400,CM4             : Cortex-A72   ARM8-A cores (BCM2711C0T 28nm SOC chip)
                              - Other than a higher clock rate on the newer SOC revision, it's unclear what else is new here
        4                   : Cortex-A72   ARM8-A cores 
                                 Newer Rpi4 have the BCM2711C0T 28nm SOC chip - same as the 400/CM4
                                 Older Rpi4 have the BCM2711B0T 28nm SOC chip) 
                              Both RPI CPUs are a similar generation to the Qualcomm Snapdragon 650, Snapdragon 652 processors
        Rpi 3               : Cortex-A53   ARM8 cores   (BCM2710A1 cores in the BCM2837B0 SOC 40nm chip)
        Rpi 3A+/B+,CM3+     : Cortex-A53   ARM8 cores   (BCM2837B0 SOC 40nm chip)
        Rpi 2 v1.2          : Cortex-A53   ARM8 cores   (BCM2837   SOC 40nm chip)
        Rpi 2 v1.1          : Cortex-A7    ARM7 cores   (BCM2836   SOC 40nm chip)
        Rpi Zero 2 W        : Cortex-A53   ARM8 cores   (BCM2710A1 cores in the RP3A0-AU custom SOC+RAM chip)
        Rpi Zero W          : ARM1176JZF-S ARM6L core   (BCM2835   SOC 40nm chip)
        Rpi 1 A/B and 1+    : ARM1176JZF-S ARM6L core   (BCM2835   SOC 40nm chip)

        CPU Cache details:
        400, CM4, Rpi4 cores       : 32KB level 1 cache and   1MB Level 2 cache memory
        Rpi 3B+, 3A+, and 3 cores  : 32KB Level 1 cache and 512KB Level 2 cache memory
        Rpi 2 v1.2 cores           : 32KB Level 1 cache and 512KB Level 2 cache memory
        Rpi 2 v1.1 cores           : 16KB Level 1 cache and 256KB Level 2 cache memory 
        Rpi 1,+, Zero,Zero-W cores : 16KB Level 1 cache and 128KB Level 2 cache memory 

        CPU Instruction details
        400, CM4, Rpi 4              * Cortex-A72 have a 15-instruction pipeline depth
                                     : Support for out-of-order instruction execution

        Rpi CM3+,3+,2 v1.2, Zero 2 W :  * Cortex-A53 have a  8-instruction pipeline depth

        64 vs 32bit:
        400, CM4, Rpi 4, 3B+, 3A+, 3, Zero 2 W  : 64bit cores
        Rpi 2, Zero W, Zero, 1+, 1 A/B          : 32bit cores

           The four cores on the 4, 3B+, 3, and Zero 2 W support 64bit.  Raspberry Pi OS Buster through 
           Jessie (8.0) kernels does support 64bit but the distro's binaries remain built only for 
           32bit CPUs as there there is questionable speed vs memory bloat benefit.  The Raspberry Pi v2, 
           Zero W, and v1 only offer 32bit cores.  Please remember that even though a CPU is 64bit, 
           it doesn't necessarily gain you much unless you have LOT more memory to compensate for 
           the 2x larger data space requirements.  A little board like an Rpi used to not have a lot 
           of RAM so didn't make much sense.  

           See the "OS Version" section below about 32bit and 64bit OS distributions.

           64 vs 32bit kernel support:

           /boot/kernel.img supports 32bit-only and is used by RPi 1B, 1A, A+, B+, 2B (first version), Zero, 
              Zero (with camera), Zero Wireless, ComputeModule1 

           /boot/kernel7.img supports 32bit-only and is used by the RPi2B2, RPi3B, ComputeModule3 and ComputeModule3L
              BCM2836 (RPi2) and BCM2837 (RPi3)

           /boot/kernel7l.img supports 32bit-only and is used by the RPi4

           /boot/kernel8.img supports 64bit and can be used by the Pi4, Pi3, Pi2B rev1.2, and Zero 2 W boards
              BCM2837 (RPi3) or BCM2711 (RPi4)

        Thoughts on CPU performance differences
        400, CM4, Rpi4: Each of the Rpi 4 A72 cores are said to offer a 300% performance increase over the previous A53 
                   based ARM cores due to the technology points mentioned above.  How is this possible?  The Rpi v3's 
                   Cortex A72 CPUs improved pipeline depth and out-of-order instruction execution abilities make a 
                   big difference.  This means that if the two CPUs were running at the same clock speed Cortex-A72 
                   processors would still run significantly faster (and use more power) compared to their RPI3+ / 
                   RPI3 A53-powered ancestors.

        Zero 2 W: Benchmark results differe on 64 vs 32bit where 64bit can be faster in some results at the cost
                  of increased memory usage.  Overall, the Zero 2 W is 3-7x faster than the Zero W due to the
                  new model having four cores that are of a newer generation.

        Older   The 3B+ A53 CPU cores have a 30% performance improvement in the CPU instruction set performance 
        gen:    PER CORE compared to the Raspberry Pi 2 v1.1's Cortex-A7 4-core ARM7 cores.  These points alone 
                show the substantial performance increase over the years and remember: count the cores.  For the 
                older v3B+: that's 30% better performance x 4 cores or 120% faster than the first-gen Rpi2!

        Oldest  The Rpi Zero-W, Older non-wireless Zero, v1-B, and v1-A boards use the old and obsolete ARM 
        gen:    ARM1176JZF-S CPU with the ARM v6L CPU instruction set.  While this CPU is still supported in 
                the Raspbian distro, many other ARM-enabled Linux distributions have DROPPED support for it.  
                Those ARM6L CPUs are substantially slower and is less efficient than even a Raspberry Pi v2.  
                Raspbian is one of the last Linux distros to actively maintain this old CPU and instruction set.
                I generally only recommend people to use the Rpi 0-W if you need the lowest lower power consumption 
                or the smallest physical footprint.  Don't get me wrong, I think the Zero-W is a great little 
                board but it's very old technology wise compared to it's other Raspberry Pi cousins.  

   - RAM Size
        400                          : 4GB of RAM

        CM4                          : 1, 2, 4, or 8GB of RAM versions  (1GB version discontinued in favor of 2GB 
                                       being baseline))

        4 (2nd gen)                  : 2, 4, or 8GB of RAM versions  (1GB version discontinued in favor of 2GB 
                                       being baseline))

        4                            : 1, 2, or 4GB of RAM versions

        CM3+,3B+/A+,v3,v2            : 1GB   of RAM 

        Zero, Zero-W, Zero 2 W, +, 1 : 512MB of RAM 

        1A+, 1A                      : 256MB of RAM

   - RAM technology and clocking:
        The RAM on the 3A+, 3B+, 3, and Zero-W is clocked 50Mhz faster than the Rpi v2 and v1

           400, CM4, 4               : 3200Mhz LP DDR4-2400 RAM
           CM3+, 3A+/B+              :  500Mhz LP DDR2 RAM
           3, Zero 2 W, Zero-W, Zero :  450Mhz DDR2 RAM
           v2, 1+, 1                 :  400Mhz DDR2 RAM

   - GPU technology:
           400, CM4, 4               * Video Core VI GPU
                                     - Openly ES 3.0 graphics
                                     - Supports H.265 (4KP60 decode) in hardware
                                     - Supports H.264 (1080p60 decode, 1080p30 encode)

      CM3+,3+, 3, 2, 1+, 1, Zero 2 W : Video Core IV CPU
                                     - Openly ES 2.0

   - GPU Clocking:
        The GPU video chip used on all Raspberry Pi models is the VideoCore IV but the Rpi 3B+, 3 and Zero 
        W run 50Mhz faster:

           400, CM4, 4     : 500Mhz
           3+,             : 400Mhz
           3, Zero-W, Zero : 300Mhz
           v2, v1          : 250Mhz

   - HDMI Display details
           CM4                     * Two full sized HDMI ports with the same display connectivity as the Rpi4 via the 
                                     optional I/O board; no direct video connections on the CM4 itself

           400, 4                  : Two micro-HDMI 2.0 ports for dual displays
                                      - dual displays can run at max 4Kp30 (3840 x 2160) resolution
                                      - single display can run at max 4Kp60 (3840 x 2160) resolution
                                        with the other display at 1080p
                                      : 4Kp60 hardware decode of H.265 (HEVC) video
                                      : 1080p60 hardware decode and 1080p30 hardware encode of H.264 (AVC) video
                                      : There have been reports that different HDMI display resolutions 
                                        might interfere with the 2.4Ghz wifi radio.  More research is being 
                                        done here

           3+, 3, 2, 1+, 1         : One HDMI 1.3 port (full sized connector) running at
                                     max 2560 x 1600 resolution

           Zero 2 W, Zero W, Zero  : One HDMI 1.3 port (mini style connector) 

   - Composite Video
        400                        : No composite video output available

        CM4                        : Composite video support is on the 14pin header on the CM4IO board

        4, 3+, 3, 2, 1+            : Composite video via the TRRS audio connection
        1                          : Composite video via RCA connector

        Zero 2 W, Zero W, Zero     : available on the Zero W and Zero via the secondary 4pin header
                                   : Zero 2 W offers composite video via solder pads on the bottom of the PCB

   - MIPI DSI display output
        400                        : No ribbon connections available

        CM4IO                      : 2x MIPI DSI output display 22pin via the optional CM4IO board
                                     no direct connections on the CM4 itself

        All Pi versions            : on-board two-lane MIPI DSI output display port
                                     except the Zero 2W, Zero W, and Zero which doesn't have the DSI display 
                                     output port

   - MIPI CSI-2 camera input
        400                        : No ribbon connections available

        CM4IO                      : 2x CSI-2 camera input - 22pin ribbon connections
                                     no direct connections on the CM4 itself

        4, 3+, 3, 2, 1+            : one 22pin ribbon connection to an external camera

        All Pi versions            : on-board two-lane MIPI DSI display port
                                     including the Zero 2 W, Zero W, and Zero 

   - Wireless Wifi networking:
        CM4 (Compute)     : Same Wifi support as the Rpi4 but it offers an electrically switchable u.FL connector
                           for external antenna support

        400,CM4,4,3A+,3B+ * dual-band 2.4Ghz and 5.0Ghz Wifi-5 aka support for 802.11 B/G/N/AC(Wave1) 
                            300Mbps Wifi using the Cypress CYW43455 chip with a new (superior) on-board Proant 
                            resonance cavity antenna design 
                          : Various reports gives the Rpi v4 Wifi connection running on the 5.0Ghz band
                            a 20% speed improvement over the Rpi v3+
                          : no U.FL external antenna solder pads available except on the CM4

        400,CM4,4         : There are reports that older wifi firmware doesn't allow some of the faster 802.11AC
                          : modes on the 5Ghz band.  Check your firmware version that comes with your Operating system

        400,4             : There are reports that the 2.4Ghz wifi performance is impacted when using USB 3.0

        4                 : There have been reports that different HDMI display resolutions might interfere with 
                            the 2.4Ghz wifi radio.  More research is being done here

        3                 : single band 2.4Ghz 802.11 B/G/N 150Mbps Wifi via the Broadcom BCM43438 chip that's independent
                            of the USB bus so there is less network I/O contention here 
                          : uses the older ceramic "chip" antenna design 
                          : has U.FL external solder pads

        Zero 2 W, Zero W  : single band 2.4Ghz only 802.11 B/G/N 150Mbps Wifi : new (superior) antenna design w/ 
                            has U.FL external antenna solder pads.  The Zero 2 W has been seen to have about 50% better
                            Wifi performance compared to the original Zero W

        v2, 1+, 1         : No built-in wireless support

        More details on the Wifi:
        400,CM4,4,3A+/3B+ - 2.4Ghz and 5.0Ghz 802.11AC Wifi via a Cypress CYW43455 chip
                          - Uses a similar antenna design as the Zero W which is evidently
                            significantly better than the ceramic chip antenna used on the Rpi3.  
                            Unfortunately, this board removes the u.fl solder pads which could be 
                            used to add an external Wifi antenna
        Zero 2 W          - 2.4Ghz only 802.11N  Wifi via the Broadcom BCM43438 chip
                             - The Zero 2 W has a new custom wireless chip which supposedly offers better WIFI and BT
                               performance compared to the original Zero W.  I've heard some conflicting details
                               on this point where it's possible the older Zero W might have better wifi performance

        v3, Zero 2 W, Zero W - 2.4Ghz only 802.11N  Wifi via the Broadcom BCM43438 chip
                             - the Zero W uses a new antenna design which is evidently
                               significantly better than the antenna used on the 3.  Unfortunately,
                               it also removes the u.fl solder pads which could be used to add 
                               an external Wifi antenna

   - Wired Ethernet Connectivity:
        400, 4, 3B+               : Gigabit Ethernet (1000Mbps)  

        400                       : The 400 doesn't include any link or activity LEDs on the connector (bad!)

        CM4                       : CM4 has the Ethernet chip onboard the CM4 but the RJ45 and magnetics are on the 
                                    optional CM4IO board)

        3, 2, 1+, 1               : Fast Ethernet    ( 100Mbps)

        3A+, 1A, Zero 2 W, Zero W : No wired Ethernet option but you can always connect a USB-based Ethernet dongle

        CM4           * In addition to supporting Gigabit Ethernet, this support supports the in-band 
                        IEEE-1588 timing standard

        CM4, 4        * Gigabit Ethernet (1000Mbps) using the Broadcom BCM54213 chip connected directly to 
                        the Broadcom ASIC providing near wire-speed performance (945Mbps - 5 times that of an 
                        Rpi 3B+)
                      - RJ45 and USB connections are flipped to opposite sides compared to previous Rpi
                      - Power over Ethernet (PoE) support is available via the use of a PoE HAT board
                      - The CM4 compute module has the Gigabit Ethernet MAC and part of the PHY on the actual
                        module but the connector and magnetics are on the optional I/O board

                         NOTE: Neither the PCIe slot or FAN connector will function when the setup is powered 
                               via PoE

        3B+           - Gigabit Ethernet (1000Mbps) using the Microchip LAN7515 chipset.  
                        Performance is significantly limited due to still being connected via a shared 480Mbps 
                        USB2.0 bus (roughly 330Mbps throughput max)

                      - The new 3B+ also supports Power over Ethernet (PoE) with the
                        addition of a PoE HAT board.  It's also worth noting that the
                        PXE LAN booting feature is now enabled by default on this new board

        3, 2, 1+, 1   - Fast Ethernet (100Mbps) using the SMSC LAN951x chipset (Rpi 3 and 2B)

   - Bluetooth (BT) wireless:
        400, CM4              * Same Bluetooth support as the Rpi4 but it offers an electrically switchable u.FL connector
                                for external antenna support

        4                     - BT v5.0 with BT-Low Energy (LE) support on the 2.4Ghz spectrum
                                via a Cypress CYW43455 chip : quadruple the range and roughly double the speed

        3A+, 3B+              - BT v4.2 with BT-Low Energy (LE) support on the 2.4Ghz spectrum
                                via a Cypress CYW43455 chip

        v3, Zero W            - BT v4.1 24Mbps with BT-Low Energy (LE) support on the 2.4Ghz spectrum
                                via the Broadcom BCM43438 chip

        Zero 2 W             - BT v4.2 24Mbps with BT-Low Energy (LE) support on the 2.4Ghz spectrum
                                via a custom wifi chip

        2, 1+, 1, Zero nonW   - No BT support

   - USB Connectivity 
        400               * Two USB 3.2gen1 5.0Gbps ports and one USB 2.0 port similar to the Rpi4 (see below)

        CM4               * Two USB 2.0 A-connector ports are available as well as an additional 2 USB ports can be
                            made available via a 10pin header connection via the optional I/O board.
                          - No USB 3.0 ports are available as that connection to the CPU was reused for the PCI-e slot
                          - the micro-USB adapter on the CM4IO board is only used to upgrade the firmware on the CM4 only

        Rpi 4             : Two USB 3.0 ports (aka USB 3.2gen1) running at 5.0Gbps via one VIA Lab VL805 
                            (one controller) connected via PCI-Express.  Performance is said to be maxed out at
                            about 4Gpbs due to only having one PCI-Express line to feed the USB ASIC
                          : two USB 2.0 ports running at 480Mbps via the same VIA Lab VL805 (second controller) 
                          : One USB 2.0 OTG port (USB-C power connector)

        3B+, 3, 2, 1+     : Four USB 2.0 ports connected to a single SMSC LAN9514 480Mbps USB 2.0 hub chip
                            via the the main BCM283x SOC chip; this connection to the SOC chip is also shared with the 
                            wired Ethernet interface

        1B                : Two USB 2.0 ports connected to a single SMSC LAN9512 480Mbps USB 2.0 hub chip
                            from the main BCM2835 SOC chip; this connection to the SOC chip is also shared 
                            with the wired Ethernet interface

        Zero 2 W, Zero W, : One  USB 2.0 port as On-the-Go (OTG) port via the single 480Mbps USB 2.0 controller
          Zero, 3A, 1A      directly connected to the SOC chip

   - Serial port connectivity
        Rpi documentation

        400, CM4, Rpi 4   * The Rpi4 offers 4 additional PL011 hardware serial ports using alternative dtoverlay 
                            setups with and without flow control support.  Enabling some of these overlays will take 
                            over and impact other pinout functions such as the I2C-0 bus, etc.  The enabling
                            of flow control on these ports will consume additional GPIO ports.  See
                            for more details as the standard Rpi UART documentation doesn't cover this yet.
                            The Rpi4 also has the other two serial ports as well.  See the below RPI models to 
                            understand those port offerings

        3B+,3B+,3,Zero W  - All Rpi units that come with Bluetooth Low Energy (LE) support come with two serials ports
                            via the Broadcom BCM43438 chip.  The PL011-based serial port which supports hardware flow 
                            control is mapped to support the BT system by default.  The second serial port called the 
                            "mini-uart" is a software emulated which is mapped to supporting the serial console function 
                            if enabled.  This emulated serial port has caveats as is variably clocked to the GPU part of 
                            the chip which creates reliability problems.  This second port also doesn't support flow control.
                            You can swap which UART serves which function depending on what function is more important to you

        2,1+,1,Zero-nonW  - One hardware PL-011 hardware UART with flow control pins is included

   - Storage physical format
        CM4                       : With the CM4IO board, NVMe SSDs can be connected via an adapter though you cannot boot
                                    from this storage currently (as of 11/29/20) but I imagine this will change in time
                                  : Offers 0, 8, 16, or 32GB of eMMC onboard storage (faster than the CM3+ eMMC support)
                                  : Micro-SDXC card slot available on CM4-lite versions (without any eMMC storage installed 
                                    - same SD card support as standard Rpi4 versions

        400, 4,                   : Micro-SDXC card; non-UHS-II connector (cards with double row of pins)

        CM3+                      : 0 or 8GB of eMMC onboard storage
                                  : No uSD slot but I/O pins are on SO-DIMM connector

        CM3                       : 0 or 4GB of eMMC onboard storage
                                  : No uSD slot but I/O pins are on SO-DIMM connector

        3+, 3, 2, Zero 2 W,       : Micro-SDHC card; non-UHS-II connector (cards with double row of pins)
             Zero W, Zero, 1+

        1                         : full-sized SD card

        Compute1, Compute3        : 4GB eMMC onboard

        Not sure what class/kind of SD card you have running in your Pi?  Try out these CSD decoders:
           CSD v1.0:
           CSD v2.0:

   - Storage booting support
        CM4                    : Same support as the Rpi4 - booting off an NVME SSD via the PCIe slot
                                 is not supported today

        400, 4, 3+, 3          : Boot off microSD, USB, PXE (Rpi4 PXE support coming later)

        2, Zero 2 W, Zero-W,   : Booting via a the SD card
           Zero, 1+, 1

   - Onboard storage speed:
        CM4                    : Onboard eMMC storage is substantially faster than any SD card but is still
                                 much slower than a NVME-based SSD attached via the PCI-e slot or a SATA-base 
                                 SSD attached via USB 3.0
                               - 8bit eMMC interface on CM4 is faster than the 4bit eMMC interface on CM3

        400, 4                 : Supports 400Mbps / 50Mbps transfer rates via SD "UHS-1" cards.  Performance
                                  varies wildly depending on SD card vendor (see URLs below)

                                 V-rated cards don't apply as that requires UHS-II or better cards

                                 Much higher performance can be had using USB 3.0 (625 Mbps) based flash 
                                 pen drives but performance varies wildly depending on vendor

        3+,3,2,Zero 2W,        : Supports 200Mbps / 25Mbps transfer rates via SD "High Speed" cards
          Zero W, Zero, 1+       by default (overclocking is possible for higher speeds at the risk of stability
                                 issues.  The Pi does not support 1.8V or U1 writes

        1                      : Supports 160Mbps / 20Mbps transfer rates via full-sized SD/MMC card

        Understanding which is the right SD technology for your Pi?  See

        Not all SD card manufacturers are equal read vs write speed wise.  Please see this URL for a good set 
        of real world benchmarks:


   - Firmware support
        400, CM4, 4            : All initial firmware startup is read from a dedicated EEPROM chip

        All older Rpi versions : All firmware files are read from the SD card

   - Audio Connections
        400                    : Audio can be via HDMI; no TRRS 3.5mm jack

        CM4,4,3+,3,2,1+,1      : stereo audio out via TRS 3.5mm jack
                               : Audio can be via HDMI or dedicated audio output

        Zero 2 W, Zero-W, Zero : No TRS audio output

   - GPIO connectivity and features:
        CM4                     * 40pin header from the optional CM4IO board with the same support as the Rpi4

        400, 4                  : 40pin header 
                                : 5x SPI, 6x I2C, and 6x UART functions via the alternative pinout mappings
                                : Max GPIO switching speed of about 50.8 KHz

        CM3+                    : Full Broadcom connectivity available on SO-DIMM interface 

        3+, 3, 2, Zero 2 W,     : 40pin header
              Zero W, Zero, 1+  : one SPI, one I2C, one Serial UART
                                : Max GPIO switching speed of about 16.1 KHz on the 3B+

        1                       : 26pin header
                                : one SPI, one I2C, one Serial UART

   - LEDs on the board

     Different Rpi boards have different fixed or programable settings for it's board LEDs as
     well as the Wired Ethernet jack LEDs.  Run the following command to see what your board and 
     firmware support:

        ls -l /sys/class/leds

     to see what an LED is current assigned to do, use the command:

        cat /sys/devices/platform/leds/leds/led0/trigger
        cat /sys/devices/platform/leds/leds/led1/trigger

     See section 32.b later in this document for details of how to change various LED behaviors
     for these and possibly the Ethernet jack LEDs

        400                    : Numlock, Capslock and Red power LED 
                               :   - No green activity LED or network link/activity LEDs
        CM4                    : (need to verify)

        4, 3+, 3               : Red LED (power) and green LED (sd card access) are programmable

        Zero 2 W, Zero-W, Zero : Red LED (power) and green LED (sd card access) are programmable

        2                      : Red LED (power) and green LED (sd card access) are programmable

        1+, 1                  : Red LED (power) is NOT programable, green LED (sd card access) is programmable

   - Raspberry Pi Foundation Compute module I/O boards
        CM4                : Pair of new high density connectors to the optional CM4IO board

        CM3+, CM3, CM2     : Uses the JEDEC DDR2 SO-DIMM connector

   - There are a LOT of 3rd party compute module I/O boards coming to the market these days
     especially for the CM4 board to do ALL kinds of things

   - PCI-e Expansion Slot support
        CM4                     : 1x PCI-e 2.0 1-lane slot via the optional CM4IO board
                                - Known to work with various USB3 controllers and NICs
                                - Known issues around not supporting video cards at the moment due to 
                                  PCIe "BAR" parameters

   - RTC Support
        CM4                : The optional CM4IO board has an onboard PCF85063AT RTC chip with a coin-cell 
                             battery backup holder.  This is available via on i2c-10 address 0x51

   - Fan Connector
        CM4 only           : The optional CM4IO board has a 4pin fan connector that supports +12v fans
                             with PWM control and TACH speed monitoring via the I2C bus (i2c-10 address 0x2f)

   - Power Connection and current requirements
        CM4                : Uses a barrel connector via the optional CM4IO board supporting +12v to 26v
                             (lower or higher voltages than +12v forbids the use of the PCIe connector, PSU,
                             and fan headers)
        400, 4             : USB-C connector at 5.0v @ 3.0A providing 1.2A for USB devices.  The change 
                             to a new connector is due to that the legacy USB2 Micro-USB connector is 
                             aging and generally cannot supply the required 3.0A of current

                             NOTE: 2.5A is allowed if any attached USB devices consume less than 500MA

        CM4, 4, 3B+        : Support for Power over Ethernet using an additional PoE HAT board

          NOTE#2:  There was a known issue with the v1.1 revision of the Rpi 4 boards that their design
                   has an issue when using "E-type" USB-C cables which include built-in electronics
                   to negotiate voltage, current, and other capabilities.  These type of cables are 
                   mostly found as new laptop charger power bricks + cable for say Chromebooks, Apple
                   Macs, etc.  Until a new version of the Rpi4 is released to fix this, the work around 
                   here is to NOT use E-type power bricks and/or cables.  This was fixed in revision
                   v1.2 of the Rpi4 4GB only boards

        Rpi 3+, 3, 2, Zero 2 W, Zero W, Zero, 1+, 1 :  use the USB 2.0 "micro" USB connector type
           3B+, 3, 2                                : Micro-USB at 5.0v @ 2.5A
           1+, 1                                    : Micro-USB at 5.0v @ 1.8A
           Zero 2 W                                 : Micro-USB at 5.0v @ 2.5A
           Zero-W, Zero, 1+, 1                      : Micro-USB at 5.0v @ 1.0A

   - Power consumption and management:
        Different Rpi units consume different amounts of power depending on the number of CPU
        cores and other features the offer.  

        Pi Zero: Generally speaking the Raspberry Pi Zero non-wireless is probably the lowest power consumer closely 
                 matched with the Zero-W and then the v1-A version.  One set of measurements from Jeff Geerling 
                 shows the Zero W with:

                      booted and idle: 0.42W  ( .08A @ 5.20v ) with all services enabled
                      maxed out load : 0.83W  ( .16A @ 5.18v )

                 The Zero 2 W version consumes substantially MORE power than the Zero W due to it having four
                 CPU cores instead of just one.  Again, Jeff measured on the Zero 2 W:

                      booted and idle: 0.10W  ( .10A @ 5.20v ) with HDMI and all wireless disabled
                      booted and idle: 0.62W  ( .12A @ 5.20v ) with all services enabled
                      maxed out load : 2.12W  ( .41A @ 5.18v )

        Those are also some of the slowest versions available so the compromise of performance vs. power vs.
        available features is up to you!  Some of the below URLs have good power consumption charts to help you 
        learn more.
        Rpi 4/3+: The Rpi 4 and 3+ have the MXL7704 power management chip which should make these units more 
        stable at sustained high loads.  It's also mentioned that the power consumption of the 4 and 
        3B+ are notably HIGHER than the model 3 due to their CPUs.  A high quality 3.0A power supplies is 
        *required* for the Rpi v4 and 2.5A power supply for the 3+ is even *more required* than it was before.   

        Rpi4: The initial releases of the Rpi4 were reknown for thermal throttling due to high power 
        consumption.  New firmware releases in October and November 2019 have made significant 
        improvements here.  You can read more about that here:


        Rpi3+: It's also mentioned that the 3B+ can be more successfully DECLOCKed to 600Mhz possibly lower 
        the power consumption but this thread generally recommends to buy OLDER Rpi versions if 
        power consumption matters to you:


   - Operating temperatures / Cooling
        400                 : The unit has a metal shield which acts like a large heatsink for the SoC chip 
                              only (nothing for the RAM, Ethernet controller, etc.) and the bottom of the 
                              keyboard case has vent holes.  Initial reports say the unit doesn't do any
                              CPU throttling with some level of overclocking but time will tell.  I'm also
                              curious how warm some the keys might get.
        CM4                 : Thermal requirements should be the same as the Rpi4

        4                   : The Rpi4 runs considerably hotter than the Rpi 3+ or earlier even at idle.
                              Some major power consumption improvements have been in the October and November
                              2019 firmware releases.  Real power draw and heat issues will depend on how you 
                              use your Pi but see the power management section below for details on temperatures 
                              and CPU throttling points.  Also review the benchmark links for more details on 
                              thermal measurements

        4, 3+               : The CPU now has a heat spreader on the CPU chip to better support cooling
                              without a heat sink.  It also has an improved power management system for 
                              being more stable at sustained high loads.  See the power management section 
                              for more details

        3,2,Zero 2 W, Zero-W, : These versions don't generally have any unique cooling features so
                 Zero, +, 1     depending on the workloads, some people need to add heat sinks and/or fans
                                to avoid thermal throttling (the CPU slows down)

     Operating System support:
     400, CM4, 4, 3+, CM3+, CM3, 3, 2+, 2, 1+, 1, Zero 2 W, Zero W, and Zero:

        The officially supported Linux distro is "Raspberry Pi OS" (formally named "Raspbian") 
        which supports *ALL* versions of the Raspberry Pi hardware from the Rpi v1, the compute 
        modules, all the way to the new 8GB CM4.  As new Rpi hardware versions have been release, 
        you must use the correct minimum version of the OS which includes the required drivers.
        See to better understand those versions.

   - Cases for the Raspberry Pi
     There are literally HUNDREDS of 3rd party cases out there for the various Raspberry Pi SBC versions
     but here are some thoughts at least from the Raspberry Pi Foundation but I find the 3rd party ones
     better across the board.  See the appendix in this documentation for more discussion about good and
     bad cases, fans, etc:

        400        : The keyboard is the case

        CM4        : You won't find a case for the CM4 as it cannot be used without some form of additional
                     baseboard.  There are a LOT of different ones coming out so look at those baseboard 
                     offerings for cases

        4          : new case design for the dual micro-HDMI video; USB-C power connector, swapped 
                     RJ45 and 4xUSB connections; 40pin GPIO header
        3+,3,2,1+  : full size HDMI video, TRRS audio/video, 4xUSB, 1xRJ45, micro-USB power connector, 
                    40pin GPIO header

        1          : full size HDMI video, TRS audio, RCA composite video, 2xUSB, RJ45 network, 
                     micro-USB power connector, 20pin GPIO header

        Zero 2 W, Zero W, Zero : mini size HDMI video, OTG micro USB 2.0, power via micro USB 2.0 connector
                                 40 pin GPIO header

   - Known hardware issues:
     - Full list of Rpi board revisions

     - Rpi 4 v1.0 PCB : not compatible with e-type USB-C cables : fixed in the Rpi4 4GB v1.2 boards

     - Rpi 4 v1.0 PCB : has known interference issues with Wifi and one of the HDMI ports when in 4k resolution

     - Known compatibility issue with USB 3.0 hubs and all Rpi (except Rpi4) USB 2.0 ports
       with full or low-speed USB devices -

   - Rpi SBC specification URLs:
     - A nice technical overview (but not 100% complete) of all the different boards with a table can be found here:

     - Raspberry Pi CM4 I/O board specs:

     - Raspberry Pi 4 specs:

   - Overclocking various Rpi hardware
     I generally don't recommend to overclock Raspberry Pis (especially early versions) due to all of
     their well understood power issues.  Next, if you're really needing more performance, I would
     always recommend to get the next faster version of an Rpi board vs. overclocking a lower end unit
     for the sake of stability.  That all said, some Rpis are more overlockable than others and the
     max level of overclocking will depend on your specific Rpi unit as small differences in the chips
     installed on your Rpi will impact how stable or unstable your setup will be at a given overclock.

     If you're going to overclock your Raspberry Pi, I recommend two things:

        - You must have a heatsink on the CPU SOC

        - Your case must have excellent ventalation (any enclosed cases will not work well unless 
          they are one of those extruded all-metal case+heat sink type cases) or ideally have 
          a full speed or variable RPM fan

     Various successful overlocks I've read about:

        - Zero 2 W @ 1.3Ghz :  Using a CPU core voltage setting of "4" but maybe "3" will work for 
                               you and create less stress on the CPU SOC

   - Benchmarks on various Rpi hardware
        - lots of detail including power draw comparisons for all versions of Rpi boards



     - A complete 3B+ breakdown:

     - Run your own lightweight Pi benchmark (CPU, Memory, Storage, Internet, :

1.a Choose a quality SD card and how to put a Raspbian image on it

Choosing which micro-SD card manufacturer and even the specific models of the SD card can 
really matter in terms of just outright booting up to also avoiding premature failure.   At a
high level, check out this URL for some SD card recommendations:
See those URLS for some specific SDHC technology options and benchmarks for various performance.  
I would highly recommend the following:

   - NOTE:  Newer Raspberry Pi units support booting from USB (Mass Storage Device - called MSD).
            This means you can boot from USB devices be it SSDs,hard drives (HDD), flash pendrives, 
            etc.  This means booting via a micro-SD is technically no longer required 

   - NOTE #2: PXE booting over the wired Ethernet network port is available on the Raspberry Pi 4, 
              3B+ and 3 but USB/MSD support is available on the 3

   - Use a quality brand name SD card like Sandisk, Samsung, etc. from reputable
     sellers.  There are just too many reports of either cheap cards and/or 
     counterfeit cards not giving the advertised capacity or failing very quickly.
     Using off-brand cards could prove unreliable (corruption, later full-on card 
     death, etc)

        - It's recommended to buy Class-10 cards for better performance and even more recently,
          buy a "A1" class card for this type of I/O usage.  Check out the following URL for 
          more details and how to benchmark your card:


        - It's recommended to buy a larger capacity SD card than you need : By using a larger quality 
          card, many SD cards can better leverage their (optional) built-in wear leveling functionality
          to make the card last longer before bad sectors begin to show up

        - (OPTIONAL) - If you have access to a Windows or Mac machine with an SD card reader, 
          it's highly encouraged to format any new SD card with the Official SD Association card 
          formatter programs available at: 


          Why?  This tool will verify that the card's actual storage capacity, 
          identify any physical card issues, and then format it (removing any potential
          malware on the card as well).  After using this tool, you can install it in 
          your Linux computer to image the card with the Raspbian OS

  1. Put your purchased quality MicroSD card to existing working Linux computer's SD card reader.  
     This can be on your computer itself or connected via say a USB card reader.  If using a 
     micro-SD card, you might need an inexpensive full-sized SD to micro-SD card adapter (these
     sometimes even come with the new micro SD card).

  2. Run the command "dmesg" on you Linux computer to confirm SD card showed up.  
     On my computer, it shows up as /dev/mmcblk0

1.b Download the newest Raspbian OS release and install it

     Raspbian Buster named is the current image as of 7/21/19.
     The previous Stretch image named is also available but
     is now officially on it's way out.  I would recommend to download and use the NEWEST image 
     available to a reliable location on your computer.  


        - NOTE #1:  There are three versions of Raspbian you can run:

             "Desktop and recommended software" - aka FULL - this includes a full GUI interface (was 
                 previously called Pixel) which comes with a lot of other packages like Chromium, 
                 Libreoffice, etc
             "Desktop" - includes a full GUI interface and many other packages but is lighter weight
                 aka it has a lot less programs pre-installed

             "Lite" - CLI only image (no GUI) which is considerably smaller and light weight
                - A fully patched Buster Lite image with all programs in this doc: 1.5GB used

          For Rpi installations that will never have a monitor attached to it and you'll most
          likely only SSH into it, I recommend to install the *Lite* version.  Why waste all
          that RAM and CPU cycles running the Xwindows system if you're never going to use it!
          If you want to use VNC to remotely control the Rpi via a GUI (and not via native SSH), 
          go ahead and install the "desktop" version.  This document assumes the Lite version is

        - NOTE #2: If you're going to be using newer generations of Raspberry Pi hardware such as 
                   an CM400, CM4, Rpi 4, you MUST download and use the Buster version of Raspberry Pi
                   OS to support this new hardware.  If you have a 3B+, your minimum version is Raspbian 
                   Stretch and it has to be newer than 2018-03-13.  

        - NOTE #3: If you don't use the correct minimum version of the OS,  it WON'T boot and instead, 
                   you will see 8 flashes at the rainbow screen via the HDMI output and then stop there)

        - NOTE #4:  Per the comments in 
 , Raspberry Pi OS 
          Jessie is no longer supported.  It seems that the Raspbian community follows the
          NON-LTS version of Debian schedule shown here:


          This means that all users should upgrade to Stretch ASAP to get updates, fixes, 
          security patches, etc

  1. At this stage, you have several choices on how to get the Raspberry Pi image installed into the SD card:

    1.a.  From Linux: You can use my script that will automatically 
          uncompress and copy the resulting image to the SD card in one step

          To use this approach, do the following:

             cd /tmp
             chmod 755
             sudo mv /usr/local/sbin/

          Next, from the output of the "dmesg" command run above, edit the script and make
          sure the SD card device used in the $DESTDEV variable

          Run the command:

             #Installing Stretch Lite in this example
             sudo /usr/local/sbin/ <path-to-image>/

          This command will take some time to complete depending on the speed of your SD card,
          your computer, etc.

    1.b.  From Linux: If you don't want to use the above script, you can install the image via a two step process:

             1. Uncompress the downloaded ZIPed image with the command:


             2. Now use the following command where "mmcblk0" is the name of your SD card device
                shown above from the bottom output of the "dmesg" command:  

                   dd if=2019-06-20-raspbian-buster-lite.img of=/dev/mmcblk0 bs=2M

    2.  OPTIONAL HEADLESS setup: Once the Raspberry Pi OS is imaged onto the SD card, you now have the option 
        of headless configuration (aka pre-configuring) the OS when it first boots by creating / editing key 
        files on the newly created /boot partition on the SD card.  All of these settings will be made for you
        automatically and can really help speed things up for you to log into your Rpi.

        If you want to do this, first remove the SD card from your card reader that you just imaged and nowthen 
        re-insert the card.  On most modern operating systems, it will auto-mount at least the "boot" (aka first 
        partition).  If it doesn't auto-mount the boot partition, you'll need to get that done manually.  If this
        WAS done automatically, you can confirm this on say a Linux machine by running the "mount" command from
        a command prompt to see if it's been mounted.  For example on my Linux machine, I see the two partitions
        coming from the /dev/sdb device:

           /dev/sdb1         258095     50412    207684  20% /media/dranch/boot
           /dev/sdb2        1644392   1240068    302744  81% /media/dranch/rootfs

           - To enable SSH access on first boot, create an empty /boot/ssh file.  In this example, that's
             easily done with:

                touch /media/dranch/boot/ssh

           - To configure and enable Wifi network access, you need to edit the /boot/wpa_supplicant.conf file.  
             Take the below example and change it to reflect your home wifi network's settings including your 
             country code.  If you have an existing Linux machine already connected to w Wifi wireless network, 
             you can run this command to get the correct name of the network (change the device name to reflect
             your specific wifi interface name according to the command "ip link":

                sudo iwlist wlan0 scan

             See for a full list of valid country codes
                ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev

           - To enable a serial console using the Rpi's onboard GPIO serial port UART?  Edit the /boot/config.txt 
             file and add the following line at the bottom of the file.  

                # Enable UART

             With this config, once you reboot as instructed below you will see the kernel boot and
             eventually a login prompt!  This all assume you have a working serial port and serial terminal program 
             running on a different computer.  That serial port will be connected to your Rpi's GPIO pin 6 (GND),
             pin 8 (UART TX), and ping 10 (UART RX) and the serial terminal program is configured to run at 115200 
             bps, 8 data bits, 1 stop bit, no parity, no hardware flow control, and no software flow control. 

           - New as of 4/8/22: OPTIONAL: Create a new local username:  If you want to bypass this part of the first boot 
                               configuration wizard, you can create the /boot/userconf.txt file to create a new 
                               user with a hashed password with the format

                Translating this step by step, this means:

                   1. "username" should be change to reflect your desired new username.  For me, this would be "dranch"

                   2. the ":" colon is required to be there

                   3.  The "encrypted-password" is the encrypted password you will be using.  To generate the 
                       encrypted password, you will need another Linux machine to run the following line of 
                       commands to change the "mypassword" text to be your password.  This example uses a
                       few more commands more than usual to ensure your password isn't being saved onto your 
                       file system and is a little more user friendly.  Paste this command into your other 
                       Linux machine and hit enter:

                          echo -en "enter password (characters will not be shown): "; read -s TEMPPASS; \
echo -e " "; echo $TEMPPASS | openssl passwd -6 -stdin; unset TEMPPASS

                       Once you see the result encrypted passowrd text, paste all of it after the colon into
                       the /boot/userconf.txt file

    3. Ok, that's it!  Safely unmount your SD card before ejecting it.  In this example I would use the following

          sudo umount /media/dranch/boot
          sudo umount /media/dranch/rootfs

    4. Remove your newly imaged MicroSD card and install it into your Raspberry Pi.  On the Raspberry
       Pi 4,3+,3,2,ZeroW,Zero,1 install the SD card with the shiny electrical contacts pointing UP.

    5.  ALTERNATIVE Image installation and configuration approaches:

             The official Raspberry Pi Imager tool available for Ubuntu x86, Windows, and Mac
             offers several advanced abilities w/o having to connect a keyboard and display 
             to your Pi on first boot just like above but it can do more.  Examples include
             the following and it does all this by creating the /boot/ script:

                - set the hostname of the Pi
                - create a new login account with an SSH key and not a password
                - pre-configure Wifi
                - enable SSH
                - set your local settings (other languages, keyboard maps, etc)

             Most of those items are all optional things and this document covers how to set those 
           items configured otherwise:

2. Cable up and power up your Rpi

  a. Connect your monitor via the HDMI port.  If you only have a VGA computer monitor, there
     are HDMI to VGA converter devices out in the market that cost about $25.  I have one but I found the
     resulting video quality wasn't very good.  My specific unit ironically spews broadband RF noise all 
     across the VHF spectrum.  Sigh.

     OPTIONAL:  Connect your Ethernet cable if you have a Raspberry Pi Model B with an RJ45 
                jack or have a support USB to Ethernet adapter connected to any Raspberry Pi

  b.    If you want to update your Raspberry Pi and install additional software, you'll need 
        and Internet connection.  

        Please note that since your Rpi hasn't received any security hardening yet, there is 
        some risk here if it's connected to a network.  It's HIGHLY recommended that you put 
        your Rpi behind a home "router" or NAT device which doesn't have any direct Internet 
        other port forwards pointing to the Raspberry Pi's IP address.  If you don't follow 
        this precaution, your Raspberry Pi could get hacked especially if you chose not to 
        disable the default "pi" account that has a well known password!

        To be written:  Add configuring a Raspberry Pi Zero W or Raspberry Pi 3 with Wifi-only 
                        network access - this doc current assumes wired connectivity

               For the Rpi ZeroW, you can either connect a supported USB to Ethernet adapter 
               to add Wired Ethernet or you can place a configured wpa_supplicant.conf file in
               the SD card's /boot directory.  You'll also want to create an empty
               /boot/ssh file to have the Pi enable SSH access on first boot if you
               want to configure the Pi exclusively via a network connection (no HDMI
               and keyboard connected).

               If you need all this detail right now, there are other guides on the Internet 
               on getting this initially working.  Alternatively, email me and I can 
               help you.

  c. Connect up your powered USB hub to the Raspberry Pi

     1. Connect your USB keyboard and mouse to the USB hub; optionally, you can skip the
        USB hub and connect the KB and mouse directly to the Rpi

  d. Connect your USB sound card directly to the Rpi's USB ports (more on WHY this is required
     in a later section)

  e. Plug in the micro-USB cable power cable which is connected to an appropriate power
     brick to power on your Raspberry Pi.  

        WATCH the upper right hand corner to see if you see a yellow lightening bolt icon or if 
              the red LED on the Rpi occasionally blinks.  Why?

        The official recommendation from the Raspberry Pi Foundation is to use a 5.1v (not 5.0v) 
        power supply that provides 3.0A of power for the Rpi v4, 2.5A for a Raspberry Pi3, or 1.0A
        for an Rpi Zero-W though a thick, short, and quality made USB cable.  

        I would say that all users *MUST* follow this recommendation for Raspberry Pi v2 and even 
        v1s as well.  Unreliable power is the #1 issue with Raspberry Pis so please don't just use 
        any old power brick with any old USB cable (which might have under-gauged wire and/or are 
        too long).  

        I personally tried using a "quality" LG power brick that stated 5.0v @ 1.8A and while it 
        worked for a while, I started seeing the red LED on the Pi to blink and yellow lightening 
        bolt icon show up up as I added more stuff to it (I2C LCD, USB soundcard, external USB HDD
        (externally powered), etc).  Instead of an expensive "Official Raspberry Pi" supply, I 
        bought a Pro-Elec model # 28-19338 5.1v @ 2.5A supply and it's working well.

        REMEMBER: Longer the USB cable, the high chance of power issues which show up as Raspberry 
                  Pi crashes, corrupt file systems and even permanently physically damaged SD cards!  
                  Long power cords are a BAD idea.

  f. Booting up with the HDMI console:

        If you connected an HDMI monitor and a keyboard, when your Rpi boots up, you'll see different
        initial behaviors if using a Raspberry Pi OS image:

           - Step 1: All versions (LITE or GUI):  The kernel will boot up and you'll see a very brief 
                                                  message stating that it's resizing the SD card and 
                                                  then reboot after 5 seconds.  This is normal and 
                                                  allows the system to use the full size of your SD 

           - Step 2: Any of the various HEADLESS configuration items will be applied and the Raspberry
                     Pi will be rebooted

           - Step 3: Bullseye version 4/4/2022 - You will be taken through a configuration wizard to
                     and newer OS versions ONLY  configure some key parameters.  Some of these might 
                                                 have already been set by you via the HEADLESS section.  
                                                 If not, you will be prompted here to set things like 
                                                 language, Keyboard, Locale, etc.

           - Step 4: All versions: The OS will reboot again and on the HDMI console, you will be 
                                   auto-logged in either as your newlty created username (Bullseye version 
                                   4/4/2022 and newer only) or as the user "pi"

  g.  Booting up HEADLESS aka network setup:

      If you pre-enabled SSH access mentioned above in the HEADLESS section, once your newly imaged 
      Pi boots up, it should advertise itself on your home network via the netconf/avahi/boujour 
      system name of "raspberrypi.local".  Try pinging for it once it's booted from another with:

         ping raspberrypi.local

      Success?  If so, you can SSH directly to your newly imaged raspberry pi using the user account
                you enabled from above!  If you didn't do that, you will NOT be able to use SSH
                until you complete the setup wizard on the HDMI console and let the unit reboot first.

      Failure?  There are two general scenarios I can think of here:

         1. If the machine you're doing the pinging from comes back with:
               ping: raspberrypi.local: Name or service not known
            That means that either your Pi didn't boot or maybe it's not properly
            on the network

         2. If the machine you're doing the pinging from comes back with:
               ping: unknown host raspberrypi.local
            That means your machine most likely does not have netconf/avahi/boujour
            enabled (not a bad thing as I view this service as a security risk)

         If you know how, you can also look at your home router's logs and see which
         IP address was given to your newly booted Rpi via the DHCP server

2.a. How to enable the HDMI port to always work even if the cable isn't connected

  If you boot a Raspberry Pi without an HDMI monitor connected, the OS turns off the HDMI port
  to save power.  This means that if you later connect an HDMI port while it's already booted, 
  it won't display anything.  If you want the HDMI port to always work even if the cable isn't
  connected, edit the /boot/config.txt file:

    - nano /boot/config.txt    (you can also use:   vim "/boot/config.txt" if you don't like/know vim)

    - Find the line that has:


      Remove the # character so it just shows


  Save the file and your done.

     NOTE:  When the Raspberry Pi boots up, it communicates with the HDMI monitor to understand
            the monitor's best settings for the display output.  If you connect a monitor AFTER the 
            Rpi boots, the display WILL come up but it might not look the best or might not be showing
            it's highest resolution.  You can either reboot the Pi with the monitor attached and powered
            on to get the best display or alternatively, here are some commands to try to improve the 
            display manually such as:

            Newer OSes (bullseye) using the modern vc4-kms-v3d video driver:

               sudo apt install edid-decode
               edid-decode /sys/class/drm/card0-HDMI-A-1/edid

            Older OSes NOT using the vc4-kms-v3d driver:

              tvservice --explicit="DMT 35 HDMI"

            See the output of the command "tvservice --help" for more possibilities.

     NOTE #2: I've seen many times that if I connect an HDMI cable into an already booted Rpiv1
              (very common on old Rpi v1 models), the OS on the Raspberry Pi will crash.  You have to remove 
              and re-connect the Rpi's USB power cable to reboot it and hopefully, it didn't corrupt the
              SD card.  This happens because the initial power draw (called "inrush current") caused by 
              connecting the HDMI monitor can't be dealt with on early Raspberry Pi baords.  This issue can 
              be mitigated by:

                 1. Use a better power supply for the Rpi
                 2. Use a newer generation Rpi that has beter low voltage sag performance
                 3. Connect a large electrolytic capacitor to the +5.0v and +3.3v pins on the GPIO header to
                    absorb the voltage sag.  Setting this up is beyond this document but just google it or
                    email me for help.

2.b. How to disable Bluetooth and/or Wifi

    | Optional:                                                      |
    |                                                                |
    |    Disabling Bluetooth and/or Wifi minimizes any interference  |
    |    issues with Wifi and also lowers the Rpi power consumption. |
    |    Disabling Bluetooth also returns the use of the on-board    |
    |    HARDWARE serial port (UART) via the GPIO pins which is far  |
    |    more reliable than the software-emulated UART.  Do NOT      |
    |    disable Bluetooth if you intend to use it with other        |
    |    Bluetooth devices like enabling BT serial console or        |
    |    connectivity to a Kenwood TH-D74 HT for KISS packet / TNC   |
    |    access.                                                     |

  With the introduction of the Raspberry Pi v3 and Zero W, the Pi team added both Wifi 
  and Bluetooth functionality.  I welcome the new wireless support but it also brings in 
  complexity, power consumption, etc. when you might only want wired Ethernet.  In 
  addition, the Rpi team had to make some disruptive compromises:

     - the original hardware serial console support via the Rpi's GPIO 14/15 pins to 
       /dev/ttyAMA0 was taken over by the Bluetooth interface instead.  The GPIO-pin based
       serial console is now offered via by an EMULATED serial port which is evidently *variably* 
       clocked based on the speed of the GPU which turns out to be very unreliable.  The changing 
       clock speed of the emulated serial port *will* impact the serial console port from operating 
       properly.  There are additional hardware-based URLS say on the Rpi4 and CM4 but for 
       older Raspberry Pi units, you need to decide what you want to do.

     - Note #1: Later versions of the Raspberry Pi OS moved the hardware UART connected via the GPIO 
                pins from device /dev/ttyAMA0 device to the /dev/ttyS0 device

     - Note #2: On the Rpi v4, it seems the use of the secondary HDMI port at higher resolutions 
                interfers with 2.4Ghz wifi channels less than Channel 4 and also any Bluetooth 
                signals.  Try using 1080 or 4k resolutions instead

     - Note #3: On the Rpi v3, it seems that simultaneous usage of the Rpi's Wifi and Bluetooth is 
                not very reliable.  You may see lots of disconnections and re-association on both the 
                Wifi and Bluetooth sides.  This might get improved over time or with later versions 
                of the Rpiv3 hardware

  If you don't have any need for the wifi interface, you can disable it:

     vi /boot/config.txt

  If you don't have any need for the bluetooth interface, you can disable it:

     vi /boot/config.txt

     sudo systemctl disable hciuart.service
     sudo systemctl disable bluealsa.service
     sudo systemctl disable bluetooth.service

  GPIO Header Serial Console Access
  If you want to restore serial console port access on GPIO pins 14 & 15 to use the Broadcom 
  UART chip (the built-in hardware one) for reliable serial connections, see the following URL on 
  how to enable a "dtoverlay" in the /boot/config.txt file, see the following URL.  

     NOTE:  The Raspberry Pi 3B+ has the same limitations as the 3 in this respect
This topic is also covered later in this document to do either wired or Bluetooth based serial consoles as well!

3. Boot up the new image and prepare to do initial security on it

3.a Create a new user and disable the Pi user

      Many Raspberry Pis connected to the Internet are getting compromised as people aren't 
      changing the default username of "pi" and password.  As of 4/8/22, all Raspberry Pi OS
      images no longer includes the "pi" account.  This is a good thing!  Now, the initial boot 
      up process prompts the user to create a unique username (entering "pi" is NOT allowed) 
      when first booted.  This change is a significantly more secure approach for any Raspberry 
      Pi that will be directly exposed or available on the Internet.

         CRITICAL NOTE:  
         It should be noted that though I could ssh into my Rpi2 as a newly created user like 
         "dranch" with my privately configured password, I could *NOT* use that password to log 
         into the directly connected HDMI/keyboard console!  Why?  In troubleshooting this, if 
         I tried to type in my correct password but at the username prompt where I could see the
         characters, I could see the WRONG characters were popping up (like | or +, etc) on the 
         screen!  To fix this critical issue, see below on how to set the right KEYBOARD 
         CONFIGURATION.  Basically what was happening was that the Raspberry Pi defaults to the
         United Kingdom (UK) keyboard layout which changes the various characters shared with 
         the top 1, 2, 3, 4,5, 6, 7, 8, 9, 0 keys!  Changing it to the US keyboard set was the 

           sudo raspi-config 
              --> Localization Options --> Change Keyboard Layout --> Generic 104-key PC 
              --> Other --> For me, I need "English (US)" --> Now scroll back up and select "English (US)"
              --> "The default for the keyboard layout" --> No compose key --> Finish

        1. Users NOT using the Raspberry Pi Bullseye 4/4/22 version that requires you create a new

              New user: login to your new Rpi as the user "pi" and now let's create a new user with 
                         these commands.  In this example, we create the user "dranch" (please replace 
                         "dranch" with your desired username):

                            sudo adduser dranch

           1.a. Add this new user into the following UNIX groups:

                   Bullseye OS:  - be sure to change the username at the end of this line for your username
                   sudo usermod -a -G adm,audio,cdrom,dialout,gpio,i2c,input,netdev,plugdev,spi,sudo,video dranch 

                   Buster and older OSes - be sure to change the username at the end of this line for your username
                   sudo usermod -a -G adm,audio,cdrom,dialout,gpio,i2c,input,lpadmin,netdev,plugdev,spi,sudo,video dranch 

                These groups are needed for:
                - "adm" (allow some level of admin access) - default setting for the pi user
                - "audio" (allow users to access the soundcard)
                - "cdrom" (if you ever connect an external CDROM drive to the Rpi, allow access
                - "dialout" (allow serial port access - if needed for say Fldigi)
                - "gpio" (allow access to the GPIO pins)
                - "i2c" (new group access in Bullseye for I2C communications)
                - "input" (new group access for Bullseye)
                - "lpadmin" (new group access for Bullseye for printing services)
                - "netdev" (new group access for Bullseye)
                - "plugdev" (allow for better hot-plug events via UDEV)
                - "spi" (new group access in Bullseye for SPI communications)
                - "sudo" (allow root access)
                - "video" group (allow diagnostic permissions to the GPU)

              IMPORTANT: If you see any errors stating "group XXX does not exist", you will need to remove that
                         group and try again or NONE of the changes will be made for this new user

           1.b. If you already created this username before hand and are now adding some of 
                these Unix groups after the fact, you must log out and log back in to use 
                these new permissions.  Test and make sure you can both login using
                this new username and also run sudo commands

        2. OLD OSes only :: see the above note of the "pi" account existance and how it's now deprecated

             Later (meaning don't do it now), we will disable the "pi" user account but we won't 
             do it just yet

3.b Removing or disabling unwanted packages and services

   I recommend to remove the following packages to make your machine less bloated and more secure

       Bullseye: sudo dpkg -r avahi-daemon ipp-usb libnss-mdns

       Buster:   sudo dpkg -r avahi-daemon libnss-mdns

           What these packages do:

              avahi-daemon : This service is Linux's equivalent to Apple's Bonjour services advertisement 
                             protocol typically sent out on 5353/UDP.  It's a very chatty protocol and I 
                             personally view it as a security risk. As such, I recommend you remove it.  
                             libnss-mdns is related to supporting this package.

              ipp-usb      : This new package in Bullseye allows the IPP protocol over USB which is not
                             for most amateur radio setups

       I would also encourage you to run the commands like:

             netstat -an | grep -e ":\*"


             ps aux | less 

       and both observe and research what is running.  It seems more and more programs are being started 
       by default in Debian which is not a great idea for such a small computer and adds to it's bloat (like 
       Ubuntu, Mint, etc).  If you don't know what something is in this listing, DON'T touch it until you 
       research it and know for a fact that you can change / remove it.

3.c IPTABLES: Install and configure a simple but effective firewall

Whenever you have a computer that can communicate to the Internet, it's recommended and down right
*important* to have a firewall enabled on it to protect it.  Basically, firewalls only allow it to 
communicate to other machines on both your local network or beyond (aka the Internet).  This level
of control can be important when you install new programs on your system but you haven't secured 
them or aren't aware they allow incoming traffic that you're not expecting.  

There are lots of ways to manage a Linux firewall rulesets.  This documentation details how to
do things the classic "iptables" way (this is what Raspberry Pi OS as well as Debian defaults to as
well.  This approach is editing a text file with iptables rules.  For those of you who wish to use 
GUIs, there are many tools to choose from and here is a URL you can read to learn more:

The key point of this section is how to get an initial host firewall installed and how to manage it.
It also includes details that when you make any firewall firewall changes, they have to be perfect.  
If the rules aren't correct, you run the high risk of loosing connectivity to your Linux machine.  
Fixing the typo isn't hard but it can be tedious since you have to go back to the machine's console 
to do the fixes.  This section describes a method to avoid losing your connection and will
automcatically back out any bad firewall rules.

  | NOTE: A possible more "official" way for firewall management:                                |
  |                                                                                              |
  |       AH6IX wrote in and told me about the included "iptables-apply" program that's included |
  |       with the primary iptables package.  That tool evidently does the same thing as my      |
  |       below recommended script script but is the OFFICIAL way to do      |
  |       things but I haven't looked at this program yet but this might be a good (or better)   |
  |       way to go too.                                                                         |

  | NOTE #2:                                                                                     |
  |       nftables vs iptables                                                                   |
  |                                                                                              |
  |       Starting with Raspbian Buster, the default BACKEND kernel firewall technology has      |
  |       moved to the newer "nftables" system (iptables is deprecating).  You can learn more    |
  |       about this at:                                                                         |
  |                                                                                              |
  |                                                    |
  |                                                                                              |
  |       It's important to recognize that it seems that Debian Buster's support here seems to   |
  |       be a transition release using the "xtables" package suite.  In addition, the key "nft" |
  |       program from the nftables package isn't even installed by default.  This means that    |
  |       Buster still expects users to use the iptables utility to configure firewall uses that |
  |       ultimate programs the new netfilter backend.                                           |
  |                                                                                              |
  |       I will work on adding NATIVE support for nftables in time but until then, the long     |
  |       standing and well supported iptables remains fully compatible, secure, and is fully    |
  |       supported with all versions of Raspbian.                                               |

      Assuming your Raspberry Pi has Internet access (hopefully it's behind an existing firewall 
      to keep it safe until it's running it's own firewall), run:

          sudo apt update
          sudo apt install iptables-persistent
          # Accept any needed package dependencies like:
          #    "iptables-persistent" and "netfilter-persistent"

          You might be presented with a set of color boxes prompting:
             "Save current IPv4 rules".  --> Select YES

             "Save current IPv6 rules".  --> Select YES

      Once installed, let's create an initial security based upon the guidence from 
      Please note that the above URL file points to the WRONG files installed by iptables-persistent

      1. Let's go into the directory that will hold the firewall rules:

            cd /etc/iptables

         This directory should have been already created if you saved your existing firewall rules above.  Those
         files would be named rules.v4 and rules.v6.  If the directory is not there, please create it with:  

            sudo mkdir /etc/iptables

      2. If those saved rules files are there, let's rename them so they don't overlap but most likely,
         they will be empty files:

            sudo mv rules.v4 rules.v4.orig
            sudo mv rules.v6 rules.v6.orig

         To confirm that the files are empty, run:

            ls -la 

      3. Change the default firewall policies by running:

            #  If your not familiar with how to use the Vi editor, you can
            #  use Nano instead
            # change the INPUT and FORWARD policy lines from "ACCEPT" to "DROP"
            #   NOTE:  Please note that if you want your Raspberry Pi to NOT be completely 
            #          hidden on the Internet (aka.. it will respond to pings, sent ICMP 
            #          rejects, etc), consider using "REJECT" instead of "DROP" in the specific 
            #          rulesets below the POLICY lines in the rules.v4 and rules.v6 rulesets.  
            #          Packets that are ultimately REJECTED will get a rejection notice vs. 
            #          be silently dropped.   
            #   NOTE #2: The setting of REJECT in these top policy lines is NOT allowed as 
            #            only ACCEPT and DROP are allowed here.  As such, leave these top
            #            policy lines to DROP for now

            #Fetch some pre-configured the IPv4 rules
            #  NOTE:  this file is just an example that I use at home.  You will need to 
            #         change it to reflect your home's subnet addressing scheme, etc.

            cd /tmp
            sudo mv rules.v4 /etc/iptables/

               #NOT RECOMMENDED: Or fire up an editor and copy and paste in the following below:
               sudo vi rules.v4

         3.a. If you plan on using IPv6 (it might be running and you don't even know it), create 
              a copy of the ruleset and create the new ruleset.  You'll need to make similar 
              changes in this v6 file that you for v4

              #Fetch the IPv6 rules
              #  NOTE:  this file is just an example that I use at home.  You will need to 
              #         change it to reflect your home's subnet addressing scheme, etc.

              cd /tmp
              sudo mv rules.v6 /etc/iptables/

               #NOT RECOMMENDED: Or fire up an editor and copy and past in the following below:
               sudo vi rules.v6

      4. Create a copy of the ruleset and create the new ruleset:

         These downloaded "rules.v4" and "rules.v6" files will be used to allow in various traffic 
         and ultimately TEST all firewall changes before they are made the default firewall upon 
         every boot.  Add in the the need rules (if not already present) you need/desire for your 
         system but just be sure you understand what you're doing.  If you have questions, Google 
         it first and if you still need help, you can email me.

         The below firewall example (from the above downloaded rules.v4 file) includes:

            + ALLOWs incoming SSH connections on TCP port 22 and 2222 from specific addresses
            * ALLOWs incoming SSH connections on TCP port 22 and 2222 from any address
            + ALLOWs incoming PING packets
            + ALLOWs incoming DHCP response packets for the Rpi to get a TCP/IP address
            + ALLOWs all outgoing connections and responses to other allowed sessions
            - DENYs incoming Samba / Windows File/Print traffic
            - DENYs all other incoming traffic

         You will probably want to comment out the lines allowing specific internal IPs and uncomment out
         the lines allowing ANY source addresses for port SSH traffic like so:

         NOTE:  The downloaded rules.v4 / rules.v6 files are going to be the most up to date but
                these below notes are intended to be a rough guide:

            # Allows SSH connections
            # The --dport number is the same as in /etc/ssh/sshd_config
            #-A INPUT -p tcp -m state --state NEW -s --dport 22 -j ACCEPT
            #-A INPUT -p tcp -m state --state NEW -s --dport 2222 -j ACCEPT
            #-A INPUT -p tcp -m state --state NEW -s --dport 22 -j ACCEPT
            #-A INPUT -p tcp -m state --state NEW -s --dport 2222 -j ACCEPT
            #-A INPUT -p tcp -m state --state NEW -s --dport 22 -j ACCEPT
            #-A INPUT -p tcp -m state --state NEW -s --dport 2222 -j ACCEPT
            #Other global rules
            -A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT
            -A INPUT -p tcp -m state --state NEW --dport 2222 -j ACCEPT

         You will need to make the appropriate copy/pastes and any possible changes you might want
         for your specific setup:

sudo vi /etc/iptables/rules.v4
# Load with                  iptables-restore < /etc/iptables.up.rules
# save altered rules with    iptables-save > /etc/iptables.up.rules


# Allows all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -d -j REJECT

# Accepts all established inbound connections

# Allows all outbound traffic
# You could modify this to only allow certain traffic

# Allows SSH connections 
#  Placing your Rpi on the raw Internet (no firewall in front of it) and having
#  SSH enabled is NOT recommended.  If you need this, I would recommend additional
#  protections (not covered in this document at the moment)
#    - change the default SSH port 22 to something else
#    - port knocking
#    - use SSH keys ONLY (no passwords)
# The --dport number is the same as in /etc/ssh/sshd_config
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW --dport 2222 -j ACCEPT
-A INPUT -p tcp -m state --state NEW --dport 5900 -j ACCEPT
-A INPUT -p tcp -m state --state NEW --dport 5901 -j ACCEPT

# Other more specific allows
#-A INPUT -p tcp -m state --state NEW -s --dport 22 -j ACCEPT
#-A INPUT -p tcp -m state --state NEW -s --dport 2222 -j ACCEPT
#-A INPUT -p tcp -m state --state NEW -s --dport 22 -j ACCEPT
#-A INPUT -p tcp -m state --state NEW -s --dport 2222 -j ACCEPT
#-A INPUT -p tcp -m state --state NEW -s --dport 22 -j ACCEPT
#-A INPUT -p tcp -m state --state NEW -s --dport 2222 -j ACCEPT

# Now you should read up on iptables rules and consider whether ssh access 
# for everyone is really desired. Most likely you will only allow access from 
# certain IPs.

# Allows HTTP and HTTPS connections from anywhere (the normal ports for websites)
#-A INPUT -p tcp --dport 80 -j ACCEPT
#-A INPUT -p tcp --dport 443 -j ACCEPT

# Allow ping
#  note that blocking other types of ICMP packets is considered a bad idea by 
#  some remove -m ICMP --icmp-type 8 from this line to allow all kinds of icmp:
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

#Allow DHCP incoming addresses
-A INPUT -p udp --sport 67 --dport 68 -j ACCEPT

# Block but don't log local samba traffic - expand to whatever you need
-A INPUT -p udp --sport 138 --dport 138 -j DROP

# log iptables denied calls (access via 'dmesg' command)
#-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7
-A INPUT -m limit --limit 5/min -j NFLOG --nflog-group 0 --nflog-prefix "iptables denied: "

# Reject all other inbound - default deny unless explicitly allowed policy:


sudo vi /etc/iptables/rules.v6
:INPUT DROP [41:5516]

# Accepts all established inbound connections

# Allows all outbound traffic
# You could modify this to only allow certain traffic

# Allows SSH connections
#  Placing your Rpi on the raw Internet (no firewall in front of it) and having
#  SSH enabled is NOT recommended.  If you need this, I would recommend additional
#  protections (not covered in this document at the moment)
#    - change the default SSH port 22 to something else
#    - port knocking
#    - use SSH keys ONLY (no passwords)
# The --dport number is the same as in /etc/ssh/sshd_config
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW --dport 2222 -j ACCEPT
-A INPUT -p tcp -m state --state NEW --dport 5900 -j ACCEPT
-A INPUT -p tcp -m state --state NEW --dport 5901 -j ACCEPT

# Other more specific allows
#-A INPUT -p tcp -m state --state NEW -s --dport 22 -j ACCEPT
#-A INPUT -p tcp -m state --state NEW -s --dport 2222 -j ACCEPT
#-A INPUT -p tcp -m state --state NEW -s --dport 22 -j ACCEPT
#-A INPUT -p tcp -m state --state NEW -s --dport 2222 -j ACCEPT
#-A INPUT -p tcp -m state --state NEW -s --dport 22 -j ACCEPT
#-A INPUT -p tcp -m state --state NEW -s --dport 2222 -j ACCEPT

# Now you should read up on iptables rules and consider whether ssh access
# for everyone is really desired. Most likely you will only allow access from
# certain IPs.

# Allows HTTP and HTTPS connections from anywhere (the normal ports for websites)
#-A INPUT -p tcp --dport 80 -j ACCEPT
#-A INPUT -p tcp --dport 443 -j ACCEPT

#Allow DHCP incoming addresses
-A INPUT -p udp --sport 67 --dport 68 -j ACCEPT

# Block but don't log local samba traffic - expand to whatever you need
-A INPUT -p udp --sport 138 --dport 138 -j DROP

#Allow IPv6 pings
-A INPUT -p icmpv6 -m icmpv6 --icmpv6-type 8 -j ACCEPT

# log iptables denied calls (access via 'dmesg' command)
#-A INPUT -m limit --limit 5/min -j LOG --log-prefix "ip6tables drop: " --log-level 7
-A INPUT -m limit --limit 5/min -j NFLOG --nflog-group 0 --nflog-prefix "iptables denied: "

# Reject all other inbound - default deny unless explicitly allowed policy:
-A INPUT -p icmpv6 -m icmpv6 --icmpv6-type 8 -j DROP

#Unlikely that FORWARD will be reached unless FORWARDING is explicitly enabled


      5. How to activate new or modified rules 

         | NOTE:  If you made any mistakes in the above ruleset file and if you activate          |
         |       the firewall without doing some special precautions, you run the risk of loosing |
         |       your network connection!  If this happens, you'll need to connect to your        |
         |       via the console (HDMI video, USB keyboard) to restore access with the command:   |
         |                                                                                        |
         |            Basic way to enable rulesets which can pose risk                            |
         |            iptables-restore < /etc/iptables/rules.v4.orig                           |
           #1 - RECOMMENDED METHOD:
                 I encourage you to use my script to load new rulesets.  This 
                 script will activate the new firewall and then prompt you to make sure things went 
                 OK.  If you don't respond in 30 seconds, the script will rollback to the previous working 
                 firewall ruleset.  This is very very helpful!  To get and use this script, do the following:
                    cd /tmp
                    sudo mv /usr/local/sbin/
                    sudo chmod 700 /usr/local/sbin/

                 Let's give the script a try with the following steps and follow the prompts:

                      #1: All GOOD firewall rules are saved in the file named rules.v4.checked so lets create
                          that with the initial ruleset that was created which is essentially the firewall 
                          running but doesn't do anything except allow everything:

                             sudo cp /etc/iptables/rules.v4.orig /etc/iptables/rules.v4.checked
                             sudo cp /etc/iptables/rules.v6.orig /etc/iptables/rules.v6.checked

                      #2: Run this command to start the script and it's countdown.  

                            NOTE: It's CRITICAL key that the & character is included at the end of the line
                                  or things won't work properly!

                             sudo /usr/local/sbin/ &

                      #3: Within 30 seconds, you need to "blindly" type in the follow command while some of your
                          keystrokes get overwritten by the countdown.  This overwriting is expected:

                             touch /tmp/fwok

                          If you don't run this second command (or cannot run it because the terminal stops 
                          responding), the firewall will revert back to the previous working firewall rules  
                          and hopefully will restore your connection.  This is exactly want we want!  

                      #4: If everyting seems to be working without any major delays or ERRORS, this means your 
                          new firewall ruleset installed OK.  Very good!  Now make this new ruleset your
                          new default ruleset with:

                          sudo cp /etc/iptables/rules.v4 /etc/iptables/rules.v4.checked
                          sudo cp /etc/iptables/rules.v6 /etc/iptables/rules.v6.checked

           #2 - NOT RECOMMENDED: Alternative method:

                Temporarily load in the new firewall rules
                   sudo iptables-restore < /etc/iptables/rules.v4
                   sudo ip6tables-restore < /etc/iptables/rules.v6

      6. By loading your new firewall rules, you hopefully you didn't just loose your network connection to 
         your Rpi (you wouldn't if you use my recommended script above) due to any 
         syntax errors or typos.  Confirm you still have a working network connection by hitting the ENTER key 
         a few times.  If you see a bunch of new command line Bash prompts, things are good.  Look at the output 
         of the command to confirm things look like you expect them to:

            #View the loaded IPv4 ruleset:
            sudo iptables -vL
            Chain INPUT (policy DROP 0 packets, 0 bytes)
             pkts bytes target     prot opt in     out     source               destination
                2   100 ACCEPT     all  --  lo     any     anywhere             anywhere
                0     0 REJECT     all  --  !lo    any     anywhere             reject-with icmp-port-unreachable
             5304  395K ACCEPT     all  --  any    any     anywhere             anywhere             state RELATED,ESTABLISHED
                3   180 ACCEPT     tcp  --  any    any     anywhere             anywhere             state NEW tcp dpt:ssh
                0     0 ACCEPT     icmp --  any    any     anywhere             anywhere             icmp echo-request
               33 10824 ACCEPT     udp  --  any    any     anywhere             anywhere             udp spt:bootps dpt:bootpc
             7188 1838K DROP       udp  --  any    any     anywhere             anywhere             udp spt:netbios-dgm dpt:netbios-dgm
            25831 1765K NFLOG      all  --  any    any     anywhere             anywhere             limit: avg 5/min burst 5 nflog-prefix  "iptables denied: "
            32958 2307K REJECT     all  --  any    any     anywhere             anywhere             reject-with icmp-port-unreachable

            Chain FORWARD (policy DROP 0 packets, 0 bytes)
             pkts bytes target     prot opt in     out     source               destination
                0     0 REJECT     all  --  any    any     anywhere             anywhere             reject-with icmp-port-unreachable

            Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
             pkts bytes target     prot opt in     out     source               destination
             3884  606K ACCEPT     all  --  any    any     anywhere             anywhere

            #View the loaded IPv6 ruleset:
            sudo ip6tables -vL
            Chain INPUT (policy DROP 0 packets, 0 bytes)
             pkts bytes target     prot opt in     out     source               destination         
                0     0 ACCEPT     all      any    any     anywhere             anywhere             state RELATED,ESTABLISHED
                0     0 ACCEPT     tcp      any    any     anywhere             anywhere             state NEW tcp dpt:ssh
                0     0 ACCEPT     tcp      any    any     anywhere             anywhere             state NEW tcp dpt:2222
                0     0 ACCEPT     udp      any    any     anywhere             anywhere             udp spt:bootps dpt:bootpc
                0     0 DROP       udp      any    any     anywhere             anywhere             udp spt:netbios-dgm dpt:netbios-dgm
                0     0 ACCEPT     ipv6-icmp    any    any     2603:3024:185e:b000::/56  anywhere             ipv6-icmptype 8
                0     0 NFLOG      all      any    any     anywhere             anywhere             limit: avg 5/min burst 5 nflog-prefix  "iptables denied: "
                0     0 DROP       all      any    any     anywhere             anywhere            
                0     0 DROP       ipv6-icmp    any    any     anywhere             anywhere             ipv6-icmptype 8

            Chain FORWARD (policy DROP 0 packets, 0 bytes)
             pkts bytes target     prot opt in     out     source               destination         
                0     0 REJECT     all      any    any     anywhere             anywhere             reject-with icmp6-port-unreachable

            Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
             pkts bytes target     prot opt in     out     source               destination         
                0     0 ACCEPT     all      any    any     anywhere             anywhere

      7. If things look good, let's save the new firewall ruleset to become your default

           8.a.  RECOMMENDED: approach:

                 If you're using the script and you've now confirmed the new 
                 firewall ruleset seems to work, save that new ruleset as your NEW fallback firewall 

                    sudo cp /etc/iptables/rules.v4 /etc/iptables/rules.v4.checked
                    sudo cp /etc/iptables/rules.v6 /etc/iptables/rules.v6.checked

           8.b.  Alternative approach:

                 #This essentially won't do anything as the rules.v4 firewall is already there but
                 # I put this as a FYI:
                 sudo sh -c "iptables-save > /etc/iptables/rules.v4"
                 sudo sh -c "ip6tables-save > /etc/iptables/rules.v6"

      8. Now enable the firewall to start up upon every boot by create the following file and add the
         lines in the startup file:

           sudo vi /etc/network/if-pre-up.d/iptables
            /sbin/iptables-restore < /etc/iptables/rules.v4
            /sbin/ip6tables-restore < /etc/iptables/rules.v6

      9. Make the script executable with:

           sudo chmod +x /etc/network/if-pre-up.d/iptables

     10. To make sure things working by default if your Rpi is rebooted, let's test it.  Let's reboot now!

            sudo /sbin/shutdown -r now

     11. Once the Rpi has rebooted, make sure you can SSH back into it, and ensure that the output of 
         the command:

            sudo iptables -vL
            sudo ip6tables -vL

         Make sure it the two key lines as well as any other specific rules you expect to 
         be there (be it DROP or REJECT depending on what you setup):

             Chain INPUT (policy DROP)
             Chain FORWARD (policy DROP)

     12. If you cannot SSH into the Raspberry Pi, you probably made an error in the rules.v4 file.
         You will need to log into the Raspberry Pi via the console (HDMI monitor and keyboard),
         fix the offending issue in the firewall ruleset, and reload it again with the firewall-confirm
         script or reboot the Pi again.

     13. With the firewall in place, you will start seeing iptables block log entries in both
         /var/log/syslog but also in your "dmesg" output:

            iptables drop: IN=eth1 OUT= MAC=01:00:5e:00:00:01:ec:38:73:97:90:54:08:00 SRC= DST= LEN=32 TOS=0x00 PREC=0xC0 TTL=1 ID=30813 PROTO=2 

         IMHO, this is VERY annoying so we'll fix this in a section below using the ulog2 system.

      | IMPORTANT:                                                                   |
      |           It's very important to understand that the above firewall ONLY     |
      |           allows in any v4 protocol and blocks all IPv6 traffic.  If you     |
      |           have a public IPv6 address and want to allow in traffic, you'll    |
      |           need to update the above firewall rules.                           |

4. Rpi initial setup (OS patches), additional Security hardening, Rpi firmware upgrade)

Now that your Raspberry Pi has some initial firewall protection, let's start configuring 
your Raspberry Pi hardware and software:

   IMPORTANT: Once the Rpi boots back up, log in as your newly created user (in the above example, 
              I created and and logged in as the user "dranch" and not the "pi" user.  You need
              to log in with that new username

         NOTE #1: this is for OLD OSes only (see the note of the "pi" account existance is now deprecated)

              Did it work and you were able to login as this non "Pi" user?  If so, great!  If not, 
              you MUST fix this issue before moving on.

         NOTE #2: In the below instructions, I recommend you to change the "locale" of where you 
               live which changes the character set on your keyboard.  I saw an issue that once 
               I changed the locale from the UK to the US, I couldn't SSH in with the password that 
               I set for the newly created user when it was done on the Rpi console (monitor, keyboard,
               mouse).  This issue turned out to be an issue with the wrong keyboard 
               layout (default Locale --> Keyboard setting in the raspi-config tool is "UK" 
               and not "US") which moves around or replaces some of the various punctuation characters 
               associated with the top number keys: ~ ! @ # $ % ^ & * ( ) _ + .  Once I changed the 
               keyboard mapping to "US", I had to reset the password and things then worked ok.

  | NOTE:                                                                           |
  |      It's important that you run these commands using your newly created        |
  |      username as created above and *NOT* as the "pi" user.  It matters!         |
  |                                                                                 |
  |                                       ---                                       |
  |                                                                                 |
  | NOTE #2: the ORDER of making these changes *matters* so it's REQUIRED to follow |
  |           these steps in the order shown here                                   |
  |                                                                                 |
  | NOTE #3: The raspi-config program has changed a LOT over they years and the     |
  |          following steps reflect the layout and settings for Raspberry Pi       |
  |          Buster but there have been big changes rolled out even during Buster's |
  |          release cycle.  If your version of raspi-config looks different or has |
  |          items in different places, that's ok but you still need to set ALL     |
  |          these items.                                                           |

   a. Run the Raspbian OS configuration tool:

         sudo raspi-config

   b. Change the following areas:

      - System Options:

          - Hostname
            - Make the hostname something unique so you know which Linux machine you're on

         - Boot / Auto Login
             - Console
               - If you installed the "Lite" version of Raspberry Pi OS / Raspbian, you're NOT 
                 going to be running Xwindows and consuming all that RAM for the GUI that you
                 probably won't use much.  A such, select "Console"

               - I do NOT recommend to use any of the "auto-login" options as it makes your
                 machine less secure

         - Interfacing options
              - Legacy-Camera : Enable this ONLY if you 1) plan on using a CSI cabled Raspberry PI 
                                camera via using the OLD pre-Bullseye operating system.  If you're
                                using Bullseye, do NOT enable this

              - SSH        : Enable this: I recommend to enable SSH for remote management

              - VNC        : If you installed the Desktop or Full version of Raspberry Pi OS wth
                             a GUI and you want to manage it via a remote computer, enable this

              - SPI        : If you have any SPI high speed devices and plan to use them

              - I2C        : If you have any I2C low speed devices and plan to use them, enable this
                             Users wanting to add an RTC or a TNC-Pi devices will need to enable this

              - Serial     : If you plan on using the hardware serial port for say serial console,
                             either via bluetooth or the physical GPIO pins, enable this.
                             NOTE: If you're going to use a TNC-Pi TNC HATT NOT operating in I2C mode, 
                                   do NOT enable this option

              - 1-wire     : If you plan on using the 1-wire slow speed devices (GPIO 4), enable this

              - Remote GPIO: If you plan on enabling the remote GPIO via pigpio network functionality,
                             enable this

         - Localization options

              - Locale  (previously mentioned in the previous section)

                   - Since I am in the USA, I unselected "en_GB.UTF-8 UTF-8"  (GB stands for "Great Britain") 
                     and selected "en_US.UTF-8 UTF-8".  At the second prompt, I chose "en_US.UTF-8" as the 
                     default language.  You will need to select the correct language for your needs

                     - When prompted, I then selected default locale: en_US.UTF-8 for my USA location

                     |  CRITICAL:  I've seen that after I change this setting in Raspbian Buster, the |
                     |             interface started complaining about missing map files and started  |
                     |             doing strange things.  If you see this, I recommend to exit the    |
                     |             raspi-config tool and reboot the Pi with:                          |
                     |                                                                                |
                     |                sudo /sbin/shutdown -r now                                      |
                     |                                                                                |
                     |             After the Pi comes back up, log back in and finish up on any       |
                     |             remaining steps in this section                                    |

              - Timezone (set to your timezone)
                   - I selected "America" --> "Los Angeles" which is one way to set the "Pacific" timezone
                     with Daylight Savings support

              - Keyboard 
                   - this option is only seen when running raspi-config text interface via a terminal window  
                     I do NOT see this via the GUI version of the tool running on the Raspberry Pi OS "desktop" 
                     or "Full" versions:
                     IMPORTANT: If you are in the United (US) and you're only presented with 
                                "English (UK)", you need to select "OTHER", then select "English (US)"

                    - Generic 104-key PC (with a Windows key, else select 101-key) --> Other --> For me, 
                      I need "English (US)" --> Now scroll back up and select "English (US)" --> "The 
                      default for the keyboard layout" --> No compose key --> OK

              - Wlan country (for Wifi)
                   - If you have an Rpi v3 or Zero W, you need to set your correct country.  I selected 
                     "US United States"

         - Advanced options
            - "Expand the file system" - This feature is usually automatically run when you first booted from 
                                         this specific uSD card.  You would see this on your monitor
                                         saying "Expanding the Filesystem" and then it reboot your Rpi.  
                                         You shouldn't need to run this command but what it does is tells the 
                                         Raspberry Pi OS to change the uSD card's partitioning scheme to use 
                                         the full capacity of the card.  To confirm things expanded as expected, 
                                         open another terminal terminal window and run the command "df".  Look at 
                                         the "/dev/root" device line and look at the "Available" column's value.  
                                         It should be ROUGHLY the size of your uSD card in Kbytes.  For me, a 32GB 
                                         microSD card shows as "27201292" or 27GB (the missing space between 32GB 
                                         and 27GB is due to the file system's overhead and is expected).

                                         If you didn't see your system using the expected size, select this 
                                         option.  It will prompt you to reboot once it's done.  After that,
                                         come back to this section and complete any remaining steps.

            - Network interface names

              # NOTE: This might be disabled now but is still VERY important to check if using Linux's AX25 packet radio system
              - Enable Predictable Network interface names --> NO

   c. If you've made any changes to your Rpi via raspi-config, it will prompt you to reboot.  Accept
      the reboot and wait for it to come back up

4.a Harden the Raspbian installation

   1. If you're now logged in as your new user (NOT as user "pi), make sure you can use the "sudo" command
      such as:

         sudo ls -la /root

      Did that work?  If not, you MUST fix this before moving on (see the "usermod" command in the
      previous section)

   2. OLD OS Images only: CONSIDER deleting or locking the "pi" user - Old Raspberry Pi OS versions

        NOTE: Please see the 4/8/22 note of how the "pi" account is now no longer created nor ALLOWED
              on new versions of Raspberry Pi OS - Bullseye and newer

        Now that you created login and tested this new username, let's now consider removing
        the "pi" account as just the existence of this well known account, even being locked out as
        this document previously recommended, still remains a security risk:

          | CRITICAL NOTE:                                                                        |
          | --------------                                                                        |
          |    There are a lot of pre-built Rasperry Pi images that depend on both the presence   |
          |    and have various files in the /home/pi directory.  It's recommended to run the     |
          |    command:                                                                           |
          |                                                                                       |
          |       sudo ls -la /home/pi                                                            |
          |                                                                                       |
          |    and make sure there aren't any critical files in there.  If there is or your       |
          |    not sure, do NOT delete this "pi" user's home directory and all of it's contents.  |
          |    Instead, use option #2 below and just LOCK the "pi" user's account.                |
          |                                                                                       |
          |    It will take some time for various amateur radio Raspberry Pi images, programs,    |
          |    documentation, etc. to catch up to this distruptive removal of the "pi account.    |

          If it looks ok to remove / disable, consider disabling or even deleting the Pi account

           a. Option A: Keep the user "pi" around, at least LOCK out the account so you cannot 
                        log into it directly with:

                 sudo usermod -L pi

              NOTE:  If you have your OS set to auto-login the "pi" user on the local GUI console,
                     this will CONTINUE to function.  This will only impact remote SSH logins not
                     being able to login as the "pi" user

           b. Option B: delete the "pi" account

                 sudo userdel -r pi

              You might see the output:

                  userdel: pi mail spool (/var/mail/pi) not found

              This is ok as it just means no previous email was found for the user "pi".  Ignore it.

   3. OPTIONAL: Disable auto-login (GUI enabled versions of Raspberry OS):

         Double check: If you installed one of the GUI versions of Raspberry Pi OS (not the Lite CLI-only 
         version), the system by default will auto-login the "pi" user into the LXDE desktop.  This 
         default is very insecure and I recommend to disable this. Run:

            sudo raspi-config

              In the menu, select "Boot Options" --> "Desktop / CLI" and select
              "Desktop GUI, requiring user to login"

   4. Remove any unneeded or unwanted applications that came pre-installed in Raspberry Pi OS

      Disable any other OS level daemons:
        #Disable NFS clients unless you plan on using this
        sudo systemctl disable

      Depending on the version of OS you installed on your Rpi (Raspberry Pi OS "Desktop and recommended software" 
      aka "Desktop" (GUI), or "Full" (GUI) or "Lite" (CLI only), you might might have brought in a bunch of 
      stuff you won't need/want.  I recommend you uninstall what you don't need.  For example, on the 
      "Desktop and recommended software" GUI) version (was previously named "Pixel") version of Raspberry Pi
      OS includes:

              - OpenOffice suite of document, spreadsheet, and presentation creation tools

              - Wolfram GUI scientific package is included on the Pixel version of Raspbian

              - Scratch (only found on older versions of the Raspbian releases)

                # To remove these programs
                 sudo apt remove --purge wolfram-engine libreoffice* nuscratch

        You can get a complete list of what other packages are installed in your Raspberry Pi OS by 

           sudo dpkg -l | less

        | IMPORTANT:                                                                |
        |                                                                           |
        |  Unless you know what each package does and understand it's dependencies, |
        |  DO NOT REMOVE IT                                                         |

   5. For Raspberry Pi OS, automatic OS updates are done via SystemD.  I don't recommend to do
      automatic updates because if something breaks, you won't know why.  To disable it,
      do the following commands:

               sudo systemctl disable apt-daily.timer
               sudo systemctl disable apt-daily.service

            Thoughts on Updates/upgrades:
            If you have multiple remote Raspberry Pis running at different locations, I'd 
            recommend to upgrade the most easily fixable or "accessible" Pi *first*.  

            If and only if that upgrade goes well on that Pi, then you can probably feel safe
            in kicking off remote upgrades for all your other deployed Pis.  Those upgrades
            can be done as simply as using SSH and manually running the following commands to 
            start an upgrade and reboot (with checking the Unix exit code for each step).  You 
            can also consider using automation systems like Ansible, Salt, Chef, Puppet, etc.  
            but that's well beyond the scope of this document.  If you're curious about Ansible,
            email me and I can let you know what I think of it, send you some cheatsheets, etc.

      FYI on other update methods found in other Linux distros:
      As a heads up for Raspberry Pi OS users, this OS is heavily based on the vanilla Debian Stretch 
      OS release includes an OS auto-updating ability as mentioned above.  While some people might like 
      and even NEED this concept here (aka.. lazy or inattentive users), it's probably NOT good idea for 
      amateur radio applications.  Why?  

      I've just seen too many upgrades cause problems and once something breaks, you won't have no idea 
      why.  Once a system has becomes broken (even unreachable) due to an update, repairing it can be 
      very difficult if not impossible until fixed packages are released.  

      Anyway, if you're NOT running a Raspberry Pi OS version of OS (this example is for Ubuntu),
      I recommend you check the presence of the tool and remove it (if it exists):

         dpkg -l | grep unattended-upgrades

            If the package is installed, remove it with the following steps.  If it's NOT installed, you 
            can skip this command:

               sudo dpkg -r unattended-upgrades

  6. Let's make sure your machine is up to date.  Run the following commands when
     you have an Internet connection and a LOT of time (maybe late at night before you
     go to bed):

          All Raspberry Pi OS versions:
             sudo apt clean

             sudo apt update

             # Notice the "--no-install-recommends" - this is to avoid possible bloating
             # of your installation
             sudo apt upgrade --no-install-recommends

             sudo apt full-upgrade --no-install-recommends

             BEWARE: You can choose to also do "auto-removes" but I've seen it create package 
                     removal list which is removing packages I needed!  Not good!
                     # Be careful: If you want to try it, the command is:
                     sudo apt autoremove

                -- You should see a bunch of things be free if you removed the Avahi daemon
                   as it drags in all kinds of bloated stuff

          Raspberry Pi 4 / CM4 / 400 hardware:
          If you have a Rpi4, consider updating the firmware on the dedicated hardware EEPROM:

             sudo apt install rpi-eeprom

             sudo rpi-eeprom-update

                - This will tell you if you need to do any updates or not

                - If you do need an update, run:

                     sudo rpi-eeprom-update -a

  7. Prepare a new script to occasionally purge old kernels

      Raspberry Pi OS (aka Debian for Raspberry Pis) has a nasty habit of keeping around old kernels,
      especially the "rpi-update" kernels.  You can remove that bloat with the following script.  
      You can either download this script with:

          cd /tmp

       Or you can manually create the script by pasting in the following (getting it this way is
       not recommended to avoid copy/paste errors):

          vi /tmp/
          echo -e "\nListing old Raspbian based kernels that can be removed"
          dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d' 
          #    | xargs sudo apt -y purge
          echo -e "\n"You can edit this script to add the following line to the above line to auto-purge these packages"

          echo -e "\nRemoving left over rpi-update kernel modules that are not used for the current `uname -r` kernel"
          cd /lib/modules
          ls -1 | grep -v `uname -r` | xargs rm -Rf

       Now put it in the right place, give it execution permissions:
          sudo mv /tmp/ /usr/local/sbin/
          sudo chmod 700 /usr/local/sbin/

       After every so many times you update your system, you can run this script to purge any left over unused 
       kernel packages that weren't automatically cleaned up.  This script will also delete any installed kernel modules
       that are NOT usable by your system.  For example:

            # ls -lat /lib/modules 
            total 24
            drwxr-xr-x  3 root root 4096 Dec  1 13:59 5.10.63-v8+  <--- used by Rpi4, CM4, Rpi400 only
            drwxr-xr-x  3 root root 4096 Dec  1 13:59 5.10.63-v7l+ <--- used by Rpi3+, 3, 
            drwxr-xr-x  3 root root 4096 Dec  1 13:59 5.10.63-v7+  <--- used by Rpi2 
            drwxr-xr-x  3 root root 4096 Dec  1 13:59 5.10.63+     <--- used by Rpi1i, 1+, Zero, and Zero-W

          sudo /usr/local/sbin/

  8. NOT RECOMMENDED but good to know:

         Sometimes there is newer firmware and possibly a better, bleeding edge kernel for your Raspberry Pi that might
         resolve some of your technical issues.  If it's been recommended to try it, go ahead and run:

            #WARNING: Newer bleeding edge firmware and kernels might destablize your setup
            sudo rpi-update

      If the above program is not installed, do the following and then try again:

         sudo apt install rpi-update 

  9. If any new updates or new kernels were installed, it's recommended to reboot to make all updates active

      If you monitored the "apt upgrade" stages, you probably already know if a new kernel was installed but 
      you can programatically confirm if you need to reboot with this script:

         vi /usr/local/bin/

         # 12/01/21 - Dranch - initial version

         # workaround to determine if the host needs to be rebooted as the standard Linux
         #  /var/ temp file isn't set in Raspberry Pi OS / Raspbian


         CURKERN="`uname -r | awk -F+ '{print $1}'`"
         NEWKERN="`ls -1t /lib/modules | grep -v "-" | head --lines=1 | awk -F+ '{print $1}'`"

         if [ $DEBUG -eq 1 ]; then
            echo -e "Current running Kernel: $CURKERN"
            echo -e "New available kernel  : $NEWKERN"

         Current running Kernel: 5.10.52
         New available kernel  : 5.10.63

            #If there is a difference, then reboot to get the newer kernel
            sudo /sbin/shutdown -r now  

  10. OPTIONAL: Placing your Rpi on the raw Internet (no firewall in front of it) and having
                SSH enabled is generally NOT recommended.  If you need this, I would recommend 
                additional at least this following protection.  

         If your Raspberry Pi isn't going to be directly connected to the raw Internet (not 
         behind some form of a NAT/Router), you probably don't need to do this.

         a. change the default SSH port 22 to some other port number

            - Doing this offers some reduction in drive by attacks but not for full attacks 
              as port scanning will find your new port.  To change this, edit the SSH daemon 
              config file:

                 sudo vi /etc/ssh/sshd_config

                    - find the line that reads

                         #Port 22

                      and change it to say

                         Port 2222

         b. If you implemented the above IPTABLES firewall setup, you'll now need to update the 
            iptables ruleset to allow port TCP port 2222.   You will need to add this new port 
            into the various rules found in the /etc/iptables/rules.v4 and rules.v6 files.  Once 
            the rule files are updated, follow the process to use the /usr/local/sbin/ 
            script to make them active.

               NOTE:  Consider allowing both port 22 and port 2222 to give you a transition
                      stage.  Once sshd is restarted and you reconnect on port 2222, again 
                      update the firewall and REMOVE the legacy 22 port rules.

         c. Restart the SSH service or reboot your Rpi to start using port 2222

            #To restart the service
            sudo systemctl restart ssh

         d. In a new window, SSH to your Raspberry Pi using the new 2222 port:

               ssh -p 2222 <remote IP address>

         e. If you implemented the above IPTABLES firewall, it's recommend to aain update it
            again to REMOVE the original TCP port 22.   Delete that rule in the /etc/iptables/rules.v4 
            file and follow the process to use the /usr/local/sbin/ script
            to make that active.

4.b (OPTIONAL): Use SSH keys ONLY for logging into remote systems and DISABLE passwords

         1. (OPTIONAL): Use SSH keys ONLY for logging into remote systems and DISABLE passwords

            There is an industry wide push to completely remove the use of passwords as too many 
            users use exceptionally weak passwords and/or use the same password across too many 
            systems.  In addition, the removal of passwords dramatically helps lowering the risk 
            of brute force password attacks as SSH keys are far more secure.  The use of SSH keys
            also makes doing automated system management using say Ansible a breeze.  Finally, it's 
            also worth mentioning that you can have MULTIPLE SSH keys which can be used for say:

               - one SSH key per a set of remote hosts as yourself
               - one SSH key used for automation purposes like Ansible
               - one SSH key per unique remote host (pretty overkill)
               - anywhere in between

            Most Unix-based OSes have supported SSH keys for decades as well as the better network
            equipment like routers, switches, etc.  SSH is everywhere it's it's recommended to use 

            NOTE:  One downside to this approach is that if you want to log into a given remote
                   system from some OTHER machine than your usual computer, you MUST copy over 
                   this newly created PRIVATE SSH key onto this temporary machine or you will
                   NOT be able to log in.

            NOTE #2: Using modern computers might create SSH keys that are incompatible with very 
                     old versions of SSH servers.  The correct and secure solution for this problem
                     is to replace the old operating system for an OS that runs a more modern 
                     version of the SSH server

            To create an SSH keys with a passphrase:

               - Be logged into the Rpi with your normal non-Pi username

               - Run the command "ssh-keygen" to create a key

                  - When prompted, enter in a UNIQUE passphrase that locks the use of this SSH key.
                    This password can be cached so you won't be prompted everyt time you use SSH
                    to log into a remote system.  If you loose this passphrase, you will loose the
                    use of these SSH keys

                    - NOTE:  If you already created an SSH key but without a passphrase, overwriting
                             this file will make you LOOSE your old SSH key and it cannot be recovered
                             without restoring from a backup.  

                    - NOTE #2: If you already have an existing SSH key, you can ADD a passphrase to it.
                               This is easy and is covered in the "man ssh-keygen" output

                  - Once the SSH key is created, the program will tell you:

                    - Where your private key is stored (keep this save and NEVER copy it's contents to
                      remote systems

                    - Where your public key is stored (ends in a .pub filename).  This is the detail
                      you will put into remote servers you wish to log into

                    - Some key details about the key itself:
                         - Show it's fingerprint including what hashing technology was used (SHA256), 
                         - Show the 43 character identifier for this specific key (of possible multiple keys)
                         - the user cipher and bit strength such as RSA and 3072

            Next, let's understand some options for options for caching the SSH passphrase so you don't need 
            to type it in every time

               - OS Key manager vs per-shell caching

                    - Key Manager: Many modern operating systems like Debian / Ubuntu / MacOS / etc. are SSH 
                                   key aware.  What this means if you try to SSH to a remote system, you will 
                                   be shown a GUI popup to give your SSH passphase.  If correct, it will cache 
                                   this entry for you across any other windows that you try to SSH from.  Kinda 
                                   cool but you can disable this if you don't want it.

                    - Per Shell: The more classic way of using key caching is using the ssh-agent program which
                                 will cache you SSH keys ONLY for that specific shell instance running in a
                                 terminal window.  If you want to create another SSH connection from another
                                 window?  You'll need to run another instance of ssh-agent.

               - Per Shell Caching - run these commands:

                    # This will start the agent with passphrase caching support.  If you use some other 
                    # Unix shell than bash, enter that in here.  
                    #  NOTE: This command will seemingly do nothing and just return you to the shell prompt 
                    #        but if you run "ps", you'll see you now have TWO instances of bash running.
                    #        This is expected.
                    ssh-agent bash

                    # Enter in your SSH passphrase or passphrased for your various SSH keys

               - If everything worked, the ssh-add tool will tell you "Identity added" for your single or 
                 multiple SSH keys

            Now let's start putting this SSH key onto your remote systems you want to log into:

               - It's possible that your local OS has a tool installed to make this easy.  To see if it's 
                 there, run the command "whereis ssh-copy-id".  

               - If the "ssh-copy-id" tool is there, simply run this command with making the appropreate 
                 substitutions for the remote username and hostname:

                    #If you're using the configured alternative port
                    ssh-copy-id -p 2222 username@remote_host


                    ssh-copy-id username@remote_host

               - If that command worked, you should see:

                    Number of key(s) added: 1

            Ok, you should be set!  Try SSHing to that remote system again and if everything works, you
            should just be dropped to the shell prompt!  No passwords yet fully secure!

          - OPTIONAL / Best Security: If possible, it's recommended to DISABLE all password authentication on 
                                      your remote systems and ONLY use SSH keys.  If you've already tested that 
                                      you can SSH into a remote system using SSH keys *AND* everyone else who 
                                      uses that machine have also converted to SSH keys, do the following:

               - Edit the SSH server config file and make sure the following two lines are set:

                    sudo vi /etc/ssh/sshd_config
                    PasswordAuthentication no
                    ChallengeResponseAuthentication no

               - Run the following command to restart the SSHD service to make the changes go into effect:

                   sudo systemctl restart ssh

               - Final Testing: In another window, try one more time to SSH in from the SSH-key enabled client 
                                with the required SSH client key installed and make sure everything works 100%.  
                                If you cannot login, go back to the other terminal already open and either fix 
                                your issue or re-enable rasswords in sshd and restart the daemon it again 

   Future / To-do:  Advanced security thoughts that I'll add into this doc some day

         - enable Iptables port knocking support (potentially removes the need to change port numbers or
           mandate SSH-keys
         - Enable log monitoring tools like fail2ban to block remote IPs after X number of failed login 
           attempts, portscans, etc.

4.c Static IP Address for the Rpi

For those of you who wish to have your Raspberry Pi use a static IP address and not get it's address 
from DHCP, follow these instructions:

  NOTE:  The configuration of static IPs on Raspbian (now Raspberry Pi OS) has changed dramatically 
         over it's various releases from Wheezy, Jessie, Stretch, and now Buster.  For this section,
         I'm currently covering Buster ONLY.

   In Raspberry Pi OS (Buster and Stretch), the configuration of static IPs is actually configured 
   via the DHCPcd daemon (strange but true). 

      #scan down and find the eth0 interface area
      #  Remove the preceding # to un-comment out lines
      #  NOTE: The following example assumes you DISABLED "Predictable interface names" as recommended 
      #        in a previous section. Make sure the disabling of Predictable Interface names is actually 
      #        OFF by running the command "ip link" and you only see names like "eth0", "eth1", etc
      #  NOTE#2: If you want this to run on a different interface like eth1, make the correct name 
      #          change below
      sudo vi /etc/dhcpcd.conf
      interface eth0
      static ip_address=
      static routers=
      static domain_name_servers=

Once complete, reboot the Raspberry Pi with:

   sudo /sbin/shutdown -r now

Now try pinging the new static IP and if all goes well, it will start pinging and you can now
SSH, VNC, etc. into it.


5. Fixing some current Raspbian issues (Gotchas)

  a. Raspbian Jessie specific fixes ONLY (not for Buster or Stretch): 

     If you plan on using NFS on your Raspberry Pi (NOT recommended unless you know what you're 
     doing), it seems my Rpi v2 running Jessie as of 3/5/16 won't reboot if you use the 
     /sbin/shutdown or reboot or even "systemctl reboot" command.  Evidently this is a known issue 
     and is mentioned here:

     To work around this, edit the /etc/init.d/rpcbind and /etc/init.d/nfs-common
     file and change their start up/down priorities from:

        # Default-Start:     S
        # Default-Stop:      0 1 6


        # Default-Start:     1 2 3 4 5
        # Default-Stop:      0 6

     Once that's in place, you need to reboot but maybe you can't.  As such, I 
     recommend you do the following:

        a. run this little script as root (sudo su)

           while [ true ]; do
           sync; sleep 1

        b.  While that script is running, pull the USB power cord on the Rpi, 
            wait 5 seconds and replace the power

  b. Other gotchas and fixes will go HERE in the future if required

6. Configure temporary RAM file systems or OverlayFS to minimize SD card writes

As your Raspberry Pi runs normally, it will update various logs in the /var/log directory as
well as write other files as required (core dumps, etc).  This continuous writing can be dangerous
as the SD card can fill up to 100% full and over time, these writes will physically wear out the 
SD card itself.  The other issue is SD card has a higher risk of becoming corrupt if the power is 
removed from the Rpi when it's doing important file system writes.  To minimize these risks, you have 
a few options:

   1. RECOMMENEDED - RAM Drive:  
      Sending the log files to a RAM drive (non-persistent storage) removes much of this SD wear-out risk 
      but the downside is when/if your Raspberry Pi reboots, you will loose all those logs.  The setup of
      a RAM drive also consumes previous RAM on your Raspberry Pi so you need to be careful here but 
      setting this with a fixed amount of RAM won't consume all RAM.  This solution DOES still keep the
      root or / file system read-write so there is still a risk of file system corruption if the Rpi looses 
      power but I say this risk of NOT being recoverable is pretty low.


   2. OverLayFS: Newest versions of Raspberry Pi OS (Buster November 2019 or newer) have a built-in
      feature available via the raspi-config tool to make the /root and/or the /boot partition read-only.  
      This feature provides even more file system corruption protection than #1 above offers but if more 
      and more writes accumulate to the in-ram file system, this solution can consume all RAM and eventually 
      crash the Raspberry Pi.   

      This technology is similar to writing to on-disk snapshots found in Linux's LVM storage sub-system.  
      If you use this feature, you should monitor the Raspberry Pi and ensure it's running ok over time.  
      You can find this setting in the raspi-config tool under:

         Advanced Options --> Overlay FS 

      You can read more about this feature here:


   3. Read-only SD card:  This option is the safest option for long term running systems as the SD card 
      should never go corrupt.  The downside here is if you ever want to make permanent changes like apply 
      OS patchesS, make config changes, etc, you have to reboot the system to make the file system read/write, 
      make do your changes, and then reboot the system again to make it read-only.


   4. External storage:  You can boot and use an external USB attached pendrive, HDD, SSD for all storage 
      needs.  This will prove to be both faster and offer much longer life (SSD drives) but is more 

      a. you can boot off the Rpi's SD card yet mount the /var/log and /tmp directories to an external USB 
         device such as a USB HDD, SSD, or even a USB pendrive

      b. Use a MUCH larger SD card than you really need so that the RPi can better wear level the writes
         across the entire SD card (still not a great idea in my opinion)

   | NOTE:                                                                                      |
   |     Regardless of what choice you make, I highly recommend you follow the Logrotate        |
   |     section below to manage and compress all log files so the file system (RAM drive or    |
   |     not doesn't fill up.                                                                   |

I currently recommend you use the "Option #1 Ramdrive" approach above as I've had great luck with 
that setup.  That's with Rpis that have good power supplies and pretty (but not perfect) power.  
How do you do it?  Lets get started with that.  

   - Run the "df" command and make sure you see key file system entries like:

     Buster based OSes using "tmpfs":

     Stretch based OSes using "tmpfs":

Notice the use the "tmpfs" file system (or not) used for /run and /run/lock but not for say "/".  
These tmpfs entries are RAM drives which is good but in say Buster, there aren't any explicit
entries for /var/log/.  The LACK of any specific directory struction means this file system is 
using whatever supports the / or root file system.  For the Raspberry Pi, that means it's running 
on the SD card.  That's bad.  

Enabling the use of ramdrives has changed across the different versions of Raspbery Pi OS and 
Raspbian but I try to detail the different versions below:

  Bullseye / Buster / Stretch / Jessie OSes:  
   - The first line will create a 10MB ramdrive from your Rpi's total RAM space for storing log files. 
     Usually 10MB is plenty from a Raspberry Pi with 1GB of RAM.  If you have a new Rpi4 with 2GB, 4GB
     or even 8GB of RAM, you can choose to make this larger (say 50m) if you wish.  

     *** You will see in a later section where you might want to temporarily INCREASE this space if you
         wish to do some light compiling but you do not want to mount an external storage device like
         a USB pendrive, SDD, or HDD drive

   - The second line will create a 50MB ramdrive for /tmp from your Rpi's total RAM space (usually 1GB 
     of RAM shared with the OS.  

   - If you wish to store more in your Rpi ram drives, you can increase these sizes but remember that 
     you're effectively stealing RAM away memory from the Linux kernel for use in various caches

   - ADD the following two lines to the BOTTOM of the file:

     #These numbers are for an Rpi with 1GB of RAM - lower these numbers by a factor of 2 for smaller pis
     sudo vi /etc/fstab
     tmpfs           /tmp            tmpfs   defaults,noatime,mode=1777,size=20m   0   0
     tmpfs           /var/log        tmpfs   defaults,noatime,mode=0755,size=50m  0   0

    NOTE:  In Raspbian Jessie and Stretch OS versions:
           The previous Wheezy approach of configuring RAM drives (/etc/default/tmpfs) is broken.  As such 
           and they have PERMANENTLY moved back to the classic fstab approach 
     You can learn more specifics of operation in "man tmpfs"

Ok, you're done with this step, DON'T reboot your Rpi just yet to activate these changes. 
We have few more things to do first!

6.a. Next, Noatime File system optimization

Confirm or enable the "noatime" attribute to disable the recording the date and time whenever any and all files are ever 
looked at across on the file system.  Turning this feature off will help minimize file system writes on your 
root file system that's on the SD card.  

  #NOTE:  This might already be enabled for Raspbian Buster users but please double check 
          that it's present regardless

  sudo vi /etc/fstab

     # For the Buster and Stretch based OSes, the fstab system uses UUIDs instead of partitions, etc.  
     # Your UUIDs will be *different* for your storage but regardless, find your specific line for the "/" 
     # root filesystem and make sure the "noatime" attribute is added
     PARTUUID=92f034a6-02  /               ext4    defaults,noatime  0       1

     # for Jessie, it should look something like:
     /dev/mmcblk0p2  /               ext4    defaults,noatime  0       1

Ok.. NOW you can go ahead and reboot your Rpi right now using the command:

      sudo /sbin/shutdown -r now

When it comes back up, log in and run "df".  Make sure those various mount points now are 
mounted to a "tmpfs" file system like:

   Filesystem     1K-blocks    Used Available Use% Mounted on
   /dev/root       14660888 1051092  12981572   8% /
   devtmpfs          241580       0    241580   0% /dev
   tmpfs             245908       0    245908   0% /dev/shm
   tmpfs             245908    3436    242472   2% /run
   tmpfs               5120       4      5116   1% /run/lock
   tmpfs             245908       0    245908   0% /sys/fs/cgroup
   tmpfs              51200     144     51056   1% /var/log    <------------------
   tmpfs              10240       0     10240   0% /tmp    <------------------
   /dev/mmcblk0p1    258096   39969    218127  16% /boot
   tmpfs              49180       0     49180   0% /run/user/1001

7. Enable/Disable IPv6 upon booting

In a previous chapter, I recommended to lock down the IPv6 firewall when loaded upon boot.  
Unless you plan on using IPv6 on your network, you might has well explicitly DISABLE the IPv6 protocol 
COMPLETELY.  To confirm IPv6 is currently running, run the following command:

  ip address

Under the second interface, you'll see a line prefixed with "inet6" and starting with the 
address "fe80".  That's the host's IPv6 link local address which is a local-only address.  
The output of your host might include other lines showing IPv6 site-local (a real address), 
IPv6 privacy address (also real addresses), etc.

  1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
      link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
      inet scope host lo
         valid_lft forever preferred_lft forever
      inet6 ::1/128 scope host
         valid_lft forever preferred_lft forever
  2: eth0:  mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
      link/ether b8:27:eb:d0:0d:fc brd ff:ff:ff:ff:ff:ff
      inet brd scope global enxb827eb2532fc
         valid_lft forever preferred_lft forever
      inet6 fe80::c8c1:a034:5b63:a614/64 scope link  <----------------------------
         valid_lft forever preferred_lft forever

If you wish to outright DISABLE IPv6, edit the /etc/sysctl.conf file and change or ADD the 
following lines to the bottom of the file:

   sudo vi /etc/sysctl.conf
   net.ipv6.conf.all.disable_ipv6 = 1
   net.ipv6.conf.default.disable_ipv6 = 1
   net.ipv6.conf.eth0.disable_ipv6 = 1
   net.ipv6.conf.lo.disable_ipv6 = 1

If you which to enable / disable IPv6 on specific devices connected to your Rpi, you will need to add additional
lines for say "eth1", "eth2", etc.

If you did disabled IPv6 per the above steps, you need to reboot your Rpi for the changes to take effect.  
Once it's back up, log back into it and run the "ip addr" command to confirm there aren't any "inet6" addresses 
showing up (even the "fe80" link-local addresses).

[Chapter Gap]

9. OPTIONAL: Enable power management for attached USB HDDs

Doing program compiles on the Raspberry Pi's local SD card can significantly wear out the flash card and make 
it fail prematurely.  If you have another Linux machine on your network, you can use NFS to do remote 
mounts to support these heavy writes.  Unfortunately, remotely mounted NFS shares doesn't always work 
for doing compiling some reason.  One example of this is the "autoconf" stage of configuring the Makefiles 
can fail to complete.  

The only other option here is to compile things on a DIFFERENT locally mounted file system.  A far 
better solution here is to use an external USB connected pendrive, HDD (better)or SSD (best).  It's 
worth mentioning that the Raspberry Pi v4 or 400's USB3 ports offer much better file system performance 
compared to the microSD card, the eMMC storage on say a CM4, or even over NFS (over the network).

The challenge with using spinning disk hard drives is that the Raspberry Pi defaults to leaving the 
drive spinning all the time and it will never spin down if it's not in use.  That can wear out your 
hard drive prematurely and it consumes excess power too.  To make sure the HD's auto-spin down 
feature is enabled, do the following:

   NOTE: One challenge here is that some hard drives behave different and not work with these settings.
         Most drives are standardized these days but if you're unlucky, you'll need to try out these 
         various commands and see if they need to be modified for your specific device

   a.  Powering your external hard drive

       | IMPORTANT:                                                                                      |
       | ----------                                                                                      |
       | Some USB hard drives are purely powered via the USB bus but the Raspberry Pi CANNOT supply very |
       | much power via USB.  If your USB hard drive is like this, you MUST first connect the drive via  |
       | a *powered* USB hub (one that has a power brick connected to the wall).                         |
       |                                                                                                 |
       | If your external hard drive has it's own power brick, you can connect the hard drive directly   |
       | to the Raspberry Pi.                                                                            |

   b.  Connect your USB hard drive to the Pi

       After connecting the hard drive, make sure you can figure out it's device name via the "dmesg"
       command.  I see the following and my desired drive and partition is "/dev/sda1":
       [  360.177269] scsi 0:0:0:0: Direct-Access     IC35L080 AVVA07-0              PQ: 0 ANSI: 0
       [  360.186259] sd 0:0:0:0: [sda] 160836480 512-byte logical blocks: (82.3 GB/76.7 GiB)
       [  360.187426] sd 0:0:0:0: [sda] Write Protect is off
       [  360.187448] sd 0:0:0:0: [sda] Mode Sense: 33 00 00 00
       [  360.188544] sd 0:0:0:0: [sda] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
       [  360.207824] sd 0:0:0:0: Attached scsi generic sg0 type 0
       [  360.209560]  sda: sda1
       [  360.214723] sd 0:0:0:0: [sda] Attached SCSI disk 

   c.  Install the hdparm utility:

          sudo apt install hdparm

   d.  Confirm that your HD APM level is set to 127 (not 128 or higher : default is 254)
       Any values of 127 or lower will allow the HD to power down if idle

          sudo /sbin/hdparm -B /dev/sda
           APM_level      = 254

       That's a good output and it means the drive is running and has all power management

       NOTE:  If you get output like the following from the above test command:
               APM_level      = not supported

              This most likely means the drive you're trying to use is very old

       NOTE#2:  If you get output like the following from that above test command:
              SG_IO: bad/missing sense data, sb[]:  70 00 05 00 00 00 00 0a 00 00 00 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
               APM_level      = not supported

              This means the USB to SATA/PATA bridge chip in your USB to HDD adapter 
              is not passing all the IDE commands codes through.  There is most likely
              nothing you can do about this except use a different USB to HD adapter 
              or enclosure.  If it's a brand new bridge chip, maybe Linux needs more 
              time to add support for it but once that support is added, you most
              likely will have to upgrade your Linux distribution (with kernel) to 
              get the new support.

              One user also noted that the Western Digital WD Blue and WD Green series 
              of drives do NOT support APM_level which is evidently a known issue.  
              There is a 3rd party tool out there named "hd-idle" that might help you 
              work around this

   e.  Ok, let's do some more commands.  For example, let's see if the HD is spinning now:

       sudo /sbin/hdparm -C /dev/sda
        drive state is:  active/idle

   f.  For a temporary power test, run the following command to change the APM power

          sudo /sbin/hdparm -B 127 /dev/sda

       You can learn more about HD APM levels at:


   g. To permanently allow this drive to spin down when idle, change:

         vim /etc/hdparm.conf
         #apm = 255
         apm = 127

   h. Btw, you can force the HD to spin down ASAP by running the command:
         sudo /sbin/hdparm -y /dev/sda
         issuing standby command

      You can then use the "sudo /sbin/hdparm -C /dev/sda" command to see that the drive 
      is spun down by confirming it's in "standby".

   i. You can also force another timer in /etc/hdparm.conf to spindown the drive in 
      say 10 minutes
      spindown_time = 120

Ok, we'll use this hard drive later for compiling stuff.  For now, go ahead and let the HDD
spin down.  In the bottom of "Section 17 - Enable local storage for demanding builds", it 
includes scripts to both mount and unmount the drive for compiling needs as well as spin 
down the drive.

10. Hardening: Check and disabled unneeded services (the SystemD way)

OPTIONAL:  This section covers the shutdwown of various services which I consider useless, 
           bloat, security issues, etc.  These aren't required to be disabled but I encourage
           you to research and make up your own mind!

   NOTE: a helpful SystemD cheatsheet for those who are interested

   #I recommend to REMOVE Avahi (Bonjour) for it's network spamming (if you didn't already remove it's
   # package as recommended in a previous section.  You can see what Avahi spams your network about
   # by running the command:
   #    avahi-browse -lart | grep -A1 -e "^="
   # I recommend to just disable it from running:
   sudo systemctl disable avahi-daemon.service
   sudo systemctl disable avahi-daemon.socket
   sudo systemctl stop avahi-daemon.service
   sudo systemctl stop avahi-daemon.socket

      #OPTIONAL recommended removals to make the machine more secure / reliable): 
      #   Disable the Avahi mDNS system on the Rpi
      sudo update-rc.d -f avahi-daemon disable

   # Disable printing support (if installed) and running all the CUPS baggage 
   # (usually found on the GUI versions # of Raspberry Pi OS - not the LITE versions)
   sudo systemctl disable cups-browsed.service 
   sudo systemctl disable cups.service

   #OPTIONAL: disable bluetooth if you don't plan on using it
   #   Disable Bluetooth on the Rpi
   sudo update-rc.d -f bluetooth remove
   sudo systemctl disable bluetooth.service

   # Disable the special key keyboard mapping / hotkey tool used for IR remote controls, etc
   sudo update-rc.d -f triggerhappy remove
   sudo systemctl disable triggerhappy.socket
   sudo systemctl disable triggerhappy.service

   #Disable the Rsync daemon (might NOT be installed)- usually doesn't autostart without editing the /etc/default/rsync 
   # file anyway
   sudo update-rc.d -f rsync disable

   #IMPORTANT... please run and review
   #show other running daemons and see if any might need to be disabled
   #   do NOT disable anything unless you know exactly what you're doing
   systemctl | grep running

   #See what else might be configure to start at bootup (still applies to Raspbian Buster, etc)
   ls /etc/rc3.d/

   Once you've disabled everything required, reboot your Rpi and confirm everything is disabled.  I also
   encourage you to run the following command and make sure there aren't any unexpected network ports
   still listening:

      netstat -an

   On my systems, I only leave enabled:

      - port 2222 for SSH
          or port 22 (this is the default port)

      - port 5900 for VNC (for any GUI enabled hosts)

      - port 68 for DHCP

11. OPTIONAL: Syslog Tuning

  a. (OPTIONAL) On Raspbian Jessie based systems as of 12/11/15, I would see /var/log/syslog errors 
     that show up like:

         rsyslogd-2007: action 'action 17' suspended, next retry is Fri Dec 11 15:18:31 2015 [try

     This is evidently due to the Xwindows xconsole not running (when you Rpi isn't running Xwindows 
     because you're probably running Raspbian Lite).  To fix this, edit the /etc/rsyslog.conf file, 
     find and delete the following stanza:
        *.=notice;*.=warn       |/dev/xconsole
     If you still want to receive console errors, read the section BEFORE this xconsole  
     section and enable that which will send errors to console vty 8 instead

  b. I would also recommend to delete the following stanza as it's redundant, 
     and only creates additional log items in both the /var/log/messages and /var/log/debug files:

     sudo vi /etc/rsyslog.conf
        news.none;mail.none     -/var/log/debug

  c. You'll find that Raspbian logs too much stuff to too many places.  I 
     recommend you follow this URL as step one: 

     It's a little terse on what really needs to be done.

        sudo vi /etc/rsyslog.conf

        1.  Find the line:

               *.*;auth,authpriv.none        -/var/log/syslog

            and change it to the following (adds the ",mail")

               *.*;auth,authpriv,mail.none        -/var/log/syslog

        2. delete the lines:

            mail.warn                     -/var/log/mail.warn

        3. change the line

            mail.err                      /var/log/mail.err


            mail.warn                     /var/log/mail.err

        4. Find the line:

             kern.*                        -/var/log/kern.log

           and right after it, add:

             kern.debug                    stop

     Once edited, restart syslog with:

         sudo service rsyslog restart

     And then delete the old, abandoned logs (or reboot as 
     all these logs are on the temporary RAM drive now):

         rm -f /var/log/debug*

11.a. Add ULOG to remove IPTABLES lines from /var/log/messages

If you enabled the IPTABLES firewall setup in the previous section and put your Raspberry
Pi on the direct Internet, you probably noticed it begins log too much stuff into too many 
log places.  Worse, if you have your hardened Raspberry Pi connected to the raw Internet 
and look at the contents of /var/log/messages or dmesg, you'll probably notice an absolute 
ton of attack traffic!  Scary stuff but if you followed the various recommendations of this 
doc, your system is now pretty safe.  

To clean up all these IPTABLES lines from filling up your name /var/log/messages and 
dmesg log files, you can enable the Ulog system to move these lines them to a dedicated 
log file(s).

Why do you have to do something special like this?  Good question but the crux of the issue 
is that the IPTABLES system in Linux logs everything to the "kernel" syslog facility which 
has a a LOT of ramifications.  It's unfortunately NOT possible to make it to use any of the 
Syslog LOCAL[0-7] facilities.  To work around this, one has to make a bunch of minor 
changes to redirect logs but it's not too difficult to do.  

I recommend you set this Ulog system up *AS IS* (aka no changes) since using other facility 
levels have other ramifications like sending messages to the console, dmesg, etc.  It's 
a pain to change and something I've never liked about IPTABLES when the old stateless IPCHAINS 
running on 2.6 and 2.4 kernels never did logging stuff like this.  Oh well.. that was then.. 
this is now so lets get this work around in place:

  1. Make sure your kernel has the netlink kernel modules which is required

     #Should find one kernel file 
     find /lib/modules/`uname -r`/kernel/net/netfilter/ | grep -e ip_conntrack_netlink.ko -e nf_conntrack_netlink

     #You should find three or more library files
     sudo find / | grep -e -e -e

        #If some of the above packages are missing, you can explicitly install them with:
        sudo apt install libnetfilter-log1 libnfnetlink0 libnetfilter-conntrack3

  2. Install ulogd2

      sudo apt install ulogd2

  3. Confirm the newly installed ulogd daemon has already been started

        ps ax | grep ulogd

  4. Now configure Ulog2 by editing it's config file

     Find the following lines in the configuration file and make them look like the following:

     sudo vi /etc/ulogd.conf
     #Buster defaults to loglevel=3 which should be ok but if you want more detail





  5. Restart Ulogd to get the new settings

      sudo service ulogd restart

  6. Alter your iptables firewall to use the new Ulogd system

       6.a Edit the /etc/iptables/rules.v4 file and find the line:

          sudo vi /etc/iptables/rules.v4
          -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

          Replace it with:
          -A INPUT -m limit --limit 5/min -j NFLOG --nflog-group 0 --nflog-prefix "iptables denied: "

       6.b Edit the /etc/iptables/rules.v6 file and find the line:

          sudo vi /etc/iptables/rules.v6
          -A INPUT -m limit --limit 5/min -j LOG --log-prefix "ip6tables drop: " --log-level 7

          Replace it with:
          -A INPUT -m limit --limit 5/min -j NFLOG --nflog-group 0 --nflog-prefix "ip6tables denied: "

  7. Reload the firewall set following the previous recommendations in the Firewall section of this
     doc assuming your using my firewall reload script:

        sudo /usr/local/sbin/ &

     Assuming that went well, now things should be all logged in the /var/log/ulogd_traffic-emu1.log file and 
     no longer in your /var/log/syslog nor dmesg logs!

  If you're curious, you can learn more about Ulogd2 here:

In a few sections, I will add recommended log rotation and compression of the /var/log/ulogd_traffic-emu1.log
so it won't fill up the RAM drive.

12. Install the Postfix email server and Logwatch to get nightly system reports

To get daily reports of how your Raspberry Pi SBC is running, let's install a local-only 
email server and some log notification tools.  To do this, run the following command:
   #Some additional required packages will be installed as well
   sudo apt install postfix logwatch bsd-mailx dnsutils 

As the Postfix package installs, it will bring up a TUI interface and prompt you for 
specific settings for your email environment.  The first prompt given to you is to
understand your hostname and DNS domain name.   In this example, I entered in the 
following but you will need to enter in your Rpi's system's hostname and domain name:

Next, you will be prompted to understand how your system can send SMTP email.  The 
answer here really depends on your ISP and if they BLOCK SMTP email.  The most common
options will be "Internet" or "Internet with Smarthost":

   * "Internet" means you can *directly* send and optionally receive email without
     issue.  Most modern ISPs do NOT allow this to migate systems sending spam

   * "Internet with Smarthost" means your system can only send email via relaying
     the SMTP messge to some other mailhost first.  This is the mechanism most ISPs 
     require to mitigate systems from sending spam.  This is also commonly used 
     for many home-hosted email systems

If you select "Internet with Smarthost", you don't enter in the actual IP of the remote 
host doing the relay but the DNS record that will accept email from your Rpi's domain name.  
In my case, I would enter in the the DNS "MX" record (not a DNS "A" or "CNAME" record)
configured to accept email for my "" domain.  If you're not sure what your
record should be, contact your ISP for the correct "smarthost" or "MX" relay you should
be using.

The next step is to configure postfix to ONLY offer email services locally.  To do
so, you need to frst edit the postfix configuration file:

   sudo vi /etc/postfix/

      - Find the line that looks like
        inet_interfaces = all

        Comment out that line and add the following line:
        #inet_interfaces = all
        inet_interfaces =

   Next, we need to make sure the host leverages the /etc/hosts file in addition
   to DNS to support setups that don't run their own DNS servers.  Do the following:

      sudo vi /etc/host.conf
      multi on
      order hosts,bind

Next, you need to edit the /etc/aliases file to point all "root" user emails to go to a 
valid email address (off box).  This will be the desired valid email address where you'll 
# receive daily email reports from your Raspberry Pi.  For me, this is what I setup:

   sudo vi /etc/aliases
   root:			<change all this to reflect your full email address>

Once you edited the aliases file, run the command to activate the change:

    sudo newaliases

  This command will silently compile this new alias information into the /etc/aliases.db 
  database.  If it runs ok, it won't return any details but if there are errors, it will 
  say so.

Once the above steps are completed, you need to restart postfix with:

     sudo systemctl restart postfix

On the upstream MX / SMTP relayhost configured above, it's required that it will accept
emails from your new Raspberry Pi.  For most ISP's MTAs (remote email servers that accept email), 
this won't be needed but if *you* sysadmin your own upstream "smarthost" or SMTP relay, you might
to need to update the "access" database (not the aliases) database.  If you do have to make changes 
to this "access" database, make sure to run the "newaccess" command to create a new version of the 
database and restart your email server.

Once you've update the access database, now test the Rpi's local email system by running:

   echo "test email from `uname -n`" | mailx -s "test email from `uname -n`" root

There won't be any output from the command line but you can see if there were any other issues
by looking at logs on your mail server (if you have access to your email server):

   sudo less /var/log/mail.log

You need to see a line saying something like "... dsn=2.0.0, status=sent (delivered to mailbox)"

Also check and see if this email was ultimately received on your chosen destination email address.  
If the email wasn't received, you need to check the local and remote email logs.  Do NOT proceed 
past this step until this is resolved if you want to get nightly notifications.

12.a. Add an email notification when your Rpi is rebooted

If the test email notification was received, now configure system send you an email whenever 
the Rpi is rebooted.  This is VERY helpful as it can help you diagnose non-desired system 
crashes, power issues, etc.  To do this, edit the /etc/rc.local file and add this command 
before the end of the file (before the "exit 0" line):

   NOTE:  The whole concept of /etc/rc.local is being deprecated for distros using 
          systemd.  There are workarounds to create a systemd target that acts like
          a classic /etc/rc.local script:

   sudo vi /etc/rc.local
   #Send a message to root when the Rpi reboots
   echo -e "`date`\nhost: `uname -n` was rebooted" | mailx -s "host: `uname -n` was rebooted"

If now is a good time to reboot, let's try it.  Reboot your system with:

   sudo /sbin/shutdown -r now

and once the Rpi comes back up, the email address you aliased to recive root
messages from should have a message about the reboot.

13. Install the Logrotate log management system for log rotation and compression

Now that you have an email server running and are hopefully running an IPTABLES firewall 
with logging support going through Ulogd, etc, you need to manage your logs.  If you don't 
install this rotation system (usually installed by default), the RAM drive can get full 
and you'll loose important diagnostic logs, etc.  It's also important that if you create 
new log entries for say the IPTABLES Ulog system, these new files get managed.

To solve this, install the logrotate suite (if it isn't already):

   sudo apt install logrotate

Next, edit the /etc/logrotate.conf file to enable bzip compression 

   sudo vi /etc/logrotate.conf
      - Un# out the line "#compress"

      - Add the following lines just below the "compress" line
        # use bzip2 with higher compression than gzip
        compresscmd /bin/bzip2
        uncompresscmd /bin/bunzip2
        compressoptions -9
        compressext .bz2

Now edit the /etc/logrotate.d/rsyslog file and add the following items at the TOP of 
the file (don't put these lines UNDER ANY SPECIFIC file stanza and delete any duplicate 
lines from any of the other stanzas in the file.  

   NOTE: If the "delaycompress" parameter is present anywhere in the file, comment the 
         line out by adding a "#" in front of it

   sudo vi /etc/logrotate.d/rsyslog
	rotate 3
	compresscmd /bin/bzip2
	uncompresscmd /bin/bunzip2
	compressoptions -9
	compressext .bz2

Now, if you followed the instructions on the Ulogd section for IPTABLES logging in a previous
section, I highly recommend to rotate those logs as well.  Edit the /etc/logrotate.d/ulogd2 file
and add the following stanza:

    sudo vi /etc/logrotate.d/ulogd2
            rotate 4
            size 10M
	    compresscmd /bin/bzip2
	    uncompresscmd /bin/bunzip2
	    compressoptions -9
	    compressext .bz2
            create 640 ulog adm
                invoke-rc.d ulogd2 reload > /dev/null

Once you've made these changes, no other command are required.  The logrotate system 
is run by the cron system and it will automatically rotate the logs on it's regular 

14. OPTIONAL: Install important sysadmin and monitoring packages?

Though completely optional, I would recommend to install some of these useful programs:

   vim     - better version of Vi
   tcpdump - network monitor
   lsof    - tool to see what ports / files are open on the machine
   gpm     - mouse program for cutting/pasting when in CLI mode
   telnet  - make simple outgoing TCP connections for various network tests
   minicom - a very useful serial terminal program to troubleshoot serial ports, TNCs, etc
   links   - a text-based web browser

   #Install them and their required dependencies
   sudo apt install vim tcpdump lsof gpm telnet minicom links

      # If you install Vim, start using the "vim" command instead of the basic "vi" command yet
      # see screwy copy/paste issues via the mouse, MANUALLY type in the following to allow
      # future copy/paste support:
      #Update your vim preferences
      vim $HOME/.vimrc (change the "dranch" username to be your username)
      set mouse=r
      set paste

      #and do it again for when running things via sudo:
      sudo vim /root/.vimrc

      Next, I would also recommend to ONLY run Gpm it when you're on the actual console (HDMI) 
      and only when it's needed.  As such, I recommend to disable gpm from starting at boot 
      sudo update-rc.d gpm remove

# Personal Preference: Enable Vim as system default text editor and not Nano

   sudo update-alternatives --set editor /usr/bin/vim.basic

Next, if the /boot partition on your SD card ever gets corrupt, you can fix it if you install these
tools ahead of time (if not already installed in your version of Raspberry Pi OS):  

  Please note that the Raspbian Wheezy version of dosfstools is broken

  sudo apt install dosfstools

Moving on, it would be good to confirm that your Raspberry Pi is stable and reliable with it's power supply,
etc.  The "stress" tool is a nice tool to create high loads to check to see if:

    - The RED power LED on the Rpi's board blinks indicating a power issue
    - You see a yellow lightening bolt in the upper right corner of the Rpi's HDMI console indicating a power issue
    - See if your Raspberry Pi crashes (could indicate either a power issue or something on the Rpi itself.. aka.. it's defective)

To try this test, do the following:

   1.  Install a basic load test program
        sudo apt install stress

   2.  Reboot your suspect Raspberry Pi and confirm the "Throttled" output shows "0x0".  Anything other
       than "0x0" means that your Rpi is being slowed down either by low voltage, over-temp, etc

        /usr/bin/vcgencmd get_throttled

   3. Run the stress program for 2 minutes to load up your Rpi.  You can watch the RED led on your
      Raspberry Pi during this time to see if it blinks (that's bad):

        | NOTE:                                                                             |
        |                                                                                   |
        |    If you have already enabled watchdog support on your Rpi with high CPU load    |
        |    tracking, these commands might reboot your rpi.  To work around this, consider |
        |    disabling the watchdog service before running these commands.                  |

        #For 4core Rpis like Rpi2, 3, 3+, 4
        stress --cpu 20 --io 20 --vm 6 --vm-bytes 25M --timeout 120s
        #For 1core Rpis like Rpi0, 0w, 1
        stress --cpu 5 --io 20 --vm 6 --vm-bytes 25M --timeout 120s

      The output from the stress tool would look something like:
      stress: info: [1680] dispatching hogs: 20 cpu, 20 io, 6 vm, 0 hdd
      [...120 seconds later...]

      stress: info: [1680] successful run completed in 120

   4. After the stress program is complete, confirm the load was high (for example, this stress command created a load of 
      36.62 on a Raspberry Pi 4 w/ 4GB RAM): 

     If your Raspberry Pi crashes, you'll know for SURE that you have a problem that's load related.  You will need to 
     look at getting a better power supply, a better / shorter USB cable between the power supply and Raspberry Pi, etc

   5. Re-confirm if an undervolt situation occurred by confirming if you do or DON'T see a "0x0" output:
        /usr/bin/vcgencmd get_throttled

There are other great testing / performance tools to consider installing:

      hdparm         - storage configuration and basic I/O benchmark tool
      sysbench       - comprehensive benchmark tool
      speedtest-cli  - Internet and network benchmark tool
      rpi-benchmark  - comprehensive suite of benchmark tools tailored to Raspberry Pis

OPTIONAL: One of the more comprehensive benchmarks is the rpi-benchmark tool.  You can read more about it in the
          URL.  It does drag in a LOT of other packages to do a complete run (databases, etc) so you might think
          twice if you have a small SD card or don't want to add a lot of bloat to your OS.
   cd /tmp
   chmod 755
   sudo mv /usr/local/sbin/
   sudo /usr/local/sbin/

15. Pyshutdown: Building a shutdown button for an Rpi much like a PC's ATX power button

One of the more significant issues with the entire line of Raspberry Pi boards is that there is 
NO WAY to safely shutdown the OS w/o logging into the device via the console or SSH, etc first.  
Many alternative SBCs that compete with the RPi line include a little shutdown button on the board 
itself but the Rpi line doesn't.  I view this is as a *very* bad design as almost any OS can and 
WILL get partially corrupt it's filesystem when ungracefully shut down.  Yes, there are some complex
tricks to make the OS run as read-only from the file system (SD cards, eMMC, etc) but that is beyond
the scope of this doc.  Fortunately, it's not too hard to add a shutdown button to the Rpi and I
highly recommend you add one.

The first thing to to figure is out what GPIO pin to use.  This selection completely depends 
on the generation of Rpi you're using.  Looking at the 
22. Choosing GPIO pin for the radio PTT line section,
pick a GPIO pin for your setup.  I'm using the following pins for various purposes in this doc:

    Direwolf to Radio PTT on Rpi:
      Rpi pin 37 (Broadcom GPIO 26) :: connect this to RS232 DB9 pin7 (this is the RS232 RTS signal)
      Rpi pin 39 (Broadcom for GND) :: connect this to RS232 DB9 pin5 (this is the RS232 GND signal)

    Direwolf DCD indicator on Rpi:
      Rpi pin 33 (Broadcom GPIO 13) :: connect to anode of LED (long lead / larger metal inside LED)
      Rpi pin 34 GND                :: connect to 470 Ohm resistor and connect the other side of the
                                       resistor to the cathode of LED (short lead / smaller metal inside LED)
      Rpi pin 18 (Broadcom GPIO 24) :: connect to 10k resistor, connect the other side of the resistor to 
                                       one side of a momentary switch
      Rpi pin 20 - GND              :: Connect to other side of momentary switch

Historical note:  I used to use the solution at 
as an outline for this section and code BUT there were several issues with it and other designs found on
the Internet:

   - This specific design does not use a resistor to current protect the GPIO line.  This is a
     bad idea and can physically damage your Rpi due to sinking too much current though the monitoring 
     GPIO pin.  I recommend to use a 10k Ohm resistor in-line to the shutdown momentary switch to protect 
     the GPIO pin from over-current

   - The above script doesn't support a debouncing capability and I was experiencing false shutdowns
     (the Raspberry Pi was thinking the button was being pushed when it WASN"T - I believe this was due to
     RF interference (RFI) issues.  A better solution is using the below solution from the following tool 
     with some modifications:

   - My version of the script requires you to HOLD DOWN the button for THREE seconds and then the Rpi will 
     gracefully shut down.  This is both much safer against accidental button pushes and with this 
     software-debouncing, it's much more reliable too.

   - This modified script includes improved system messaging to any logged in users

Next, let's connect the shutdown button to the RPi's GPIO header.  It's important to first SHUTDOWN (not 
reboot) your Rpi with:

   sudo /sbin/shutdown -h now

Let the Rpi shut off (the activity LED will blink 10 times to indicate that the OS is down).  Now disconnect 
the USB power cable to the Rpi to remove all power to the Pi.  Now, wire up the following simple circuit 
(this example uses Broadcom GPIO 24):

   1. Rpi pin 18 (Broadcom GPIO 24) connected to a 10K Ohm resistor 
      (resistor color code: brown, black, orange, gold)

   2. Then other side of the resistor to a momentary switch/button

   3. Then other side of the momentary switch to GND such as Rpi pin 18 

   4. Make sure you built this reset button properly.  Use a good momentary switch, use good slim connectors 
      to make solid contact to the GPIO pins. Use electrical tape or better yet, heat-shrink tubing around 
      those pin connectors to avoid any short circuits to the other nearby GPIO pins, etc.

Once the button is wired up and connected to the correct GPIO pins on the Raspberry
Pi, go ahead and connect the USB power back to the Raspberry Pi to boot it up.

   NOTE: Just as a heads up for the curious, I connected a volt meter to physical 
         pins 16 and 18 upon initial power up.  At first, I saw 0 volts but as the 
         Rpi finished it's booting, I saw the voltage jump to +3.3v as expected.

Next up, lets first test that your button is connected and reading correctly

   a. Make sure you have the raspi-gpio utility installed

      sudo apt install raspi-gpio

   b. Download the following test script:

      cd /tmp
      sudo mv /usr/local/bin/

   c. Make the script executable:

      sudo chmod 755 /usr/local/bin/

   d. Now make the shutdown GPIO pin as an INPUT

         echo 24 > /sys/class/gpio/export
         echo "input" > /sys/class/gpio/gpio24/direction
         #Turn on the internal pull-up resistor
         raspi-gpio set 24 pu

   d. Now run the script which will run in 1 second loops.  Now push down and continue to hold down
      your button for at least one second and then release the button.  The script will show you which GPIO 
      pin changed by looking at the "level" column.  An example looks like this which is changing
      Broadcom GPIO 24 aka physical GPIO pin 18 when I press the button:

      /usr/local/bin/ diff
      < GPIO 24: level=1 fsel=0 func=INPUT
      > GPIO 24: level=0 fsel=0 func=INPUT
       GPIO 24: level=0 fsel=0 func=INPUT
      > GPIO 24: level=1 fsel=0 func=INPUT

      Once you've confirmed your button push and release is being seen, hit control-c to exit the script

Ok, now to get the shutdown script going, do the following:

   a. Get the actual shutdown script on to the Rpi

      cd /tmp
      sudo mv /tmp/ /usr/local/sbin/
      sudo chmod 700 /usr/local/sbin/

   c. Edit the /usr/local/sbin/ file and find the lines:

      sudo vi /usr/local/sbin/
      #Find the line and change the GPIO pin to use what you chose from the above details
      # This is the Broadcom GPIO pin and NOT the physical Raspberry Pi pin.  See 
      INT = 24

Next, edit the /etc/rc.local file as root to start this shutdown script on every boot:

  sudo vi /etc/rc.local
  find the line that says "exit 0" and just above it, add the lines:
  echo "Starting script"
  echo "Starting script" | /usr/bin/systemd-cat
  python /usr/local/sbin/ &
  if [ $? -ne 0 ]; then
     echo " script failed to start"
     echo " script failed to start" | /usr/bin/systemd-cat

Now, let's test that the script can run.  To do so, run:

  sudo python /usr/local/sbin/

If things work properly, the script will just sit there, seemingly doing
nothing.  Ok, for the big test:  PRESS AND CONTINUE TO HOLD DOWN the shutdown button for 
say 5 seconds and then let go.  Depending on the Raspberry Pi model you're using,
the green "activity" LED might start flickering showing storage activity as the Pi
is shutting down.  

   - On say the Raspberry Pi 0-W version, the green LED stays on for 8 seconds, then 
     starts to flicker.  

Eventually, all Raspberry Pi boards should blink the green LED 10 times meaning the OS 
has been gracefully shut down.  That means the script it works!  

Ok.  since your Rpi has been HALTed, go and unplug the USB power connecting to your Rpi 
and then re-connect it after say 5 seconds to boot the Rpi back up.  Once the Rpi is fully 
booted, let's test the shutdown button setup a real world test.  

   - Give the shutdown button a momentary push but DON'T hold it down.  The Raspberry Pi 
     should simply stay running as you didn't hold down the button long enough.  

   - Now for the real test, PRESS AND HOLD DOWN the button for at least three seconds and 
     the Rpi should begin to gracefully shutdown the OS as mentioned above.  The Raspberry Pi 
     should eventually blink it's GREEN activity LED 10 times and after that, the OS is 
     shutdown.  At that point, only the RED led will stay lit for Rpi models that have that
     LED.  If you had a volt meter connected to the Rpi pins, you would now measure the voltage 
     at 1.03volts.  To boot your Rpi back up, remove the power connection to the Rpi, count 
     five seconds, and then re-connect the Rpi's USB power cable.

Alternative shutdown solutions if you don't like this recommended solution (I would be 
curious why):

15.a. Broadcom HW Watchdog: Automatic reboots if the system becomes unresponsive

If your Raspberry Pi unit happens to lock up, crashes, or otherwise becomes non-responsive, 
a hardware watchdog has the ability to automatically "reset" the hardware for you.  The goal 
here is to have the Raspberry Pi brought back online instead of you having to manually reboot
it with a cycle the power.  

   NOTE:  Whenever the watchdog kicks in, you still run the chance of the the SD card's file 
          system getting corrupt.  This risk is no different than having to do a manual 
          power cycle

   | IMPORTANT : 08/29/17 on Raspbian Stretch  (does not apply to Raspbian Buster)                    |
   |                                                                                                  |
   |            Per the thread at;amp;t=147501  |
   |            it seems that there is confusion / issues with enabling the watchdog system via       |
   |            systemd vs. the previous watchdog daemon approach.  It seems the systemd approach     |
   |            is more granular and might be more compatible with the Linux Out of Memory (OOM       |
   |            killer (OOM) process but it doesn't seem to always work for system hangs.             |
   |                                                                                                  |
   |            It's unclear if enabling this via the watchdog package will conflict with             |
   |            the Systemd method.  As such, I don't know if I can recommend enabling this           |
   |            at this time. Raspbian Stretch uses the watchdog 5.15-2 package which is supposedly   |
   |            fixed but the documentation hasn't caught up.  I believe the proper solution now is   |
   |            to exclusively use the Systemd approach and NOT use the watchdog package.             |
   |                                                                                                  |
   | see:                                                                                             |
   | |
   |                            |
   |                                     |

To get this useful feature working, you need to follow a few key steps:

   1. Make sure the Broadcom watchdog kernel module is present:

         NOTE:  The path and the name of the kernel module for watchdog has changed over time 
                with the various Rpi kernel versions

         #Correct name in Raspbian Bullseye and Buster - kernel versions: 5.10.92, 5.9.x, 5.4.51+ or 4.19.50-v7+
         find /lib/modules/`uname -r` | grep wdt

         #Correct name in Raspbian Stretch - kernel version: 4.9.45
         find /lib/modules/`uname -r` | grep bcm2835

         #Correct name in Raspbian Jessie
         find /lib/modules/`uname -r` | grep bcm2835_wdt

         #Correct name in Raspbian Wheezy
         find /lib/modules/`uname -r` | grep bcm2708_wdog

   2. Confirm that the /dev/watchdog device is (or isn't) present

         ls -la /dev/watchdog
         crw------- 1 root root 10, 130 Jun 29 20:53 /dev/watchdog

      If it *IS* already present (aka the kernel module is loaded), you can skip down to step #3 

      or if it's not loaded where you see:
         ls: cannot access /dev/watchdog: No such file or directory

         You will need to follow the below steps to get it to automatically load

      To get the watchdog kernel module to load:

         2.A  For Raspbian Stretch ONLY via Systemd:

            1. edit /etc/systemd/systemd.conf
                  - change #RuntimeWatchdogSec= to RuntimeWatchdogSec=10
                  - uncomment #ShutdownWatchdogSec=10min

            2. This might now be obsolete: Temporarily follow the recommendations found in


               Seems this recommendation is avoiding the SystemD approach 

         2.B. For Raspbian Jessie ONLY - Buster and Stretch do not need this due to the tighter 
                                 integration with Systemd

            1. Load the Broadcom watchdog kernel module at boot time:

               NOTE:  Systemd will also automatically load the kernel module when
                      it sees a change to the /etc/modules file

              #only for Jessie / 4.4.x kernels 
              sudo echo "bcm2835_wdt" >> /etc/modules

            2. Load the kernel module and make sure it loaded

               # This only for Jessie / 4.4.x kernels
               #  This doesn't create any harm on Stretch / 4.9.x kernels but also won't show up at all
               sudo modprobe bcm2835_wdt

               sudo lsmod | grep bcm2835_wdt
               bcm2835_wdt             4133  0

               NOTE:  Notice the trailing "0" here.  This means it's not currently in use

         2.C Confirm that the /dev/watchdog device NOW is present

            ls -la /dev/watchdog
            crw------- 1 root root 10, 130 Dec 12 16:01 /dev/watchdog 

   3. All OS versions: Install the software side of things:

         sudo apt update
         sudo apt install watchdog

   4. Enable the software refresh daemon to start on boot (but it won't start just yet)

         # Raspbian Bullseye and Buster
         # ----------------------------
         Confirmed things enable and auto-start fine when "watchdog" is installed above

         # Raspbian Stretch
         # ---------------
         Confirmed things enable and auto-start fine when "watchdog" is installed above

         #  Raspbian Jessie
         # ---------------
         #  At the moment, this watchdog package is not 100% Systemd compatible.  If you tried to run:
         #    sudo systemctl enable watchdog
         #  You would see various errors like 
         #    The Systemd unit files have no [Install] section. They are not meant to be enabled
         #    using systemctl.  Possible reasons for having this kind of units are:
         #    1) A unit may be statically enabled by being symlinked from another unit's
         #       .wants/ or .requires/ directory.
         #    2) A unit's purpose may be to act as a helper for some other unit which has
         #       a requirement dependency on it.
         #    3) A unit may be started when needed via activation (socket, path, timer,
         #       D-Bus, udev, scripted systemctl call, ...).

             To fix this in Raspbian Jessie, edit the /lib/systemd/system/watchdog.service file and 
             in the [Install] section, add the line:


    5. Edit the /etc/watchdog.conf file and un-# out the following lines:

         sudo vim /etc/watchdog.conf
         watchdog-device        = /dev/watchdog

         max-load-1             = 24
         max-load-5             = 18
         max-load-15            = 12

         NOTE:  Other interesting things to "watch" are included in here such as ping monitors for the
                network, etc.  Consider enabling other items if you can trust them.

    6. Go ahead and enable and start this service when the system boots

         #Buster and Stretch version of OSes
         sudo systemctl enable watchdog
         sudo systemctl start watchdog.service

       6.a Jessie ONLY: make sure the watchdog kernel module is now being used by showing a "1" at the end

         #The watchdog feature is built into the Raspbian Buster and Stretch kernels
         sudo lsmod | grep bcm2835_wdt
         bcm2835_wdt             4133  1

    7. I would recommend to now reboot the Rpi and after it's rebooted, log in and repeat
       step #2 to ensure the watchdog is running again with:

          systemctl | grep watchdog

    8. If you followed the email section elsewhere in this doc, the "root" user should also 
       receive an email that the Rpi was rebooted if the watchdog ever kicks in

That's all it took (I'd recommend to do a reboot to ensure it gets enabled every time).   
To test the watchdog itself, there are two ways to do it and I recommend to test BOTH 

      a. RECOMMENDED: Cause a kernel panic.  This WILL crash your Rpi and potentially cause 
         file system corruption but it's important to do this test.  This command line will try to 
         minimize that risk:

            1. Turn on the HDMI monitor so you can see the login prompt

            2. become root with running "sudo su"

            3. Crash the Linux kernel (normally the system would forever stay in this state)
               and make sure the machine reboots 60 seconds later:

                  sync; sleep 2; sync; sudo bash -c "echo c > /proc/sysrq-trigger"

            4. You should see a panic message on the HDMI screen and within 10 seconds, the
               Raspberry Pi should automatically reboot.  If it doesn't reboot, review your
               changes as recommended in this section.

      B. Forkbomb the Raspberry Pi into very high load.  This WILL crash your Rpi and 
         potentially cause file system corruption but it's important to do this test.  This 
         command line will try to minimize that risk:

         1. prevent swapping to the SD card!
         sudo systemctl stop dphys-swapfile.service

         2. Root file system is still R/W but lets make it as clean as possible
         # then start the bomb (this is a one line command designed to crash your Rpi)
         sync; sync; sync; : (){ :|:& };:
         3. Shortly after starting the bomb (maybe 15 seconds), the system should automatically 
         reboot,  If it doesn't reboot, review your changes as recommended in this section.

16. Install the required tool-chains to be able to build Linux programs

To build some of the AX.25 packet programs that are either not available in the Debian 
repositories or to build newer versions, you need to install various compiler tool chains.  
Let's do that now with:

   #Install the required programs and any of their dependencies
   sudo apt update
   sudo apt install build-essential autoconf automake libtool checkinstall git

17. (OPTIONAL) Enable local storage for demanding builds

It's generally required on any Linux system that you have a large enough /tmp file system 
to do compiles.  Why /tmp?  Some programs like Direwolf, Node.js, etc. require a lot more 
space than 512MB or 1GB of RAM in the Rpi itself when you compile them.  When some of 
these compiling jobs run low on RAM, they automatically overflow the building objects 
to the /tmp file system.  If this overflow to /tmp happens without having a large enough
overflow space, you will (at minimum) significantly reduce the life of your SD card due to 
many writes.  Worst case, the /tmp will fill up and the build will fail and the OS could
crash.  I know because I killed one SD card this way!

So you You might be thinking: "Why can't I just build this stuff on my Raspberry Pi's SD 

The answer is "you can" but you run the real risk that if you do it enough times, you WILL
actually permanently damage the SD card.  Why?  SD cards are generally intended for writing 
data a few times but READ many times for use cases like digital cameras, music players, etc.  
Compiling code can actually be writing a LOT of data in the same place and if those writes 
are intensely focused in the same storage region, the flash cell there can wear out and fail.  

The ways to work around this include:

   - NOT RECOMMENDED : Use a much larger SD card.  Raspbian can fit on a 4GB SD card but that 
     won't give you much space to do anything.  It's this remaining space that would used for 
     compiles which would focus all the writes in that small area, and potentially fail the 
     flash cells there.  Consider using a 16GB or 32GB card at minimum if you really must do 
     builds on SD cards.  If you go this route, I recommend re-read 
     "section 6. Configure temporary RAM file systems to minimize writes" and increase /tmp 
     to at least 50MB.

   - More Recommended:  Use a USB flash pendrive to mount /tmp.  These kind of storage devices 
     are somewhat more suited (but still not great) for more writes.  The reason for this is 
     they have something called "wear leveling" (some microSD cards have this now too) to 
     distribute the writes throughout the flash cells on it's media.  Not all flash pendrives 
     are equal in terms of compatibility, performance, reliability, or even have this wear
     leveling support.  Arguably Linux is very forgiving here and most pendrives will work 
     fine.  I would recommend to use nothing smaller than a 8GB pendrive.

     Use an external Solid State drive (SDD) or hard disk drive (HDD) connected
     to the USB port.  These devices are designed for handling lots of writes over time.  
     Some of these drives don't come with their own power and assume the computer will supply 
     all it's power needs.  If you don't already know, the Raspberry Pi CANNOT SUPPLY ENOUGH 
     POWER via it's USB ports (the Raspberry Pi 4 is a little better here).  This ultimately 
     means you need to connect a powered USB hub to your Raspberry Pi and connect the external
     USB HDD or SDD to that hub.  A powered USB hub is a hub that comes with it's own external 
     power brick for handling power loads.

To support larger /tmp and general build area storage, I recommend going the external HDD/SDD
route described below:


   1. Your external USB Flash pendrive / HDD / SDD needs to be formatted with a Linux
      File system.  It should NOT a FAT16, FAT32 (VFAT), ExFAT, etc formatted file system.  See below
      on how to reformat your device if required.

   2. These are temporary settings and are to get you compiling things for one boot
      of your Raspberry Pi.  They are NOT required for every boot of your Raspberry Pi.
      This means if you want to do other compiles in the future, these steps are required to be 
      re-run every reboot.  

   3. There is no need to unmount /tmp before you shutdown your Raspberry Pi.  You can 
      just mount the USB HD on top of the existing /tmp mount.  When you're done and 
      unmount the USB HD, the previous mount will be still there

In this example, I'm mounting and unmounting the drive via a script.  You can choose to download and
modify this script which supports syntax differences for Raspbian Buster, Stretch, Jessie, and even
Wheezy as well as both simple primary partition schemes and LVM enabled partitioning.  This script
should just work for simple setups but you'll need to edit the script it for any advanced needs:

   cd /tmp
   chmod 700
   sudo chown root
   sudo mv /tmp/ /tmp/ /usr/local/sbin

Now go ahead and connect the SDD/HDD to your Rpi's USB port and wait 10 seconds.  Then run the 
"dmesg" command where you should see something like:
   [Sun Jul  7 09:42:31 2019] scsi 0:0:0:0: Direct-Access     ST325031 0AS                   PQ: 0 ANSI: 5
   [Sun Jul  7 09:42:31 2019] sd 0:0:0:0: [sda] 488281250 512-byte logical blocks: (250 GB/233 GiB)
   [Sun Jul  7 09:42:31 2019] sd 0:0:0:0: [sda] Write Protect is off
   [Sun Jul  7 09:42:31 2019] sd 0:0:0:0: [sda] Mode Sense: 28 00 00 00
   [Sun Jul  7 09:42:31 2019] sd 0:0:0:0: [sda] No Caching mode page found
   [Sun Jul  7 09:42:31 2019] sd 0:0:0:0: [sda] Assuming drive cache: write through
   [Sun Jul  7 09:42:31 2019] sd 0:0:0:0: Attached scsi generic sg0 type 0
   [Sun Jul  7 09:42:31 2019]  sda: sda1
   [Sun Jul  7 09:42:31 2019] sd 0:0:0:0: [sda] Attached SCSI disk

Ok, so I have an important question for you:

   Have you ever used this storage device under Linux?  

If not, it's probably formatted with either the VFAT or ExFAT Windows file systems.  That won't work 
for Linux so we need to ERASE your drive, partition it, and then REFORMAT it.  Make sure you're OK 
with removing all the data off this drive or STOP following this section *now*!  Assuming you're OK 
with the erasing of the drive and your drive drive is "/dev/sda" as shown in the example above, let's 
use the newer style "parted" command to see what file system type is on your drive:

   sudo parted /dev/sda print
   Model: ST325031 0AS (scsi)
   Disk /dev/sda: 250GB
   Sector size (logical/physical): 512B/512B
   Partition Table: msdos
   Disk Flags:

   Number  Start   End    Size   Type     File system  Flags
    1      1049kB  250GB  250GB  primary  fat32

Let's delete that partition and create a new Linux one.  To do that, let's use parted in interactive

  sudo parted /dev/sda
  GNU Parted 3.2
  Using /dev/sda
  Welcome to GNU Parted! Type 'help' to view a list of commands.
  (parted) ?

     Let's get the partition numbers out of the program using the "print" command.  As you can see here,
     we have the "1" partition that we'll want to delete:
        (parted) print
        Model: ST325031 0AS (scsi)
        Disk /dev/sda: 250GB
        Sector size (logical/physical): 512B/512B
        Partition Table: msdos
        Disk Flags:

        Number  Start   End    Size   Type     File system  Flags
         1      1049kB  250GB  250GB  primary  fat32

     Ok, let's delete the old partition and create a new one:
        rm 1

    Ok, now let's use the modern GPT style of partition tables (compared to the legacy MBR type):
       (parted) mklabel gpt
       Warning: The existing disk label on /dev/sda will be destroyed and all data on this disk will be lost. Do you want to continue?
       Yes/No? yes

    Ok, now let's create a single large partition using the EXT4 file system and the maximum drive size as show above shown as "250GB":
       mkpart primary ext4 0GB 250GB

    Check your work by using the "print" command:
       Model: ST325031 0AS (scsi)
       Disk /dev/sda: 250GB
       Sector size (logical/physical): 512B/512B
       Partition Table: gpt
       Disk Flags:

       Number  Start   End    Size   File system  Name     Flags
        1      1049kB  250GB  250GB  ext4         primary

   Ok, looks good so use the "quit" command to exit partd.  Now let's format the drive with the following command.  When (or if 
   prompted), give a "y" to confirm you want to format the partition.  The actual formatting will take various amounts of time
   depending on the size and performance of your drive:
      /sbin/mkfs.ext4 /dev/sda1

      mke2fs 1.44.5 (15-Dec-2018)
      /dev/sda1 contains a vfat file system
      Proceed anyway? (y,N) y
      Creating filesystem with 61034752 4k blocks and 15261696 inodes
      Filesystem UUID: b83c5909-3fdd-4ef0-af0c-a6d0f1ac20b2
      Superblock backups stored on blocks:
              32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
              4096000, 7962624, 11239424, 20480000, 23887872

      Allocating group tables: done
      Writing inode tables: done
      Creating journal (262144 blocks): done
      Writing superblocks and filesystem accounting information: done
Ok, now we need to install the LVM tools just in case your existing SDD/HDD was already 
formatted with a LVM partitioning layout:

   apt install lvm2

Now you're ready to mount the drive:

   sudo /usr/local/sbin/

If this is the first time you've followed this guide, you'll be given some instructions to
   Stage 2 - /tmp/usr/src/archive does not exist on USB HD.  Create this directory path with the command:
   sudo mkdir -p /tmp/usr/src/archive/Rpi-scratch
   sudo umount /tmp

If you see that, then follow those commands by simpling typing in:
   sudo mkdir -p /tmp/usr/src/archive/Rpi-scratch
   sudo umount /tmp

  NOTE:  If you get a busy error when unmounting /tmp, make sure you're not currently cd'ed 
         into the /tmp directory and then try the umount command again.

Now run the command again:
   sudo /usr/local/sbin/

Essentially, this mount script above mount a partition onto /tmp and creates some symlinks to
/usr/src/archive for a build area.  In my specific example, what is does is the following with a bunch
of error checking, etc:
  #   Attach the USB HD
  #   mount /dev/mapper/vg_dranchlt3-lv_root /mnt/lvm/root 
  #   mkdir -p /mnt/lvm/root/home/
  #   ln -s /mnt/lvm/root/usr/src/archive/ /usr/src/archive
  #   mount /dev/mapper/vg_dranchlt3-lv_root /tmp
  #   rm /usr/src/archive
  #   ln -s /tmp/usr/src/archive/ /usr/src/archive

Finally, a few things to consider:

  1. Since this script mounts a /tmp volume on the HDD and as such, the drive might ever get idle enough
     to spin down.  It's recommended to either set the drive to a more aggressive APM level or run the 
     umount script when you don't need the drive. 

  2. if you ever want to unmount the drive at any time, just do the following:

     a. Make sure that you don't have any shell logins in any of the directories on the mounted drive 
        (including the base shell after you used "sudo") or the umount will refuse the request

     b. run "sudo /usr/local/sbin/" which will umount the drive and then 
        spin down the drive

17.a (OPTIONAL): Create remote NFS mounts for compile scratch space (save the SD card)

  | IMPORTANT                                                                                                       |
  | ---------                                                                                                       |
  | It seems that you CANNOT use autoconf (at least v2.69-8) over NFS                                               |
  | Centos5 or Centos6: -                                        |
  | |
  |                                                                                                                 |
  |  Work around:  You MUST build your source code to a local file system to the system be it the SD card           |
  |                (NOT RECOMMENDED) or attach a USB SDD or HDD (RECOMMENDED)                                       |
  |                                                                                                                 |
  |                See the previous section for how to use the USB HDD/SSD approach                                 |

  I'm leaving this section in place just in case some people are curious on the NFS steps

#Install NFS server and client programs on the remote NFS server
sudo apt install nfs-kernel-server nfs-common

#Install NFS client programs on the Raspberry Pi
sudo apt install nfs-common

#This is required for mounting remote legacy NFS machines on both the NFS server and NFS client
#  Without this , you will see the error:
#   mount.nfs: rpc.statd is not running but is required for remote locking.
# Run these commands on both the NFS server and the NFS client(s)
sudo systemctl enable rpcbind
sudo systemctl start rpcbind 

# Now we need to edit the NFS server's /etc/exports file to publish what file systems
# can be mounted and to WHERE - in this example, only the host at can NFS mount
# this remote /usr/src/archive/RPi directory and only do so as READ-ONLY:

sudo vim /etc/exports
/usr/src/archive/RPi       ,no_root_squash,no_subtree_check,async)
/usr/src/archive/RPi/tmp   ,no_root_squash,no_subtree_check,async)

# Now make the NFS server re-read the exports file and start exporting the directories:

   sudo exportfs -avr

#Next up on the local machine, edit the /etc/default/nfs-common file and change the line to:

#   TBD - Optional NFS options you can add to specify NFS over TCP or UDP, 
#         use NFS v4, NFSv3, NFSv2, etc

# Ok, let's test it.  On your remote NFS client machine, run this command to query the 
#  NFS server (your Raspberry Pi) of what NFS mounts are available to your host

   /usr/sbin/showmount -e
   Export list for

# OPTIONAL:  You can create mounting script to have the client system more easily mount
#            the NFS file shares.  
#   NOTE:   This script is specific to my environment -Please edit to suit your 
#           environment

   cd /tmp
   chmod 700
   sudo chown root
   sudo mv /usr/local/sbin

The contents of this /usr/local/sbin/ script are the following:

   if [ ! -d /mnt/nfs ]; then
     mkdir /mnt/nfs

   #change the hampacket host to match your own internal NFS server
   mount -t nfs hampacket2:/usr/src/archive/RPi /mnt/nfs
   mount -t nfs hampacket2:/usr/src/archive/RPi/tmp /mnt/nfs/tmp

18. Build VE7FET AX.25 packages from git

Why use the VE7FET AX.25 packages and not the official AX.25 packages? My reasoning is fully documented here:

   But... (there's always a "but")... things have been changing a bit.  Back in late August 2019, 
   there had been some very disruptive changes coming in from the Debian Stretch distro versions 
   which broke things.  At the same time, the VE7FET AX.25 sources had created conflicts with
   man page locations which broke deb packaging.  A LOT of changes have come into the VE7FET repo 
   to resolve these issues and I believe things should be ok now.

Anyway, assuming you've setup the scratch compile space and /tmp overflow from previous sections, 
let's get started in building out the AX.25 packet system:

   #If you didn't already create this directory on your mounted SDD/HDD:
   sudo mkdir -p /usr/src/archive
   sudo chown $USER /usr/src/archive
   mkdir -p /usr/src/archive/Rpi-scratch/
   sudo chown $USER /usr/src/archive/Rpi-scratch/

18.a Install libax25:

Download the current VE7FET sources for AX.25.  If you want to know why I recommend these AX.25
sources vs say the the official AX.25 sources, see:

Ok, let's get started:

      #Use the new directory
      cd /usr/src/archive/Rpi-scratch/

      #If this is the first time downloading the repo
      git clone

      #If you've already downloaded it before, let's update the repo
      cd linuxax25/libax25/
      git pull

Ok, now enter the libax25 directory (if you aren't already there):

      cd linuxax25/libax25/

Next, we need to install the Zlib and zlib-dev libraries as programs in this package requires it
(if it's not already installed in your version of Raspberry Pi OS):

   sudo apt install zlib1g zlib1g-dev

Now let's pre-configure the code:

   NOTE: Running this command can seemingly look hung for 20 seconds before it starts to show output.
         It IS running and it's completion is dependent on the performance of your Raspberry Pi

         autoreconf --install

       If you received an error above about "autoreconf", you probably skipped 
       ahead and DIDN'T follow "Section 16 Install the required compiler tool chains 
       to be able to build Linux programs".  Go back and do that first!

Assuming the above command worked after say 30 seconds, now do the following:

   # NOTE:  File placement opinion: You will notice I'm placing the files in /usr and /etc and NOT
            in say /usr/local, /usr/local/etc, /opt, etc.  My personal philosophy here is the 

               - If a program is packaged, it should go into the standard /usr, /lib, /etc, paths.
               - If a program is NOT packaged, it goes into /usr/local, /usr/local/lib, etc.  

            If you don't agree with my approach, feel free to change the paths to whatever you prefer

   # Now configure the package 
   ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var

   # Now build the sources: 
   #   the -j8 is for Rpi v4, 3+, and 3 with four cores
   #   use -j2 for Rpi 2, Zero-W, Zero, and 1 with one core
   make -j8

Ok, let's prepare to package it.  First do a work around trick for a checkinstall bug which incorrectly 
reads RPM spec files:

   mv libax25.spec libax25.spec.old

Next, optionally do temporarily work around a known GLIBC conflict  (see below NOTES for more details)
for Raspbian Stretch or Jessie:

   | NOTE:  Do NOT do this on Raspberry Pi OS "Buster" or the configure stage will FAIL |
   sudo mv /usr/include/netax25/ax25.h /usr/include/netax25/ax25.h.old

Next, determine what version of libax25 sources you have

      grep " VERSION" config.h

   As of 9/24/20, it shows:
   #define VERSION "1.1.3"

Now run the checkinstall program but substitute in the correct version if required
and package things up:

   sudo checkinstall --pkgname libax25 --pkgversion 1.1.3 --pkgrelease 1 --pkggroup \
hamradio --pkgsource --maintainer \ --provides "ax25" --requires zlib1g

When prompted for "Should I create a default set of package docs", Select Y

Next, when prompted for the description, enter in the following:
   Library for amateur radio packet radio applications using the AX.25, Netrom, ROSE, etc protocols

Hit ENTER again to accept the description

Next, confirm the checkinstall fields all look ok and similar to the following:
0 -  Maintainer: [ ]
1 -  Summary: [ Library for amateur radio packet radio applications using the AX.25, Netrom, ROSE, etc protocols ]
2 -  Name:    [ libax25 ]
3 -  Version: [ 1.1.3 ]
4 -  Release: [ 1 ]
5 -  License: [ GPL ]
6 -  Group:   [ hamradio ]
7 -  Architecture: [ armhf ]
8 -  Source location: [ ]
9 -  Alternate source location: [  ]
10 - Requires: [ zlib1g ]
11 - Provides: [ ax25 ]
12 - Conflicts: [  ]
13 - Replaces: [  ]

Hit ENTER to start the packaging and then attempt to install the package (hint.. it WILL fail but
   there is a reason).  After reviewing these NOTEs, please see next steps

   | NOTE #1: - checkinstall errors                                             |
   |                                                                            |
   |       If you notice that all kinds of strange of spaces are winding up     |
   |       in the output above (say the "name" field) or 1%{?dist} in the       |
   |       "release" field, this means you didn't rename the .spec file as      |
   |       mentioned above!  Rename the .spec file and try again                |

Resolving package installation failure:

   - You most likely will see checkinstall fail with:

        Building Debian package...OK
        Installing Debian package... FAILED!
        *** Failed to install the package
        Do you want to see the log file?  [y]: n
        Erasing temporary files...OK
        Writing backup package...OK
        Deleting temp dir...OK

     It seems that a recent VE7FET commit in the VE7FET GIt repo have restored previously
     known glibc conflicts.  What is that you ask?  

     If you're using either the VE7FET repo code or the "Official AX25" repo code 
     or even the old Raspbian distro-included AX.25 packages, the .deb packaging 
     creation stage will succeed but the actual package INSTALL phase will FAIL 
     due to a conflict with the /usr/include/netax25/ax25.h file which is present
     in both the Glibc package and this libax25 package. You can read more but 
     this bug at .  To work around 
     this, you can do a safe force-overwrite the conflicting file with the following 

             sudo dpkg --force-overwrite --install libax25_1.1.3-1_armhf.deb

   | NOTE #2 - Future patching issues:                                                                               |
   |                                                                                                                 |
   |      Related to the package installation issue above, this long standing Glibc conflict issue with the libax25  |
   |      package was seemingly fixed and then re-broken in the Aug 2018 version of the VE7FET AX25 sources repo.    |
   |      If you're using either an impacted version of the VE7FET repo, a version of the Official AX.25 repo,  or   |
   |      the official Raspbian repos which have VERY old code in them,  this work-around script below will still be |
   |      needed.                                                                                                    |
   |                                                                                                                 |
   |      Background:                                                                                                |
   |      As you operate your Raspberry Pi through the months and years, it's important that you keep up on security |
   |      and other bug fix updates.   You will eventually need to install glibc/libc updates included with the      |
   |      Raspberry Pi OS / Raspbian / whatever Linux distro you installed which *WILL* unfortunately conflict       |
   |      around the libax25 package similar to the NOTEs above.  That package installation error will look          |
   |      something like the following:                                                                              |
   |                                                                                                                 |
   |         Preparing to unpack .../libc6-dev_2.24-11+deb9u3_armhf.deb ...                                          |
   |         Unpacking libc6-dev:armhf (2.24-11+deb9u3) over (2.24-11+deb9u1) ...                                    |
   |         dpkg: error processing archive /var/cache/apt/archives/libc6-dev_2.24-11+deb9u3_armhf.deb (--unpack):   |
   |         trying to overwrite '/usr/include/netax25/ax25.h', which is also in package libax25 1.0.5-1             |
   |                                                                                                                 |
   |                                                                                                                 |
   |      To resolve this conflict, I've written a script to make the Raspbian updates work more smoothly:           |
   |                                                                                                                 |
   |         #Download and place this script                                                                         |
   |         cd /tmp                                                                                                 |
   |         wget |
   |         chmod 700                                                               |
   |         sudo chown root                                                         |
   |         sudo mv /usr/local/sbin/                                                |
   |                                                                                                                 |
   |      Next, you need to find the libax25 .deb package you built above and make it always available for the       |
   |      script you just downloaded to find  it.  My instructions recommend to build all those AX25 packages on an  |
   |      external USB HDD but you probably don't want that mounted 24/7.  For this setup, I do the following:       |
   |                                                                                                                 |
   |            # change the username here to reflect your username                                                  |
   |            mkdir /home/dranch/libax25/                                                                          |
   |                                                                                                                 |
   |            # cd to wherever you built the VE7FET AX.25 packages and find the libax25 deb file                   |
   |            cp -v /usr/src/archive/Rpi-scratch/linuxax25/libax25/libax25_*.deb /home/dranch/libax25/             |
   |                                                                                                                 |
   |                                                                                                                 |
   |        Finally, edit the downloaded /usr/local/sbin/ script's "FET_LIBAX25_PATH" |
   |        variable to point to the directory where the libax25 package is available.  For example:                 |
   |                                                                                                                 |
   |            vim /usr/local/sbin/                                                  |
   |            --                                                                                                   |
   |            #Change this to your desired path                                                                    |
   |            FET_LIBAX25_PATH="/home/dranch/libax25"                                                              |
   |            --                                                                                                   |
   |                                                                                                                 |
   |      After that, when you're asked to update the glibc package as part of a regular OS update but the process   |
   |      fails, simply run this script:                                                                             |
   |                                                                                                                 |
   |         sudo /usr/local/sbin/                                                    |
   |                                                                                                                 |
   |      This script will first download the newer glibc/libc packages from the Raspberry Pi OS / Raspbian repo,    |
   |      force install those packages FIRST then re-install the libax25 package and then exit.  Once that's         |
   |      completed, you can again run:                                                                              |
   |                                                                                                                 |
   |         sudo apt upgrade --no-install-recommends                                                                |
   |                                                                                                                 |
   |      and your machine will now download and install all the remaining packages  You should be good to go at     |
   |      that!                                                                                                      |

   With a recent toxic release of the AX.25 packages from Debian, it became very obvious that Debian's APT    
   repo system makes no distinction between this locally built VE7FET AX.25 package and the Debian built (and 
   toxic) AX.25 packages.  To protect your system from having the Debian APT system overwriting your built    
   packages, run the following command:                                                                       

      sudo apt-mark hold libax25

Ok, the base library for AX.25 should be installed!  

If you manually want to install this newly built libax25 package on some other machine, simply copy of the .deb 
package to that other machine and run:

   sudo dpkg --install libax25_1.1.3-1_armhf.deb

18.b Install ax25-apps:

Ok, the next few steps are going to be a lot easier.  First, this next package's source was already downloaded 
via the previous git command for libax25.  To compile this package, we first need to install the Ncurses 
libraries as the "call" program requires it:

   #For newer Raspberry Pi OS versions
   #  NOTE: As of 7/7/19, the libncursesw6-dev package seems to be missing in Raspbian Buster and Bullseye.  
   #        To work around this issue, install the previous version or run the following command:

       sudo apt install libncursesw5 libncursesw5-dev

   #For Older raspberry pi os versions
       sudo apt install libncursesw6 libncursesw6-dev 

Next, go into the source directory and start building:

   cd /usr/src/archive/Rpi-scratch/linuxax25/ax25apps

   NOTE: Running this command can seemingly look hung for 20 seconds before it starts to show output.
         It IS running and it's completion is dependent on the performance of your Raspberry Pi

         autoreconf --install

   #Now configure the package 
   ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var

   # Now build the sources: 
   #   the -j8 is for Rpi v4, 3+, and 3
   #   use -j2 for Rpi 2, Zero-W, Zero, and 1
   make -j8

Now again apply the work-around for checkinstall bug incorrectly reading RPM spec files:

   mv ax25apps.spec ax25apps.spec.old

   #work around a busted makefile - still required in Raspbian Buster, Stretch, etc
   sudo /bin/mkdir -p /var/ax25/ax25rtd

   #Determine what version of libax25 you have
   grep " VERSION" config.h

      As of 6/30/19, it shows:
      #define VERSION "2.0.1"

Now run the checkinstall program but substitute in the correct version if required
and package things up:

   #For Raspberry Pi OS Bullseye and Buster
   sudo checkinstall --pkgname ax25-apps --pkgversion 2.0.1 --pkgrelease 1 --pkggroup \
hamradio --pkgsource --maintainer \ --provides ax25 --requires libax25,libncurses6 make install 

  When prompted for "Should I create a default set of package docs", Select Y

Next, when prompted for the description, enter in the following:
This package provides specific user applications for hamradio that use AX.25 Net/ROM or ROSE network protocols

Hit ENTER again to accept the description

Next, confirm the checkinstall fields all look ok and similar to the following:
0 -  Maintainer: [ ]
1 -  Summary: [ This package provides specific user applications for hamradio that use AX.25 Net/ROM or ROSE network protocols ]
2 -  Name:    [ ax25-apps ]
3 -  Version: [ 2.0.1 ]
4 -  Release: [ 1 ]
5 -  License: [ GPL ]
6 -  Group:   [ hamradio ]
7 -  Architecture: [ armhf ]
8 -  Source location: [ ]
9 -  Alternate source location: [  ]
10 - Requires: [ libax25 ]
11 - Provides: [ ax25 ]
12 - Conflicts: [  ]
13 - Replaces: [  ]

Hit ENTER to start the packaging and checkconfig will now automatically install the package 
for you. 

   | NOTE #1:                                                                   |
   |       If you notice that all kinds of strange of spaces are winding up     |
   |       in the output above (say the "name" field) or 1%{?dist} in the       |
   |       release field, this means you didn't rename the .spec file as        |
   |       mentioned above!  Rename the .spec file and try again                |

After that, you should be good.  If you are doing this installation with an older 
version VE7FET ax25-apps (no longer needed as of 6/30/18), the default configuration 
example files might not be installed.  To check, do the following:

   ls -la /etc/ax25

If you don't see the ax25ipd.conf, ax25mond.conf, and ax25rtd.conf example config files, 
run the following commands:

      sudo mkdir /etc/ax25
      sudo cp -n /usr/share/doc/ax25apps/conf/ax25ipd.conf.dist /etc/ax25/ax25ipd.conf
      sudo cp -n /usr/share/doc/ax25apps/conf/ax25mond.conf.dist /etc/ax25/ax25mond.conf
      sudo cp -n /usr/share/doc/ax25apps/conf/ax25rtd.conf.dist /etc/ax25/ax25rtd.conf

   # If the above copy commands fail finding the *.dist files, this means you're probably 
   # ether using:
   #    - older version of VE7FET repo
   #    - an older Official AX25 repo
   #    - the very old Raspbian packages.

   | CRITICAL NOTE:                                                             |
   |      With a recent toxic release of the AX.25 packages from Debian, it     |
   |      became obvious that Debian's APT system makes no distinction between  |
   |      this home-built VE7FET package and the old Debian built (and toxic)   |
   |      packages.  To protect your system from overwriting your built         |
   |      packages, run the following command:                                  |
   |                                                                            |
   |         sudo apt-mark hold ax25-apps                                       |
   |                                                                            |

If you manually want to install the built package on some other machine, use the 
following command on that other machine once the package is copied over:

   sudo dpkg --install ax25-apps_2.0.1-1_armhf.deb

  then if using an older VE7FET based package like mentioned above, don't forget:

      sudo cp -n /usr/share/doc/ax25apps/conf/ax25ipd.conf.dist /etc/ax25/ax25ipd.conf
      sudo cp -n /usr/share/doc/ax25apps/conf/ax25mond.conf.dist /etc/ax25/ax25mond.conf
      sudo cp -n /usr/share/doc/ax25apps/conf/ax25rtd.conf.dist /etc/ax25/ax25rtd.conf

18.c Install ax25-tools

Ok, one more package to install.  The sources for the package were already downloaded via 
the previous git command so let's get started:

   cd /usr/src/archive/Rpi-scratch/linuxax25/ax25tools

   NOTE: Running this command can seemingly look hung for 20 seconds before it starts to show output.
         It IS running and it's completion is dependent on the performance of your Raspberry Pi

      autoreconf --install

   #Now configure the package 
   ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --datadir=/usr/share --datarootdir=/usr/share

   # Now build the sources: 
   #   the -j8 is for Rpi v4, 3+, and 3
   #   use -j2 for Rpi 2, Zero-W, Zero, and 1
   make -j8

Now work around the checkinstall bug incorrectly reading RPM spec files:

   mv ax25tools.spec ax25tools.spec.old

#Determine what version of libax25 you have

   grep " VERSION" config.h

      As of 9/24/20, it shows:
      #define VERSION "1.0.5"

Now run the checkinstall program but substitute in the correct version if required
and package things up:

   sudo checkinstall --pkgname ax25-tools --pkgversion 1.0.5 --pkgrelease 1 --pkggroup \
hamradio --pkgsource --maintainer \ --provides ax25 --requires libax25,zlib1g make install

When prompted for "Should I create a default set of package docs", Select Y

Next, when prompted for the description, enter in the following:
This package provides specific amateur radio packet radio tools for applications that use AX.25 Net/ROM or ROSE network protocols

Hit ENTER again to accept the description

Next, confirm the checkinstall fields all look ok and similar to the following:
0 -  Maintainer: [ ]
1 -  Summary: [ This package provides specific user applications for hamradio that use AX.25 Net/ROM or ROSE network protocols ]
2 -  Name:    [ ax25-tools ]
3 -  Version: [ 1.0.5 ]
4 -  Release: [ 1 ]
5 -  License: [ GPL ]
6 -  Group:   [ hamradio ]
7 -  Architecture: [ armhf ]
8 -  Source location: [ ]
9 -  Alternate source location: [  ]
10 - Requires: [ libax25,zlib ]
11 - Provides: [ ax25 ]
12 - Conflicts: [  ]
13 - Replaces: [  ]

Hit ENTER to start the packaging and checkconfig will now automatically install the package 
for you. 

   | NOTE #1:                                                                   |
   |       If you notice that all kinds of strange of spaces are winding up     |
   |       in the output above (say the "name" field) or 1%{?dist} in the       |
   |       release field, this means you didn't rename the .spec file as        |
   |       mentioned above!  Rename the .spec file and try again                |

   | NOTE #2:                                                                   |
   |      If you're running an older version of the VE7FET repo, you might see  |
   |      various conflicts around man pages.  This below issue detailed below  |
   |      should be resolved by the Aug 2018 version of the VE7FET repo.        |
   |                                                                            |
   |      If you must stay with an older version of the repo, you might need to |
   |      use the "official AX25" repo or the very old Raspbian packages instead|
   |                                                                            |
   |      Details:                                                              |
   |      The above checkinstall command MIGHT fail at the "Installing Debian   |
   |      package" stage due to install due to a recently introduced set of     |
   |      conflicts with axports.5.gz, nrports.5.gz and rsports.5.gz manual     |
   |      files.  The newest versions of the VE7FET repo have fixed this but if |
   |      you have this conflict, I recommend to do a forced overwrite of the   |
   |      conflicting files with the following command:                         |
   |                                                                            |
   |   sudo dpkg --force-overwrite --install ax25-tools_1.0.5-1_armhf.deb       |
   |                                                                            |
   | You can read more but this bug at:                                         |
   |                         |

After that, you should be all done with the AX25 stuff!  

If you are doing this installation with an older version VE7FET ax25-tools, the 
default configuration example files might not be installed.  To check, do the following:

   ls -la /etc/ax25

If you don't see files like ax25d.conf, axports, axspawn.conf, nrbroadcast, nrports, rsports, 
rxecho.conf, and ttylinkd.conf files, run the following commands:

      sudo cp -n /usr/share/doc/ax25tools/conf/ax25d.conf.dist /etc/ax25/ax25d.conf
      sudo cp -n /usr/share/doc/ax25tools/conf/axports.dist /etc/ax25/axports
      sudo cp -n /usr/share/doc/ax25tools/conf/axspawn.conf.dist /etc/ax25/axspawn.conf
      sudo cp -n /usr/share/doc/ax25tools/conf/nrbroadcast.dist /etc/ax25/nrbroadcast
      sudo cp -n /usr/share/doc/ax25tools/conf/nrports.dist /etc/ax25/nrports
      sudo cp -n /usr/share/doc/ax25tools/conf/rsports.dist /etc/ax25/rsports
      sudo cp -n /usr/share/doc/ax25tools/conf/rxecho.conf.dist /etc/ax25/rxecho.conf
      sudo cp -n /usr/share/doc/ax25tools/conf/ttylinkd.conf.dist /etc/ax25/ttylinkd.conf

   # If the above copy commands fail finding the *.dist files, this means you're using a
   # very old VE7FET repo, an older Official AX25 repo, or the very old Raspbian packages.

   | CRITICAL NOTE:                                                             |
   |      With a recent toxic release of the AX.25 packages from Debian, it     |
   |      became obvious that Debian's APT system makes no distinction between  |
   |      this home-built VE7FET package and the old Debian built (and toxic)   |
   |      packages.  To protect your system from overwriting your built         |
   |      packages, run the following command:                                  |
   |                                                                            |
   |         sudo apt-mark hold ax25-tools                                      |
   |                                                                            |

If you manually want to install the built package on some other machine, use the 
following command on that other machine once the package is copied over:

   sudo dpkg --install ax25-tools_1.0.5-1_armhf.deb

If using an older VE7FET based package like mentioned above, don't forget:

      sudo cp -n /usr/share/doc/ax25tools/conf/ax25d.conf.dist /etc/ax25/ax25d.conf
      sudo cp -n /usr/share/doc/ax25tools/conf/axports.dist /etc/ax25/axports
      sudo cp -n /usr/share/doc/ax25tools/conf/axspawn.conf.dist /etc/ax25/axspawn.conf
      sudo cp -n /usr/share/doc/ax25tools/conf/nrbroadcast.dist /etc/ax25/nrbroadcast
      sudo cp -n /usr/share/doc/ax25tools/conf/nrports.dist /etc/ax25/nrports
      sudo cp -n /usr/share/doc/ax25tools/conf/rsports.dist /etc/ax25/rsports
      sudo cp -n /usr/share/doc/ax25tools/conf/rxecho.conf.dist /etc/ax25/rxecho.conf
      sudo cp -n /usr/share/doc/ax25tools/conf/ttylinkd.conf.dist /etc/ax25/ttylinkd.conf

18.c.1 - Issues with Predictable Network interface names and Linux AX25

   | CRITICAL: Work around for significant Predicable Interface naming bug with AX.25      |
   |                                                                                       |
   |    NOTE:  This now seems to be disabled in Raspberry Pi Bullseye but please check it  | 
   |                                                                                       |
   |    I have confirmed that with Raspbian Stretch (unclear on Buster at the moment),     |
   |    there is an interface naming issues via it's newly enabled "predictable" network   |
   |    interface name feature.  What is this?                                             |
   |                                                                                       |
   |    When enabled and you run the command "ifconfig" or "ip addr", you will not see     |
   |    Ethernet interfaces with the classic names like "eth0" or "eth1"  but instead,     |
   |    you'll see something very long like "enxb827eb5f05" based on a combination of how  |
   |    the system is connected to your Ethernet interface (PCI this, USB, etc and the MAC |
   |    interface address.  How's that for catchy?  For known reasons to the legacy parts  |
   |    of the Linux kernel (AX.25, and other parts), the "sa_data" kernel data structure  |
   |    in both the stock Raspbian AX.25 package code and the 3rd party VE7FET AX.25 code  |
   |    will give errors like the following when ANY *network* interface name (AX.25       |
   |    interface, Ethernet interface, is longer than 13 characters is used with AX.25     |
   |    programs like "beacon":                                                            |
   |                                                                                       |
   |       SIOCGIFHWADDR: No such device                                                   |
   |                                                                                       |
   |    Other AX25 programs like Linpac will crash upon start with:                        |
   |                                                                                       |
   |       /usr/bin/linpac: line 181:  9811 Segmentation fault   $PKG_BINDIR/linpac $*     |
   |                                                                                       |
   |    Fortunately, if you disable predictable network interface names, things work fine. |
   |    To do this, do the following steps if you didn't already disable this in the above |
   |    section 4. Rpi initial setup (OS patches), additional Security hardening, Rpi      |
   |    firmware upgrade).  Alternatively, you can manually disable predictable names      |
   |    with:                                                                              |
   |                                                                                       |
   |       sudo vi /boot/cmdline.txt                                                       |
   |       --                                                                              |
   |       #append the following to the end of the one line in this file                   |
   |       net.ifnames=0 biosdevname=0                                                     | 
   |       --                                                                              |
   |                                                                                       |
   |    Now reboot your Raspberry Pi, log back in and run the command "ifconfig" or        |
   |    "ip addr" and confirm your Ethernet interface name is now say eth0, wlan0, etc.    |
   |    Things should work from there on out. Btw, if Linpac did crash on you,  your       |
   |    terminal might be screwed up and not working properly after that.To fix that, run  |
   |    the commands:                                                                      |
   |                                                                                       |
   |       stty sane                                                                       |
   |       rm -f rm /var/lock/LinPac.0                                                     |

19. Hardware vs. Software TNC

Ok, now FINALLY on to real packet stuff.  This very Raspberry Pi centric document focuses 
on installing and using the Direwolf software TNC.  It offers the reader a way to create a 
cheaper yet superior TNC solution for AX.25 packet decodes compared to almost any hardware 
TNC on the market (past or present) including comparisons to TNCs like:

   - TNC-PI (the same PIC micro-controller as TNC-X TNC on a Raspberry Pi HAT board)
   - TNC-X (a PIC micro-controller based TNC)
   - Kantronics KPC (version 2, 3, 3+, KAM, etc)
   - Timewave / AEA PK96 TNCs)
   - Kenwood D710, D72, and D74 TNCs
   - MFJ 1270 / 1272 TNC2 TNCs
   - PacComm TNCs

With that said, this documentation and the included AX25 startup scripts *DO* support:
   - Coastal Chipworks TNC-Pi board via the GPIO header 
   - Kenwood D710 KISS TNC via serial port
   - Kenwood D74 handheld via a Bluetooth serial connection

This support is either mentioned indirectly in this document's appendix and/or within the 
/etc/ax25/ packet bring up script itself.  No doubt, soldering up a TNC-Pi kit is a 
fun project and offers a reliable packet TNC.   Doing packet via Bluetooth on a Kenwood D74 HT 
is also pretty sexy but regardless of each solution, Direwolf's on-air decode performance is 
unparalleled and as such, I would STILL recommend that you just use the software-TNC to 
get the best possible performance!

   NOTE:  If you intended to use a Coastal Chipworks TNC-Pi, Kenwood D710 / D74, or any other 
          hardware KISS TNC, there is NO reason to follow this document's sections to configure 
          a sound card or build / install the Direwolf TNC program, etc.  You can simply SKIP 
          AHEAD to Chapter 25 to take it from there.  

          It's also worth mentioning that if you are looking for running an APRS setup and won't 
          be running the direwolf sw-TNC (which includes complete APRS and APRS-IS support), 
          you'll need to install a different APRS application as Direwolf CANNOT be used with
          hardware TNCs.  A good APRS client alternative is the APRX (for being a server) or 
          Xastir for a combined server and GUI client.  I have both application installations 
          detailed in my HamPacket documentation though that doc is intended for Redhat style
          Linux systems:


20. Choosing and setting up the Sound device

Ok, assuming you're going with the Direwolf software-TNC approach, you first need to pick a 
soundcard to use and get it tuned up.  The Raspberry Pi v4,3+,3,2,ZeroW,Zero,1 boards do NOT 
include a microphone or audio line-in jack so you MUST buy an external sound device.  Read the 
Direwolf User Guide for other recommended devices but I recommend one of these two devices:

   RECOMMENDED - Fe-Pi AudioZ v2.0 HAT board : this board avoids the known Raspberry Pi USB "DWC" / 
                 Direwolf "dead air" transmit audio delay issue found on the legacy Rpi USB stack.  
                 This issue occurred on all Raspberry Pi board versions running the Raspberry Pi or
                 Raspbian OS until the "Buster" which supports a 100% effective workaround.
                 Users no longer need to use the previously recommended OSS to ALSA wrapper with 
                 this I2S based option.

                 NOTE#1: As of 12/23/20, a HAT board 95% similar to the Fe-Pi I2S HAT is available
                         from the makers of the Nexus DR-X kit (see more details below).  The only 
                         difference inis that the TRRS headphone jack isn't solder on by default.  I 
                         already highly recommend the Nexus DR-X kit for connecting your radios to 
                         the Raspberry Pi (includes a built-in power supply and RTC - read below for 
                         more details) so I think this is a WIN-WIN.  If you only want to buy the 
                         Fe-Pi like sound device HAT, send them an email.

                 NOTE#2: As of 11/21/20, the original and Tindie sites say the Fe-Pi 
                         board is now RETIRED and no longer available.

      - Alternative non-USB sound devices to the Fe-Pi / Nexus DR-X sound devices:

         - Audio Injector

               This might be a good alternative to the Fe-Pi but it uses bulky RCA connectors.
               You can source different connectors if you want

      $12 US - Nexus DR-X / Fe-Pi Audio Z v2 clone I2S Sound device (not USB) available at:

         New Nexus DR-X / Fe-Pi Audio Z v2 like HAT (no headphone jack): 

            Historical: Original Now EOLed Fe-Pi Audio Z v2.0 board:

      Need other reasons why to buy this I2S-based sound device over say a USB-based sound device??  
      I still think this Fe-Pi Audio Z v2 board is superior to say a Syba CM-119 USB device for several 

         1. Fe-Pi uses the dedicated I2S audio bus so there aren't any USB issues (see the below
            Syba section for specific URLs, any I/O loading issues on the USB bus or USB power 

         2. No longer relevant: Fe-PI doesn't need to use the legacy OSS hack with Direwolf to 
            minimize the random dead TX time on Raspberry Pi based USB controllers (seeming no 
            longer occurs on the Rpi4 either)

         3. Fe-Pi has slightly better audio specs:

              Line-in ADC > 90 dB SNR and -72 dB THD+N
              Line-Out > 100 dB SNR and -85 dB THD+N

           In comparison, the recommended Syba CM119 USB solution has:

              Line-in ADC >  83 dB SNR and -76 dB THD+N
              DAC Line-Out > 94 dB SNR and -71 dB THD+N   (32 Ohm impedance)

         4. Fe-Pi offers a stereo input (2 channel) vs most sound device's mono (1 channel)
            This could allow you to connect two radios to a single Direwolf instance if you wish

         5. Fe-Pi offers the ability to connect different devices via the microphone vs. line-in 
            jack and the mixer can switch between the inputs electronically

         6. Fe-Pi offers a line-in jack for better impedance matching

         7. Fe-Pi offers various digital audio filtering which are features compared to the 
            simple Syba unit (not really need for Direwolf though)

         8. Very small Pi-Zero physical HAT format using the 40pin header for more reliable 
            electrical connections.  Small format allows for standard 3.5mm audio connectors
            to fix within an Rpi case

         For higher audio fidelity needs (say a music player / Kodi / DLNA box), it's also:

            9. Offers a 5 band hardware equalizer (called "DAP" in alsamixer)

      The Syba CM119 does have the benefit of:

         a. CM119 has 8 GPIO pins available to the user if they are willing to solder wires and level shifts to them

         b. LED activity indicator

   Basic USB-based devices:
      $7 US - Syba SD-CM-UAUD basic sound device which can be had for $7

              Direwolf DEAD AIR ISSUE (RESOLVED): 
                               There is a known Direwolf issue with USB soundcards on older Raspberry Pi boards
                               (3+ and older):  

                               This "key up but have variable Dead TX air time until the modem sounds played" issue 
                               does not happen on X86 machines.  This issue now has a fix and should be in the 
                               mainline Linux kernel since about 2021 but until then, there is also a different yet 
                               effective workarounds.

                               What's the issue?
                               What happens here is that Direwolf will key up the radio via the configured 
                               GPIO pin but the soundcard will wait some random amount of delay before 
                               playing the TNC modem tones.  Some of these delays can be up to 2 seconds!  It's 
                               reported that the Raspberry Pi 4 with it's completely new USB chip and software 
                               stack (all previous generation Raspberry Pi models use the same older SOC built-in 
                               USB chip) does NOT exhibit this issue.  

                               The easy and RECOMMEND workaround for this issue on the older Raspberry Pi modems 
                               is to either:
                                  - Use the newer DWC2 USB stack
                                  - Use the OSS sound stack ALSA wrapper
                               More details below

   NOT RECOMMENDED but works USB sound device:
                             - If you're looking for something even cheaper, you might try using 
                               one of these inexpensive CM108 USB-based sound devices as they've been 
                               reported to work for many people.  Unlike the recommended Syba USB unit 
                               mentioned above, these devices don't always include any microphone input level 
                               control, any audio filters or even include a plastic enclosure to protect 
                               the electronics.  You'll need to add an additional input control like a 
                               resistive input volume potentiometer, etc.  My other concern with using 
                               these inexpensive boards like this is that they can be changed at any time 
                               for different chips at any time and you won't know it:

                               Here is a URL for more details:

      Raspberry Pi 3+ and older boards don't do well with higher sampling sound cards running
      at say 192Khz, etc.  Use a 48Khz sampling soundcard for direwolf:

   Amateur Radio focused USB-based sound devices (Allstar interfaces):
      - There are families of of sound devices using either the CM119 sound chip that's also found 
        in say the Syba sound device or other chips focused on providing a more "integrated" offering
        with minimizing the requirement of creating custom cabling.  These type of devices are commonly
        called "Allstar" devices which is an analog Radio over IP (RoIP) technology similar to Echolink
        and IRLP:

            Nexus DR-X - an audio routing + RTC device + Buck/Boost power supply intended to connect an
            $68     external sound device (Fe-Pi Audio Z v2 is recommended) to either an Amateur Radio's 
                    6pin jack or RJ45 microphone jack (with or without Fe-Pi like I2S sound device) with 
                    electronic mixer controls only - includes a layer case:

            RIM and RIM-Lite - USB to commercial radio audio connections for setups for Motorola, Alinco,
                     Scom, RLC, etc:

            DRA-36 - A USB to either 6pin "DATA" cable or DB9 TNC2 cable + PTT device (kit or fully built)
            $51      only : kit is intended to connect directly to an Amateur Radio's 6pin jack with physical 
                     pots for audio adjustments - includes a separate case:

            DINAH - A USB to 6pin "DATA" cable sound + PTT device intended to connect directly to an Amateur 
            $35     Radio's 6pin jack with electronic mixer controls only - includes a separate case:

            DRAWS - A Raspberry PI HAT to dual 6pin "DATA" cable + PTT device + GPS receiver + RTC + Buck/Boost
            $150    power supply intended to connect directly to an Amateur Radio's jack with electronic mixer
                    controls only - case not included

    Other sound devices might work but it's known that Direwolf is sensitive to USB devices
    and not all work correctly.  The Syba unit is proven reliable and also doesn't spew RF 
    noise on 144.000MHz!  

Tangent:  Why am I talking about "noise on 144.000Mhz?  Take a hand held amateur radio, 
          change it's VFO to 144.000Mhz and walk around your home.  You'll probably find many 
          strong signals (birdies).  Why?  Many devices and sound cards have a poorly shielded 
          12Mhz crystal oscillators which is very very common in modern electronics.  Why does 
          that matter to you? The 12th harmonic of 12Mhz is 144MHz!  Tangent over.

20.a Setup the Fe-Pi Audio Z I2S soundcard

The Fe-Pi Audio Z v2 HAT board is a dedicated sound HAT board that uses the Raspberry Pi's built-in 
and dedicated I2S bus.  This audio-specific bus offers a more dedicated connection than say 
USB offers on the Raspberry Pi 3+ and older boards.  In addition to the connectivity improvement,
these boards also offer direct stereo LINE-IN and LINE-OUT connections for improved signals.

To get a Fe-Pi board working, you have to do more than just connect the board but it's not hard:

   1. Driver support is included since Linux kernel 4.9.13 (Raspbian Jessie / 8.x or newer).  You 
      can also get newer kernels by running "sudo rpi-update" tool

   2. You have to make a quick change to the Rpi boot process to enable the HAT board at the 
      Broadcom SOC level.  Do the following: 

         sudo vim /boot/config.txt
            Find a line that includes the word "dtoverlay"

            Add a line below it that has the following text (must be a NEW line.. do not add to 
            an existing line):


   3. Reboot the Rpi

      sudo /sbin/shutdown -r now

   4. Once the Rpi boots back up, login and run the following command to confirm the board
      is recognized:

         dmesg | grep -i fe-pi
         [    8.007458] snd-fe-pi-audio soc:sound: ASoC: CODEC DAI sgtl5000 not registered - will retry
         [    8.010476] snd-fe-pi-audio soc:sound: ASoC: CODEC DAI sgtl5000 not registered - will retry
         [    8.487658] snd-fe-pi-audio soc:sound: ASoC: CODEC DAI sgtl5000 not registered - will retry
         [    8.488264] snd-fe-pi-audio soc:sound: ASoC: CODEC DAI sgtl5000 not registered - will retry
         [    8.664517] snd-fe-pi-audio soc:sound: sgtl5000 <-> 3f203000.i2s mapping ok

   5. OPTIONAL: 
      When you enable the fe-pi-audio overlay, you're also enabling the Rpi's I2C subsystem so that alsamixer
      can control the sound chip's mixer settings.  If you have the i2cdetect utility installed (fully described 
      in the 16x4 LCD section),  run the following command and you should see the Fe-Pi on the 0x0a address as 
      "UU" meaning it's in use:

        sudo i2cdetect -y 1
             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
        00:          -- -- -- -- -- -- -- UU -- -- -- -- -- 
        10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
        20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
        30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
        40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
        50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
        60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
        70: -- -- -- -- -- -- -- --  

Once the board is recognized, go ahead and follow the next soundcard centric sections to test the board.

20.b Identify and test the USB soundcard

Anyway, to start, have your sound device connected up:

   NOTE:  If using a USB sound device, plug it into the Raspberry Pi directly
          (do NOT connect it via a USB hub as there is a known issue with the Direwolf 
          program and USB packet latencies introduced.  

   NOTE#2: If using a Syba USB-based sound device, there is a small green LED on it:

           On SOLID: device is initialized but doing nothing

           Blinks slowly:  device is recording audio

           Blinks quickly: device is playing audio

Let's now identify your sound device:

   #First, install some ALSA utilities (if not already installed)
   sudo apt install alsa-utils

   #To view all output capable sound devices:
   aplay -l 

Look for all the devices that show with a "plughw" option.  What I see is the following on 
an Rpi 3+:
   plughw:CARD=ALSA,DEV=0           <-------------- Rpi built-in audio output
       bcm2835 ALSA, bcm2835 ALSA
       Hardware device with all software conversions

       bcm2835 ALSA, bcm2835 IEC958/HDMI
       Hardware device with all software conversions
   plughw:CARD=Device,DEV=0         <-------------- USB based soundcard
       C-Media USB Audio Device, USB Audio
       Hardware device with all software conversions

   plughw:CARD=Audio,DEV=0          <-------------- Fe-Pi Audio Z I2S based soundcard
       Fe-Pi Audio,
       Hardware device with all software conversions

If you're going to be using multiple soundcards, you need to understand about ALSA soundcard
enumeration which is well detailed here:

That link will help you setup UDEV rules and what not to be able to reliably connect to the
same sound card ever time.  If you're just using one soundcard, then you won't really care 
about the enumeration stuff and that's what this doc will assume for now.

Next, if you're curious on getting more details on your soundcard, you can display the 
soundcard's native sampling rates with this command:

   sudo lsusb -vv | grep -e Audio -e tSamFreq | grep -v -e Descriptor -e bInterfaceClass

On my USB based Syba sound device, I see the following sampling rates.  The Fe-Pi Audio Z 
board doesn't seem to show anything:
   iProduct                1 C-Media USB Audio Device
        tSamFreq[ 0]        48000
        tSamFreq[ 1]        44100
        tSamFreq[ 0]        48000
        tSamFreq[ 1]        44100

That above output means this sound card can either natively support 48Khz or 44.1Khz input
sampling.  Alternatively if you have a PCI-based card (doesn't work for USB or Fe-Pi base
soundcards) or you're doing all this in a virtual machine, use:

   sudo alsa-info --stdout | grep -A 12 -e "Codec:" -e "Audio Input" 

Next test, let's record from the sound card for 10 seconds and puts a 960Kbyte file into the 
/tmp area:

   Fe-Pi-based soundcard test:
      arecord -D plughw:CARD=Audio,DEV=0 -t wav -f S16_LE -r 48000 -d 10 /tmp/test.wav

      NOTE:  There are not any LEDs on the Fe-Pi to indicate activity

   USB-based soundcard test:
      arecord -D plughw:CARD=Device,DEV=0 -t wav -f S16_LE -r 48000 -d 10 /tmp/test.wav

      NOTE:  A Syba sound device's green LED will go from a solid on, to blinking slowly
             for 10 seconds and then go back to being on solid

If this works ok, you should see the output:

   Recording WAVE '/tmp/test.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono

Next test, if you have speakers connected to the Rpi's HDMI monitor (default) or the speaker out jack 
on the Pi itself, built-in speakers, you can listen to the recorded file via  the "Default" soundcard 
output.  If there aren't any speakers connected to the Rpi, you can use tools like scp to send the 
file to another computer that DOES have speakers connected

   #First, test with a known good audio file going to either your HDMI monitor or the Rpi's built-in
   # output only sound card:
   aplay /usr/share/sounds/alsa/Front_Center.wav

You should see something like the following on the command line:

   Playing WAVE '/usr/share/sounds/alsa/Front_Center.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono

If you don't hear anything, make sure:

   - if HDMI audio, the sound is turned up on the monitor

   - if using the Rpi speaker out, use amplified speakers or a headphones 

   - Change the audio routing:
      amixer cset numid=3 1   #analog jack
      amixer cset numid=3 2   #HDMI jack

Ok, now try playing  the file you just recorded from the steps above with:

   aplay /tmp/test.wav

   # You probably didn't hear anything because there wasn't a microphone connected to the
   # sound device.  That's ok as long as it didn't give any errors

To play the same files through the newly added sound device (assuming you temporally 
connected speakers to the output jacks of that board), do:

   Fe-Pi Audio Z I2S USB sound card:
   aplay -Dplughw:CARD=Audio,DEV=0 /usr/share/sounds/alsa/Front_Center.wav
   aplay -Dplughw:CARD=Audio,DEV=0 /var/log/test.wav


   Syba USB sound card (the device's green LED will go from a solid on, to blinking slowly
             for a dew seconds and then go back to being on solid)
   aplay -Dplughw:CARD=Device,DEV=0 /usr/share/sounds/alsa/Front_Center.wav
   aplay -Dplughw:CARD=Device,DEV=0 /var/log/test.wav

If you select the wrong ALSA device, you might see the error:

     aplay: set_params:1239: Channels count non available

You can now mix and match commands and combine with the Unix "pipe" feature.  Here, we output from 
Rpi's built-in output only headphone jack and into say a Syba USB sound card:

20.c Setting up the Sound Card levels for 1200BAUD AFSK Packet Radio

This example is using a Alinco DJ-580 HT with a simple GPIO to PTT circuit similar to the 
one shown here (more about this later):

The PTT connection is connected to physical GPIO pin: 

      Rpi pin 37 (Broadcom GPIO 26) :: connect this to the PTT circuit or RS232 DB9 pin7 (this is the RS232 RTS signal)
      Rpi pin 39 ( electrical GND ) :: connect this to the PTT circuit or RS232 DB9 pin5 (this is the RS232 GND signal)

I initially set the Alinco DJ-580 volume knobs to:

      SQL knob          : 0.0 out of 10    (squelch fully open)
      Output Volume knob: 2.9 out of 10

20.d. Soundcard Mixer settings

The following audio level setting are an example of properly tuned levels for my specific setup 
(Syba and Alinco HT).  Please review the next section to better understand how to test your own

With the HT turned on and the SQL/VOL knobs set above, run the command:

   #We want to run this as root to set the main system levels
   sudo alsamixer

Alsamixer is a simple but effective ncurses user interface tool to change sound card levels.
Use your keyboar's cursor keys to navigate around in the tool.  Now, when doing mixer changes, 
it's VERY helpful to hear the level changes LIVE to know things are basically working and get 
the basic audio levels right.  To do this, try connecting a music device like your smartphone 
via it's headphone jack (hopefully yours still has one) to your chosen Rpi's sound card INPUT 
jack.  That would be done via a male to male 3.5mm TRS to TRRS cable.  

Now play a known audio files / music /etc from your smartphone and then run one of these commands
to get the Raspberry Pi to start simultaneously recording and playing the audio back:

   #  Don't forget the trailing "-" at the end of the command line (this is the STDOUT 
   #   system)

Two examples here that will record what's coming from the HT and play it out the soundcard's attached

   - Fe-pi Audio Z USB device : audio in and audio out on the Fe-Pi - this will record and playback forever
     until you hit control-c

        arecord -D plughw:CARD=Audio,DEV=0 -t wav -f S16_LE -r 48000 - | aplay -Dplughw:CARD=Audio,DEV=0 -


   - Syba USB device : audio in and audio out on the Syba - this will record and playback forever
    until you hit control-c

        arecord -D plughw:CARD=Device,DEV=0 -t wav -f S16_LE -r 48000 - | aplay -Dplughw:CARD=Device,DEV=0 -

Hopefully that worked but maybe not as more mixing settings might be required.  If so.. keep reading.  You can
also use Direwolf's calibration tones to make sounds.  If you'd like to try that, open a new terminal window 
on your Rpi (GUI terminal or CLI VTY) and run:

     cd /etc/ax25
     direwolf -x -a    :: Send alternating mark / space tones for 60 seconds
     direwolf -x -m    :: Send mark  tone (1200hz)
     direwolf -x -s    :: Send space tone (2200hz)

  - In alsamixer, use the The "F6" key is used to select the correct sound card 

       In these examples, I cover both the: 

           - Fe-Pi Audio Z v2 / WB7FHC I2S-connected sound hat: C-Media USB Audio Device

           - Syba USB-connected sound card: C-Media USB Audio Device

  OUTPUT interface

  - Press the "F3" key to select the "playback" or output interface on the sound device

     - Fe-pi / WB7FHC sound HAT:
            The Fi-Pi or the new WB7FHC clone of this HAT is a powerful I2S-connected (not USB) 
            sound device with built-in hardware output equalizers, mixers, line-in/out jacks as 
            well though it's a bit complex (has 24 controls on the Playback section of alsamixer 
            alone!).  The Fe-Pi Audio Z v2 is also a bit weird on where it puts its controls so 
            I'll describe each function:

            Electrically:  the Fe-Pi Audio Z offers stereo LINE-OUT audio jacks via the GREEN 3.5mm 
                           three-conductor TRS jack, LINE-IN via the PINK 3.5mm jack, as well as a 
                           HEADPHONE output via the BLACK four-pin TRRS jack.  I recommend to use the 
                           LINE-OUT jacks if you the audio levels can work for you (more below)

            Mixer Configuration:  The Fi-Pi offers a LOT of functionality that most sound devices 
                                  don't expose.  Below is what I reverse engineered out of it's 
                                  settings but the data sheet for it's sound chip also provides 
                                  deeper detail if you wish to read it:


            - In the alsamixer tool, hit the F3 key to see all "playback" settings.  Now use the keyboard's 
              cursor keys to move left and right and starting on the far left and going to the right.  
              You can see the full description of the control in the upper left corner of your screen under 
              the "item" label:

               * the two primary controls for OUTPUT control is PCM for course control 
                 and LineOut for fine control

               - "headphone db gain" : Audio playback via the black 4-conductor TRRS connector
                                       ** hit the "m" key to MUTE aka disable it as we are going to 
                                          use the green LINE-IN jack instead)

               - "headphone mux"     : DAC - options are "DAC" and "LINE_IN"

                         ** CRITICAL **: select "DAC" or everything coming in through "line_in" will
                         **************  go out the "headphone" jack only, bypassing everything in 
                                         your alsa mixer settings!

               - "headphone Playback ZC" : MUTE - not 100% sure what this setting really is 
                                           ** hit the "m" key to MUTE aka disable it

               - "PCM" : This is a master output volume that seems to control both the headphone
                         and line-in output.  Changes here make very large changes to the audio levels.

                             ** RIGHT CHANNEL: Set level to: 75
                             ** LEFT  CHANNEL: Set level to:  0  <--- Use the "z" key to lower to ZERO

                                 NOTE: zeroing out the left channel will help you minimize cross-talk
                                       and getting spurious multi-channel decodes of the same packet

                     Multi-channel Direwolf users / Nexus DR-X HAT users:  
                           Each channel (left / right) is for one dedicated radio.  As such, you will 
                           probably want both levels to be at say 75 to start

                     | Audio Level note:                                                              |
                     |                                                                                |
                     |     The Fe-Pi's Audio Z v2 line-out audio levels are much lower compared to    |
                     |     the headphone jack as the headphone output includes amplification. This    |
                     |     is *EXPECTED*.  If your radio's input requires higher levels than what a   |
                     |     setting the LineOut setting to 100 and the PCM level of "100", try:        |
                     |                                                                                |
                     |        - Check to see if your radio's audio IN has it's own gain control.  For |
                     |          example, Kenwood V71 and D710 radios have an input gain setting but   |
                     |          it can ONLY be set digitally via a MS Windows utility                 |
                     |                                                                                |
                     |        - You might need to switch and use the Headphone jack output instead    |
                     |          of using the LINEOUT jack.  Remember to lower the output levels first |
                     |          before switching to "headphone" so you don't overdrive anything.      |

               - "LineOut" : This is a STEREO volume for the line-out hack and it's control seems to 
                             make very minor level changes.  Depending on how you wire up the 
                             soundcard to your radio, turn up only one channel (say the RIGHT-side 
                             ** RIGHT CHANNEL: Set level to: 58
                             ** LEFT  CHANNEL: Set level to:  0  <--- Use the "z" key to lower to ZERO

                             To maximize your OUTPUT audio level, set this first to 100 and then increase
                             the PCM level to 100.  Please note that running the sound device at 100
                             can create undesired distortion.  If your running into this, please read
                             the note above about possibly switching to the headphone jack out instead.

                    Multi-channel Direwolf / Nexus DR-X HAT users:  
                          Each channel (left / right) is for one dedicated radio.  As such, so you will 
                          probably want both levels to be at say 58 to start

               - "Mic"    : not sure why this is here since we're in the PLAYBACK section of the mixer
                            ** Set to 0  (you cannot MUTE this setting)

               - "Capture Attenuate" : adds a -6db attenuator on the microphone input (not sure why
                                       this is in the playback section
                                       ** hit the "m" key to MUTE aka disable it

               - "Capture Mux" : determine what input port to listen to : options are "MIC_IN and LINE_IN"

                    *IMPORTANT*    Use the up/down arrow keys to select "LINE_IN"
                    ***********    - not sure why this is here since we're in the PLAYBACK section of the mixer

               - "Capture ZC" : not 100% sure what this is
                                ** hit the "m" key to MUTE aka disable it

               - "AVC"        : not 100% sure what this is
                                This control has some interaction with the "AVC hard limiter" control
                                ** leave at default: 0 or hit the M key to MUTE it **

               - "AVC hard limiter" : not 100% sure what this is
                                      This setting is used when "Digital Input Mux" is set to DAP.
                                      When "AVC" is set to 0 and this setting it set to to "m" for MUTE, 
                                      all DAP-enabled audio playback stops
                                      ** leave at default: 0

               - "AVC integrator response" : not 100% sure what this is
                                             ** leave at default: 33

               - "AVC max gain : not 100% sure what this is
                                 ** leave at default: 0

               - "AVC threshold : not 100% sure what this is
                                  ** leave at default: 0

               - "BASS 0" : Use when "Digital Input Mux" is set to DAP
                            Sound Equalization: Deep Bass
                            ** leave at default: 49

               - "BASS 1" : Use when "Digital Input Mux" is set to DAP
                            Sound Equalization: Mid Bass
                            ** leave at default: 49

               - "BASS 2" : Use when "Digital Input Mux" is set to DAP
                            Sound Equalization: Midrange
                            ** leave at default: 49

               - "BASS 3" : Use when "Digital Input Mux" is set to DAP
                            Sound Equalization: Low treble 
                            ** leave at default: 49

               - "BASS 4" : Use when "Digital Input Mux" is set to DAP
                            Sound Equalization: High Trebble   
                            ** leave at default: 49

               - "DAP Mix Mux" : not 100% sure what this is (options: ADC, I2S)
                                 ** leave at default: ADC

               - "DAP Main Channel" : Volume control when "Digital Input Mux" is set to DAP
                                       ** leave at default: 50

               - "DAP Mix Channel" : Mix control to add in DAP audio control when "Digital 
                                     Input Mux" is set to DAP. Depending on what the "DAP 
                                     Mux Channel" is set it, the level of 0, starts with
                                     that signal (say ADC) and as you increase the level, 
                                     it adds in the other DAP controlled signal (say I2S) 
                                     which adds both volume and delays 
                                     ** leave at default: 0 **

               - "DAP Muxl" : not 100% sure what this is (options: ADC, I2S)
                                     ** leave at default: ADC **

               - "Digital Input Mux" : not 100% sure what this is (options: I2S, Rsrvd, DAP)
                                       ** leave at default: I2S

                                       NOTE: there seems to be some audio delay (buffering) 
                                             between the I2S and DAP selection - the "I2S" setting
                                             seems to offer less latency

                                       NOTE2: the DAP option seems to alter the audio playback with 
                                              a "brighter" or higher frequency audio output with 
                                              a lot more mid-range sound.  Do NOT use

                                      NOTE3: The DAP setting enables the BASS 0-4 parameters 
                                             controls to change the various bass, mid, low trble, and
                                             high treble levels

     - Syba / CM108 based USB sound device
       The Syba USB-connected sound device is a reasonable quality sound device that provides consistent 

       Press the F6 key an select "C-Media USB Audio Device" and then F3 to see the Playback settings

         - Set the "speaker" level at to 00 (left) : 19 i(right) depending on on how you've wired your 
           sound device your radio.  Here, I am recommending to set the LEFT channel to "0" output and the
            RIGHT channel to a level of "19".  Use the "z" to LOWER the left channel's level.  Also ensure 
            the output is "activated" by ensuring that this slider shows "00' in the bottom box of this 
            specific vertical slider.  If it shows "MM", hit the "m" key to UN-MUTE.

         - Set the "Mic" (this is the monitor feature if it's shown there at all) to MUTED by 
            hitting the "m" key (that's shown as MM in the bottom box of the vertical slider) 

         - Auto Gain control - (if shown on your specific sound card) is selected (that's 00)   

  INPUT interface

  - Ok, lets move on to the INPUT side of the mixer controls.  Press the "F4" key in alsamixer to select the 
    "Capture" or Input interface on the sound device

     - Fe-pi / WB7FHC sound HAT:

            Electrically:  the Fe-Pi Audio Z v2 offers both LINE-IN audio jacks via the pink 3.5mm three-conductor 
                           TRS jack or MICROPHONE via the black four-pin TRRS jack.  I recommend to use 
                           the LINE-IN jack

               - "mic db gain" : Audio input level via the black 4-conductor TRRS headphone connector
                                 Default is 0
                                 ** Leave to default: 0 as we are going to use the green LINE-IN jack instead)

               - "capture" : Primary audio input level control
                             Default is 80 
                             * CRITICAL *:  Hit the SPACE BAR to make this item show "L R CAPTURE" in RED letters

                               ** RIGHT CHANNEL: Set level to: 80
                               ** LEFT  CHANNEL: Set level to:  0  <-- Use the "z" key to lower this to 0

                    Multi-channel Direwolf / Nexus DR-X HAT users:  
                         Each channel here is one of the two radio connections on the Nexus board (left or 
                         right).  As such, so you will probably want both levels to be non-zero

               - "AVC integrator response" : Same control as on the Playback control area
                                             ** leave at same value as on playback screen: 33 **

               - "AVC max gain : Same control as on the Playback control area
                                 ** leave at same value as on playback screen: 0 **

               - "AVC threshold : Same control as on the Playback control area
                                  ** leave at same value as on playback screen: 0 **

               - "BASS 0" : Same control as on the Playback control area
                            ** leave at same value as on playback screen: 49 **

               - "BASS 1" : Same control as on the Playback control area
                            ** leave at same value as on playback screen: 49 **

               - "BASS 2" : Same control as on the Playback control area
                            ** leave at same value as on playback screen: 49 **

               - "BASS 3" : Same control as on the Playback control area
                            ** leave at same value as on playback screen: 49 **

               - "BASS 4" : Same control as on the Playback control area
                            ** leave at same value as on playback screen: 49 **

               - "DAP Main channel" : Same control as on the Playback control area
                                      ** leave at same value as on playback screen: 50 **

               - "DAP Mix Channel: : Same control as on the Playback control area
                                     ** leave at same value as on playback screen: 0 **

     - Syba / CM108 based USB sound device
         - "Capture" to a level of 31 

         - make sure you can see the red word "Capture" by using the space bar

  - The "F5" key to select "All controls"

      - Some specific sound cards don't show any specific AGC (Automatic Gain) controls in 
        either the "F3 - playback" or "F4 - capture" screens but they show them here so it's 
        best to double check here

  - Hit the Escape key to exit and leave the current audio level settings in place

| CRITICAL:  Save your mixer settings                                                    |
|                                                                                        |
| Once you have the soundcard initially tuned up, save the soundcard settings and levels |
| as the root user since we'll be running direwolf as root:                              |
|                                                                                        |
|      sudo alsactl store                                                                |
|                                                                                        |
| Running this command will store all of these mixer settings into the                   |
| /var/lib/alsa/asound.state file                                                        |

20.e. Confirm Clean Silence from the Soundcard

This check is needed as a *lot* of USB sound devices will pass on noise from dirty power 
sources through your radio in the form of dirty audio.  Noisy audio will severely harm the 
software TNC's digital signal processing.  To properly check for this, do the following:

     a. Create an empty (and noise free) 15 second WAV file - output file should be about 240kbytes

        #RECOMMENDED: Recording from the soundcard interface while nothing is connected to it  

           Fe-Pi Audio Z v2-based soundcard test:
              arecord -D plughw:CARD=Audio,DEV=0 -t wav -f S16_LE -r 48000 -d 15 /tmp/15sec-silence.wav

              NOTE:  There are not any LEDs on the Fe-Pi to indicate activity

           USB-based soundcard test:
              arecord -D plughw:CARD=Device,DEV=0 -t wav -f S16_LE -r 48000 -d 15 /tmp/15sec-silence.wav

              NOTE:  A Syba sound device's green LED will go from a solid on, to blinking slowly
                     for 10 seconds and then go back to being on solid

        #NOT Recommended - This recording approach function might be broken with recent versions of 
                           Raspbian where it creates a loud clicking sound on recording

              arecord -c 2 -d 15 -f S16_LE -r 48000 -t wav -D null /tmp/15sec-silence.wav

        You should see the following output:

           Recording WAVE '/tmp/15sec-silence.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo

     b. Temporarily disconnect the packet radio from the soundcard's chosen playback jack, 
        connect in a pair of headphones to the soundcard, and listen to the playback the silence 
        sound file:

           Fe-Pi-based soundcard test:
           aplay -Dplughw:CARD=Audio,DEV=0 /tmp/15sec-silence.wav

           USB-based soundcard test:
           aplay -Dplughw:CARD=Device,DEV=0 /tmp/15sec-silence.wav

        You should see the following output:
           Playing WAVE '/tmp/15sec-silence.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo

        Carefully listening to the audio, you should first hear the noise floor increase a little bit 
        in the headphones but:

             - There should be no whine, buzzing, or clicking.  The audio should be completely noise 
               free.   If it's NOT, you must work to improve that audio.. check the output mixer settings, 
               try a different sound device, etc.

          NOTE:  If trying to use the NUL approach above, Raspbian Buster(06/30/19) and Jessie (08/29/17)
                 seems to create a very pronounced TICKING sound on the created recordings.  This is created 
                 on a both a Raspberry Pi and an X86 Centos box.  Inspecting the file in Audacity shows the 
                 ticks so I think there is a bug in the "arecord" program,   

20.f - Setting the right audio levels for AFSK packet tones

Now that you're familiar how to change the levels on the soundcard side, I recommend to
read and then RE-READ: 

Read the "The No-Test-Equipment Packet Adjustment System" section to learn how to 
tune your packet signal levels.  The "no-Test-Equipment packet adjustment system" section 
will get your radio's AFSK1200 levels to be pretty close to perfect.  Remember, the adjusting these 
levels is a COMBINATION of both the levels coming in/out of your radio as well as the  the Raspberry 
Pi's soundcard.  You MUST adjust both components to have and effective and functioning packet station.  

   NOTE:  While the Febo approach work pretty well for 1200bps AFSK signals, it WON'T work very well
          for 9600bps G3RUH FSK signals.  You'll need more accurate tools than your ears!

To send calibration tones from Direwolf, you can use the 
series of commands:

     cd /etc/ax25
     direwolf -x -a    :: Send alternating mark / space tones
     direwolf -x -m    :: Send mark  tone (1200hz)
     direwolf -x -s    :: Send space tone (2200hz)

Once you have the soundcard levels tuned, save the new soundcard levels:

   sudo alsactl store

It's worth noting that if you aren't going to be using this document's startup 
scripts, be sure to use:

   sudo alsactl restore

in your scripts to reliably restore the soundcard levels.  The level settings are
stored in /var/lib/alsa/asound.state when run with "sudo".

21. BEWARE of the soundcard and radio microphone bias DC voltage

IMPORTANT: Microphone Bias Voltage:
Before you connect any radio to your soundcard, it's CRITICAL that you check to 
see if:

   1) Your soundcard's input jack does or doesn't provides a "bias" voltage 
      for condenser-type microphones (microphone jacks probably do; line-out ports
      probably don't)

   2) Your radio's microphone jack does or doesn't provide a "bias" voltage for
      condenser-type microphones (it probably does)

On my Syba USB soundcard, it puts out +5.0v on the tip of the mono-style microphone 
jack.  I've checked with the CM108 schematics and programming API and this voltage 
cannot be turned off via software.  As such, it's CRITICAL that you connect a 10uF 
capacitor between the soundcard's microphone input and your radio's audio output.  
A ceramic capacitor is preferred but an electrolytic capacitor will work fine and   
this will isolate this DC voltage offset.

        if you use an electrolytic style cap, make sure the POSITIVE lead is 
        connected to the sound-card side (the site that's providing the voltage)

Once you've checked the soundcard microphone side, now check the radio's microphone
jack as well and if it also creates a bias voltage, it too will need a capacitor.

22. Choosing GPIO pin for the radio PTT line

To interface the Rpi to your radio, you need to select which GPIO pin on the Rpi's 
header your going to use to key up the radio.  

It's VERY important to note that some GPIO pins on the Raspberry Pi are pulled HIGH (+3.3v) by 
default but it can depend on your Raspberry Pi version as well as it's kernel version.  This 
is obviously complicated but it's important to understand this because by using one of these pins, 
your radio won't key up when your Raspberry Pi is rebooting or is down.  Very important!

You can read more about this here:

On the Raspberry Pi 3+ and Rpi v2, these GPIO pins are initialized HIGH:
   GPIO 2
   GPIO 3
   GPIO 4 
   GPIO 7
   GPIO 8 
   possibly GPIO 14 too

You can learn more about what pins are initiated HIGH here:

   Raspberry Pi Model A, B, B+, the Compute Modules, and the Raspberry Pi Zero
   ARM Peripheral spec sheet
   -- -->

   Newer Raspberry Pi versions and their specific data sheets:

If you were to use one of these pins with the simple PTT transistor circuit mentioned 
above/below, you'd find that whenever your Rpi is rebooting or is powered yet off, it 
would leave your radio keyed up (PTT asserted)!  That's very BAD!  So... I advice to 
NOT use one of those GPIO pins mentioned above.

Ok, then what GPIO pins should you use?  Well, the Rpi line of SBCs can have it's 
various GPIO pins connected to several other "alternative" functions available in the 
Broadcom SOC ASIC depending on it's pin "mode".  Unfortunately, there are *LOTS* of 
incorrect information out on the Internet on this topic as many sites don't show the 
alternative modes for each of the pins.  

Below is one of the better GPIO pin diagrams out on the web showing the different pins 
and their various modes.  Pay specific attention to the different *colors*:

   Rpi pinout graphic (doesn't include the new Rpi 4 alternative layouts if you care)

      For those of you running the full desktop version of Raspberry Pi OS (not the lite)
      version, try running the command "pinout" on the command line to see an Ncurses
      diagram of your GPIO pins

   Here are some other good URLs to check out for different overlay maps on different models
   of Raspberry Pi (official documentation):


     - Raspberry Pi B+ and Raspberry Pi-2:

Per the Direwolf documentation, it has the following recommendations:

   Raspberry Pi physical pin 11 - Broadcom GPIO 17
   Raspberry Pi physical pin 15 - Broadcom GPIO 22
   Raspberry Pi physical pin 16 - Broadcom GPIO 23
   Raspberry Pi physical pin 18 - Broadcom GPIO 24
   Raspberry Pi physical pin 22 - Broadcom GPIO 25

   The Raspberry Pi 4, 3+, 3, 2, Zero-W, Zero, and A/B+ have the larger 40pin connector 
   with additional GPIO pins:

   Raspberry Pi physical pin 29 - Broadcom GPIO  5
   Raspberry Pi physical pin 31 - Broadcom GPIO  6
   Raspberry Pi physical pin 32 - Broadcom GPIO 12
   Raspberry Pi physical pin 33 - Broadcom GPIO 13
   Raspberry Pi physical pin 35 - Broadcom GPIO 19
   Raspberry Pi physical pin 36 - Broadcom GPIO 16
   Raspberry Pi physical pin 37 - Broadcom GPIO 26  <----- My PTT recommendation
   Raspberry Pi physical pin 38 - Broadcom GPIO 20
   Raspberry Pi physical pin 40 - Broadcom GPIO 21

As such, I'm using the following GPIO connection for the PTT control on my Rpi that don't 
have any other alternative mode functionality:

    Rpi pin37 (Broadcom GPIO 26) :: connect this to the PTT circuit 
    Rpi pin39 ( electrical GND ) :: connect this to the PTT circuit

BTW, there is an optional feature in Direwolf to set a GPIO pin when a valid 
packet HDLC signal is detected (this is called the DCD indicator).  I recommend you 
connect an LED and a 470 Ohm resistor to a GPIO pin to use it.  Its a very helpful 

So I'm using the following different GPIO pins on my Rpi3 for various uses:

    Direwolf PTT signal:
      Rpi pin 37 (Broadcom GPIO 26) :: connect this to the PTT circuit
      Rpi pin 39 ( electrical GND ) :: connect this to the PTT circuit

    Direwolf DCD signal:
      Rpi pin 33 (Broadcom GPIO 13) :: connect to cathode of LED (short lead / smaller metal inside LED)
      Rpi pin 34 - GND              :: connect to 470 Ohm resistor and other side of resistor to 
                                       anode of LED (long lead / larger metal inside LED)

    PiShutdown button:
      Rpi pin 18 (Broadcom GPIO 24) :: connect to 10k resistor, connect other side of resistor to one 
                                       side of a momentary switch
      Rpi pin 20 - GND              :: Connect to other side of momentary switch

    I2C for LCD
      Rpi pin 3 (I2C Data) 
      Rpi pin 5 (I2C CLK) 

    I2S buss for Fe-Pi
      Rpi pin 33 (I2S clock)
      Rpi pin 38 (I2S buss audio input)
      Rpi pin 40 (I2S buss audio output

    PWM fan control
      Rpi pin 40 (I2S buss audio output :: PWM fan control -- this is a potential conflict)

   | Reminder:                                                                       |
   |                                                                                 |
   |   It's critical that whatever username runs the direwolf program, that user is  |
   |   given the required Unix permissions to access the GPIO pins.  This is covered |
   |   in Section 3.1.b using the "usermod" Unix command.  Without this, Direwolf    |
   |   will simply just not key up your radio and you'll never know why!             |

23. Connecting your Radio to the Soundcard with tips

The choice of which radio to use for packet radio depends on several factors:

   1. Your budget
   2. Do you want 1200bps packet (APRS and most packet) or faster (2400bps, 4800bps, 9600bps, etc)
   3. How reliable do you want your station
   4. How much hair do you want left on your head after you complete this project

Generally speaking, I recommend to ONLY use a mobile radio running at 25w with a 6pin DATA jack on 
the rear of the radio.  This increases your budget (item #1 above) but it dramatically helps
you on items #2, #3, and #4 above!   Some possible recommendations can be found here:

Take that list with a gain of salt as it also mentioned Baofeng radios which are notorious to
cause all kinds of issues with packet.

Anyway, on to connecting your chosen radio to your soundcard.  There are multiple ways to connect 
the RPi to your radio's PTT line depending on the radio, etc.  An ideal solution is to use an 
opto-isolated circuit such as:

This would be easily connected to a Raspberry Pi's GPIO pins.  Alternatively, I've used
this simple transistor circuit with my Kenwood TH-F6A HT::

   | CRITICAL NOTE:                                                                        |
   | --------------                                                                        |
   | Every radio is different and the above connections will need to be changed to         |
   | conform to your specific radio.  For example, I've since moved to using a Alinco      |
   | DJ-580 and it's PTT connections are RADICALLY different than the Kenwood.  Unless you |
   | modify the connections to suit your radio (ensure key DC blocking capacitors are in   |
   | place as mentioned above), you run the very real risk of damaging your USB sound card |
   | *and* the radio itself!                                                               |

Other potential options:

   - Use the Easy Digi isolation kit which includes an opto-isolator for PTT which also includes
     audio isolation transformers.  

     This kit solution works well for HF and 1200bps AFSK packet but it will NOT work for say 
     4800bps QPSK or 9600bps G3RUH FSK packet (or faster) as the transformers limit the audio 
     passband bandwidth too much.

   - Another option to consider is to build the time-limited PTT circuit that's found in Direwolf's
     Raspberry-Pi-APRS.pdf doc found at

     This is an extra-safe design as the design itself will prevent any hung transmitter
     situations due to including a 555 timer!

   - A nicer solution is to get a nice PCB version of WB2OSZ's circuit above which is 
     available for order here as designed by James N7SET:

   - You could then put either these two circuits or the little PCB on a Raspberry Pi proto HAT:

     and you'll then have a very slick setup that you can easily move from Raspberry Pi to 
     Raspberry Pi!

   - Signalink USB sound devices

        These devices are very popular with HAMs as they can work with many different radio combinations.
        All Signalink units include isolation transformers for mitigating ground loops, galvanic hum, etc.
        Older generation Signalink units used transformers that block WIDE modes like G3RUH 9600bps FSK packet
        and VARA Wide.  Overall, I find the Signalink units overly expensive for what they are and their
        pseudo-VOX PTT solution and the variable TX delay knob can create a lot of issues

   - One of the more ultimate solutions are:

        Nexus DR-X kit with a Fe-Pi Audio Z or compatible sound card:
          - dual radio support, also includes a RTC clock and a wide voltage converter for powering the Rpi

        NW Digital DRAWS (complete HAT):
          - dual radio support, also includes a GPS with PPS support, RTC clock and a wide voltage converter 
            for powering the Rpi, and extender header with some GPIO pins and two ADC inputs

Now that you've created the required radio interface cable to connect the radio to sound the 
soundcard CONSIDERING:

   - You've ensured that the microphone jacks on both the radio AND the soundcard don't have 
     a DC bias voltage (above).  If they do, it's CRITICAL that you install a small DC blocking 
     capacitor on both lines to remove those voltages

   - On the radio, make sure the squelch is all the way open (static noise all the time) and 
     that the output speaker volume on the radio is LOW (but not off) to start off with

   - If you're using an HT type radio, make sure that you disable any "RX power saver" as 
     well as the Automatic power off features of the radio.  If you don't disable both of these, 
     the radio will either miss part of the beginning packets and/or have the radio go to 
     sleep on you!

24. Compile, Configure, and Test Direwolf

Assuming your external SDD/HDD storage is still mounted per the previous document section, lets 
now compile up the newest version of Direwolf!

  NOTE:  If you intend to run a remote Direwolf iGate that might have unreliable Internet connectivity), 
         it's highly recommended to setup an RTC (real time clock) to let Direwolf properly timeout
         old packets.  Please see the RTC section later in this document on how to do this

  a. First install the required dependencies to build the minimal Direwolf 

        sudo apt install libasound2-dev unzip libudev-dev

     If you want to include GPS support for later support of connecting an external GPS for
     position, date/time, etc, then add the following additional packages:

        sudo apt install gpsd libgps-dev

     | IMPORTANT:                                                                                 |
     |                                                                                            |
     |      Impacts Raspbian Buster and Stretch:                                                  |
     |                                                                                            |
     |      If you disabled IPv6 on your system per the section above, you might run into an      |
     |      error installing or updating gpsd.   This is a known bug per:                         |
     |                                                                                            |
     |                          |
     |                                                                                            |
     |      To work around this, do the following (per the bug report):                           |
     |                                                                                            |
     |         Edit the /lib/systemd/system/gpsd.socket file and remove or comment out the line:  |
     |                                                                                            |
     |            ListenStream=[::1]:2947                                                         |
     |                                                                                            |
     |         then run to retry the package config:                                              |
     |                                                                                            |
     |            sudo apt -f install                                                             |

  b.  Enter the compiling area and make it writable by users in the "adm" group

         cd /usr/src/archive/Rpi-scratch/
         mkdir direwolf
         cd direwolf

  c. Get a copy of the Direwolf sources
     You have two choices here to the version of Direwolf:

        - RECOMMENDED: The mainline release version of Direwolf is v1.6 as of 01/01/21.  This new version
          has many new features such as FX.25, AIS Reception on appropriate marine frequencies, and a ton 
          of fixes and improvements including known color issues with it on newer Linux distributions 
          (Raspbian Buster).  You can find it and any newer mainline releases at:


        - The "dev" or development branch of Direwolf is v1.7 as of 11/29/20.  This development release is 
          very new and while it does offer some interesting improvements over v1.6 today, it's NOT stable.  
          As the "dev" branch develops, I'm sure my recommendation will swing back to the Dev branch for 
          those who need / want to try it.

     c.1: RECOMMENDED: Get the Release (master) branch version
        | RECOMMENDED:                                                                              |
        |                                                                                           |
        |   The newest Direwolf code in the "master" branch is v1.6 which now uses the cmake build  |
        |   system.                                                                                 |

            git clone
            cd direwolf
            git branch -r
            git checkout master
            cd ..


     c.2: NOT RECOMMENDED: Get the DEV branch version
        | NOT RECOMMENDED : Advanced users only :                                                 |
        |                                                                                         |
        |   The newest Direwolf code in the DEV branch is Direwolf v1.7.  This upcoming version   |
        |   which will eventually become the next major release currently has some interesting    |
        |   new features and fixes but might NOT be stable at this time                           |

            git clone
            cd direwolf
            git branch -r
            git checkout dev
            cd ..

24.a. Direwolf Dead TX airtime workarounds

     If you're using a USB based sound device (not an I2S-based sound device like a Fe-Pi Audio Z v2) 
     on older Raspberry Pi model (RPi 3B+, 3, 2, Zero-W, Zero, 1, but NOT the RPi4 or newer Raspberry 
     Pi hardware), there is a known issue of Direwolf transmitting random amounts of "dead airtime" 
     before actual modem sounds play over the air.  You can read more about this Raspberry Pi USB DWC 
     bug at:

     To summarize the issue, the Linux kernel in Raspberry Pi / Raspbian OS versions has a modified USB stack
     that has a specific USB bug impacting sound card devices.  This bug has been fixed in bleeding edge kernels
     (newer than 5.4.70) but this is going to take until Jan 2021 or later to come as a Raspberry Pi OS update.

     NOTE: It was previously mentioned in this doc and no longer recommended that to work around this "Dead TX 
           airtime" issue, older Rpi HW owners could use a work-around using the legacy OSS sound system (the 
           Linux sound server before ALSA).  Unfortunately, this legacy OSS support was accidentally disabled 
           from the Raspberry Pi OS kernel (was recently re-added in (see URLs above) but going the OSS route
           is still NOT recommended.

     There are several options to address this USB-only issue:

        Option #1: RECOMMENDED: Use the DWC2 USB kernel module for users using a USB sound device:
                   Rpi 0, 1, 2, 3, 3+ users running Raspberry Pi OS "Buster" version can try using the alternative 
                   "DWC2" USB stack which the default USB stack used by the Rpi4 new hardware.  To try this, it's 
                   first recommended to first make a backup of your SD card (a method is recommended in the appendix 
                   of this doc).  Once you're ready, edit the /boot/config.txt file and find one of the multiple 
                   possible lines starting with "dtoverlay".  Add the following line:

                      sudo vim /boot/config.txt

                   Once added, reboot your Raspberry Pi, log into your pi and run the command:

                      lsmod | grep dwc2

                  to confirm you're using the new USB kernel module.  If this last command didn't find it
                  loaded, you've done something wrong and you need to re-check your work, fix the issue, and
                  again reboot.

        Option #2: Regain OSS support via a bleeding edge kernel version:
                   Users running Raspberry Pi OS Buster, Stretch, and Jessie can switch to using the 
                   bleeding edge kernels using the "rpi-update" tool to get both the DWC_OTG fixes 
                   finally solve ALSA sound issues as well as bring the return of the OSS sound system.  
                   Once the 5.4.70 kernel for the Buster OS comes to a mainline release (~Jan 2021), 
                   Raspberry Pi Buster users will no longer need the bleeding edge kernels.  The Stretch 
                   and Jessie distros will NEVER get these fixes in a mainline kernel update so you'll
                   need to stick with the bleeding edge kernels.  Please make a backup of your SD card 
                   before you try this.

        Option #3: Use the Legacy OSS sound stack:
                   It seems that the original Linux sound system (OSS) is not affected by this DWC 
                   USB issue and thus, fixes the issue.  The problem here is that in modern Raspberry Pi
                   OS versions, this option was accidentally disabled in the mainline kernel.  If users want 
                   to go this route, you will either need to use a bleeding edge built kernel mentioned in 
                   Option #2 above or compile your own kernel.  Building a new kernel isn't too hard
                   and there are many guides out there on the Internet how to do it but it does take time.
                   If you've never built a kernel, I recommend this as you'll learn alot.

        NOT RECOMMENDED:  Option #2 / Option #3: OSS workaround for kernels that have the OSS support included 
                          for Direwolf release 1.6 or newer:
           If you're curious: read for more information on this change

           OSS Option #1: create and apply a simple patch 
           a.1.a - Enter the Direwolf 1.6 sources directory

              cd /usr/src/archive/Rpi-scratch/direwolf/direwolf

           a.1.b - create the file "direwolf-cmake-oss.patch" and put the following contents into it:
--- CMakeLists.txt.orig 2019-12-22 09:19:09.329897884 -0800
+++ CMakeLists.txt      2019-12-22 09:19:27.828061636 -0800
@@ -202,7 +202,7 @@

-  find_package(ALSA REQUIRED)
+  find_package(ALSA)

           a.1.c Apply the patch with:

                  patch -p0 < direwolf-cmake-oss.patch

           OSS Option #2: NOT RECOMMENDED - manually edit the CMakeLists.txt file in the root Direwolf source code directory 
           a.2.a Enter the Direwolf 1.6 sources directory

              cd /usr/src/archive/Rpi-scratch/direwolf/direwolf

           a.2.b create the file direwolf-cmake-oss.patch and put in the following contents:

              find the line:
              find_package(ALSA REQUIRED)

             change it to read:

     A.3 NOT RECOMMENDED: OSS workaround for kernels that have the OSS support: Direwolf release 1.5 or older:

           Edit the Makefile.linux file found in the root Direwolf source code directory and comment out 
           (aka add the # character front of the line).  Edit the Makefile.linux file in the root Direwolf source code 
           directory and find the line:
           alsa = 1

           Change it to read:
           #alsa = 1

  24.B.  Check the libgps version
     To properly identify package dependencies, we need to be aware which version of the libgps package
     you have installed.  Generally speaking, this is what you should see:

                - The "Sid" aka "unstable" version of Raspbian versions it's libgps library "libgps26"
                - The "Bullseye"  version of Raspbian versions it's libgps library "libgps28"
                - The "Buster"  version of Raspbian versions it's libgps library "libgps23"
                - The "Stretch" version of Raspbian versions it's libgps library "libgps22" 
                - The "Jessie"  version of Raspbian versions it's libgps library "libgps21" 
                - The "Wheezy"  version of Raspbian versions it's libgps library "libgps21" 

                Because of this, the resulting Direwolf package built for one OS version is not usable for 
                the other OS version. You can run the following command to see what version is installed on 
                your Rpi:

                    dpkg -l | grep libgps

  Prepare to compile Direwolf:
  24.c.1 RECOMMENDED: Direwolf 1.6 AND LATER VERSIONS ONLY: Prep the system and sources

        #Install cmake 
        sudo apt install cmake 

        #Just to make sure you're in the right dir
        cd /usr/src/archive/Rpi-scratch/direwolf/direwolf/

        # Review the CMakeLists.txt file and make sure it has the correct version of libgps specified.
        #  If it doesn't, update the the string "libgps23" found in the following line:

        vim CMakeLists.txt
        SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libasound2,libgps23")

        # Create the Cmake build area
        mkdir build
        cd build

        # Time to build Direwolf and you have a choice based on the above dead-airtime workarounds
        # mentioned above:

           # RECOMMENDED - build with ALSA sound support (default)
              #  If you're compiling in ALSA support (only use on RPi4 or new newer Raspberry Pi hardware, 
              #  DWC2 kernel module enabled Pis (read more above), using non-USB audio devices, 
              #  or running Direwolf on X86-based machines
              #NOTE: Yes, these two trailing periods on the command below ARE are required
              cmake ..

              #The above command should complete without any errors


           # NOT-RECOMMENDED: OSS (non-ALSA) based audio workaround: 
           #        If you intend to use the legacy OSS sound support for using Direwolf with USB-based sound 
           #        devices on older Raspberry Pis like RPI 3B+ or older hardware (not required X86 based computers):

  OPTIONAL: Prepare Stage #2 to compile Direwolf:
     You can OPTIONALLY update the APRS object database before compiling

     Direwolf v1.6 and newer ONLY:
        # yes, this is a "make" command and not Cmake
        make update-data


     Direwolf 1.5 AND PREVIOUS versions only: 
        #Just to make sure you're in the right dir
        cd /usr/src/archive/Rpi-scratch/direwolf

        #update all the symbol data, etc (yes, this is a Make command and not Cmake)
        make tocalls-symbols

  ALL Direwolf versions: Compile Direwolf (all Direwolf versions and all TX-dead airtime work arounds):
  24.d. Compile Direwolf (all versions or work arounds)

     Let's now compile the Direwolf sources using all available cores on your Raspberry Pi.
     If you are using an Rpi Zero-W, Zero, or v1, use "-j2" instead'

       d.1 For Direwolf 1.6 and newer versions using Cmake on a 4-core Raspberry Pi (Pi4, CM4, 3+, or 3):

          make -j8


       d.2 For Direwolf 1.6 and later using Cmake (on a 1-core Raspberry Pi2, 1+, 1, Zero-W, or Zero):

          make -j2

       d.3  For Direwolf 1.5 or previous versions:

          make -f Makefile.linux -j8

  Direwolf Packaging:

  24.e. Package and install Direwolf (all versions and permutations of Direwolf installs mentioned in this chapter)

     e.1 If you already had a /etc/ax25/direwolf.conf file installed, lets make a backup of it just in case.
         If this is a fresh install, you can just skip this step
            sudo mkdir /etc/ax25/Old
            sudo cp /etc/ax25/direwolf.conf /etc/ax25/Old/direwolf.conf-`date +%m%d%y`

    e.2  Direwolf 1.5 AND OLDER VERSIONS ONLY

            I recommend to use the checkinstall program to both package Direwolf and install the resulting package
            instead of just using the too-simplistic "make install" approach.  It's not a perfect tool but it works
            well enough:

               NOTE:  The default version of checkinstall included with Raspbian is NOT compatible with Cmake-based 
                      projects such as Direwolf 1.6 per .  This issue
                      is fixed in checkinstall Git branch or v1.6.3 or newer but Raspbian doesn't have that version.

           Since you have compiled Direwolf for Raspbian directly and are NOT using the pre-built Raspbian 
           repos, you need to delete the RPM spec file to work around a known bug in the checkinstall program:

              cd /usr/src/archive/Rpi-scratch/direwolf/direwolf/
              rm direwolf.spec

           Next, run the following commands:

               These steps are only required for Direwolf v1.5 installs using the checkinstall tool:
               sudo mkdir -p /usr/share/doc/direwolf/examples
               sudo ln -s /usr/share/doc/direwolf /usr/share/direwolf
               sudo mkdir -p /usr/share/direwolf/pixmaps
               sudo mkdir -p /usr/man/man1

           Ignore any warnings/errors that might be given

    24.f All Direwolf versions: Confirm the real version of Direwolf you just compiled:

         - Direwolf 1.6 and NEWER users:
            cd /usr/src/archive/Rpi-scratch/direwolf/direwolf/
            grep -r "direwolf_VERSION_" CMakeLists.txt
            As of 10/28/20, the main Direwolf release version is "1.6.0" as shown on the top three lines:
            set(direwolf_VERSION_MAJOR "1")
            set(direwolf_VERSION_MINOR "6")
            set(direwolf_VERSION_PATCH "0")
            set(direwolf_VERSION_SUFFIX "")
            (you can ignore the other lines in this output)


         - Direwolf 1.5 and OLDER users:

            grep "VERSION" version.h

         - Direwolf 1.7 Dev branch users:

            If you built the "dev" branch of any Direwolf version, there is one more field to check for:

               grep "Dire Wolf DEVELOPMENT" src/direwolf.c
                  As of 8/8/20, it shows:
                  dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "A", __DATE__);

              That means this is Direwolf version 1.7 Beta test version "A"

    24.g Let's package up and install the new Direwolf:

              | INFO: Users coming from Direwolf 1.5 and upgrading to Direwolf v1.6:                                    |
              |                                                                                                         | 
              |    Direwolf 1.6 users:                                                                                  |
              |       Direwolf 1.6 moved to the Cmake system which is incompatible with the checkinstall tool as it     |
              |       currently SEGFAULTS when trying to process the build process:                                     |
              |                                                                                                         |
              |          Makefile:526: recipe for target 'cmake_check_build_system' failed                              |
              |          make: *** [cmake_check_build_system] Segmentation fault                                        |
              |                                                                                                         |
              |    This checkinstall issue was mentioned in and has been   |
              |    fixed but I am now recommending to use the native Cmake method of packaging.                         |

        Pick ONE of the following approaches:
          | NOTE:                                                                                                  |
          |       I know offering multiple options here makes things more confusing but different users might have |
          |       different needs so I give the options here.  Please contact me if you need help understanding    |
          |       and I'm trying to make sure this wording is as strait forward as possible                        |

           g.2.a  Direwolf 1.6 and Newer releases:

                 Run the following command to package and install the newly compiled Direwolf code:

                    cd /usr/src/archive/Rpi-scratch/direwolf/direwolf/build 
                    cpack -G DEB
                    sudo apt install ./direwolf-1.*.deb 

                    #Make a backup copy of the deb for any future use
                    sudo cp direwolf-1.*.deb /usr/src/archive/Rpi-scratch/direwolf/

                 It's recommended to mark the Direwolf package as HOLD so future Raspbian OS updates won't accidently
                 mess with it (downgrade it, etc):

                      sudo apt-mark hold direwolf

                   At any future time that you want to upgrade or even downgrade Direwold, you'll first need
                   remove the package hold with:

                      sudo apt-mark unhold direwolf

                 Next up: File locations: 
                      I choose to put the direwolf.conf file in /etc/ax25 directory to make it a system-wide
                      configuration file.  I personally feel this direwolf.conf file is an infrastructure 
                      level configuration file (just like configuring Ethernet or Wifi interfaces) so this belongs 
                      in /etc somewhere.  If you disagree with my approach and prefer putting this conf file 
                      in say /home/pi, that's fine but make sure you update all the various configuration and 
                      execution scripts to match.

                    # Go ahead and copy over the key config files:

                      sudo cp /usr/share/doc/direwolf/conf/* /etc/ax25/
                      sudo cp /usr/share/doc/direwolf/scripts/* /etc/ax25/


           g.2.b Direwolf 1.5 and OLDER releases only:

              1. For users using the standard ALSA support (Rpi 4 or newer board, Fe-Pi Audio Z sound devices, 
                 X86 computers), I've used the "pkgrelease = 1" to indicate the use of "Standard ALSA support":

                 NOTE:   You must update the version of libgps found above into the details below to match your 
                         distro's included version -- the below example is defaulting to libgps23

                 sudo checkinstall --pkgname direwolf --pkgversion 1.5 --pkgrelease 1 --pkggroup \
                 hamradio --pkgsource --maintainer \
        --provides "tnc" --requires libasound2,libgps23 \
                 make install


              2. For users using the OSS support wrapper (Rpi 3+, 3, 2, 1, Zero-W, Zero only), I've used the 
                 "pkgrelease = 2" to indicate the use of OSS support and removed libasound2 as a requirement:

                 NOTE:   You must update the version of libgps to match your distro's version

                 sudo checkinstall --pkgname direwolf --pkgversion 1.5 --pkgrelease 2 --pkggroup \
                 hamradio --pkgsource --maintainer \
        --provides "tnc" --requires libgps23 \
                 make install

            The checkinstall program will then prompt you with the following:

              Should I create a default set of package docs?  

                 Type in "Y" and hit enter

              When you see the prompt for "Description for the package:", type in:
                 DireWolf is an AX25 soundcard TNC, digipeater, APRS server, Igate, APRStt gateway, via serial, tcpkiss, or AGW sockets

              Validate the display output from checkinstall:
              0 -  Maintainer: [ ]
              1 -  Summary: [ DireWolf is an AX25 soundcard TNC, digipeater, APRS server, Igate, APRStt gateway, via serial, tcpkiss, or AGW sockets ]
              2 -  Name:    [ direwolf ]
              3 -  Version: [ 1.5 ]
              4 -  Release: [ 1 ]
              5 -  License: [ GPL ]
              6 -  Group:   [ hamradio ]
              7 -  Architecture: [ armhf ]
              8 -  Source location: [ ]
              9 -  Alternate source location: [  ]
              10 - Requires: [ libasound2,libgps23 ]
              11 - Provides: [ tnc ]
              12 - Conflicts: [  ]
              13 - Replaces: [  ]

              If the output from checkinstall looks similar to what you inputted, hit ENTER to begin the packaging and final install

           g.2.c Direwolf v1.5 and checkinstall users only: Copy over an example direwolf.conf file:

                 If this is a new Direwolf install and you want an example direwolf.conf file put in place, 
                 you need to run another command as the file is not automatically packaged in with checkinstall.  
                 Run the following to install a an example direwolf.conf file:

                    sudo make install-conf
                    cd /root
                    sudo mv direwolf.conf sdr.conf telem-m0xer-3.txt telem-*.conf /etc/ax25/

                 NOTE #1:  File locations: 
                      I choose to put the direwolf.conf file in /etc/ax25 directory to make it a system-wide
                      configuration file.  I personally feel this direwolf.conf file is an infrastructure 
                      level configuration (just like configuring Ethernet or Wifi interfaces) so this belongs 
                      in /etc somewhere.  If you disagree with my approach and prefer putting this conf file 
                      in say /home/pi, that's fine but make sure you update all the various configuration and 
                      execution scripts to match.

                 NOTE #2:  Disk Full errors:
                     If you get a "disk full" error here when checkinstall tries try to install things, it 
                     most likely means either the current file system you're doing your builds on or /tmp
                     became full (out of space).  While it's not technically required, I say you should have 
                     followed the previous section on creating a temporary /tmp mount point by using a local USB SDD/HDD 
                     drive or even a USB pendrive.  An NFS mount works for Direwolf too if you know how to do that.   
                     If you cannot setup an external mount, you can try increasing the running Raspbian 
                     "tmpfs" RAM drive size for /tmp (the stock 10MB is not enough).  You can try increasing
                     the /tmp file system up to 100MB.  Do this with the following:
                       # Temporary TMP space RAM drive resize
                       # ------------------------------------
                       sudo umount /tmp
                       sudo mount -t tmpfs -o size=104857600,mode=1777 overflow /tmp
                     The new Raspberry Pi 4 has versions that include 2GB and even 4GB of RAM.  Those will be
                     far more future proofed in this respect but will also consume more power which might
                     be an issue for some.  Please remember that a Raspberry Pi 4-1G, 3+, 3, or 2u only have 
                     1GB of RAM available.  Raspberry Pi Zero-W, Zero, v1B only have 512MB of RAM and the v1A only 
                     has 256MB.  I do NOT recommend to increase the /tmp file system go over 50% of that available 
                     memory and ONLY do so only temporarily.

                 NOTE #3: checkinstall errors:
                     If you notice that all kinds of strange of spaces are winding up in the output above 
                     (say the "name" field) or 1%{?dist} in the release field, this means you didn't rename the 
                     spec file as mentioned above!  Rename the .spec file and try again           

                 NOTE #4:  Mentioned already above but if you get an errors like:

                        install: cannot create directory /usr/share/direwolf: No such file or directory

                     then this means you probably didn't follow the section above as well as download 
                     and install the Makefile patch applied above.  If you ran that above patch file 
                     or you did and it didn't work for whatever reason, you can alternatively run the 
                     following commands and then try the checkconfig command again.  (I'm not sure why 
                     that patch doesn't 100% work but it doesn't hurt to run these commands regardless):

                        sudo mkdir /usr/share/doc/direwolf
                        sudo ln -s /usr/share/doc/direwolf /usr/share/direwolf
                        sudo mkdir -p /usr/share/doc/direwolf/examples
                        sudo mkdir -p /usr/man/man1
                     Now try the "checkinstall" program again as stated above

                 If everything went well, the checkconfig program will automatically create and install the 
                 resulting .deb package for you.  It will also save a copy of the built .deb package in the 
                 /usr/src/archive/Rpi-scratch/direwolf/direwolf-1.5 directory.  

                 If you had already installed a previous version of Direwolf, check that the /etc/ax25/direwolf.conf 
                 file still contains all your expected changes and wasn't reset to defaults.  If it was reset, 
                 you can restore the previous backup config file that was put in /etc/ax25/Old.

           h.  All versions of Direwolf

                 Now that you've been able to create a Debian package of Direwolf, you can copy this build .deb package 
                 to other Raspberry Pis and install it on different Raspberry Pi's assuming those other Rpis are:

                    - Running the same CPU type (RPi v0 and v1's CPU is different from Rpi v2/3/4)
                    - Running the same OS version of Raspbian (Buster, Stretch, Jessie, Wheezy)
                    - You've also installed the other required packages for Direwolf on those systems

                 To install that deb package once it's copied to that other Rpi, you would use the following 

                   NOTE:   The example configuration file aren't included in the checkinstall based deb package
                           so those will have to be copied over manually into /etc/ax25/

                   #To do the install on to other Rpis once the .deb package is copied over to them:

                      sudo dpkg --install direwolf_1.6-1_armhf.deb
                      sudo cp /usr/share/doc/direwolf/conf/* /etc/ax25/
                      sudo cp /usr/share/doc/direwolf/scripts/* /etc/ax25/

24.i. Configuring Direwolf

To configure Direwolf, edit the /etc/ax25/direwolf.conf file and set the following 
parameters for your specific needs.  This guide specifically ONLY enables basic KISS
TNC functionality to the Linux AX.25 protocol stack.  Direwolf can do a lot more
for APRS uses internally but that's beyond the scope of this document.  For additional 
parameters, please read:

   - General setup: PDF found in /usr/share/doc/direwolf/User-Guide.pdf

   - APRS specific setup: Raspberry-Pi-APRS.pdf and Successful-APRS-IGate-Operation.pdf

Anyway, let's configure Direwolf:

      Change the following line to reflect the correct sound device for your computer.  
      We have a few choices here so lets work our way through it:

      sudo vi /etc/ax25/direwolf.conf

      Input / Output sound device :: this is an ALSA device name.  Not PulseAudio or 
                                     PortAudio name 

         - ALSA support:
           If you're using Direwolf with a Fe-pi based sound device, simply enter in the 
           matching found sound device as shown from the "aplay -l" command.  In this 
           example, I've left the Raspberry Pi's built-in soundcard (playback only) still
           operational and make the Fe-Pi seen as the second available sound device.  Remove
           the "#" in front of the ADVICE line and make it look like:

              ADEVICE  plughw:2,0

          | Direwolf "dead air" workaround support:                                                |
          | Some versions of the Raspberry Pi OS with specific versions of the Raspberry Pi has    |
          | a known issue of keying up your radio and just WAITING some period of time before      |
          | sending the modem tones.  This section talks to several options to address this issue. |
          |                                                                                        |
          |                                      ------------                                      |
          |                                                                                        |
          | - RECOMMENDED: If you're using a USB based sound device on an older Raspberry Pi model |
          |      older than an RPi4 aka a RPi 3B+, 3, 2, Zero-W, Zero, or 1 SBCs, it's recommended |
          |      to try the use the new "DWC2" USB overlay fix (see above for more details).       |
          |                                                                                        |
          |                                                                                        |
          |   LESS RECOMMENDED: If the DWC2 approach doesn't work for your needs (say breaks other |
          |      things), you can try to use the "ALSA OSS" wrapper" work around. This still helps |
          |      then audio delay or "TX audio silence" bug.                                       |
          |                                                                                        |
          |   - To use this work around, you must re-compile direwolf where ALSA based support is  |
          |     DISABLED.  If you didn't recompile Direwolf, this won't work                       |
          |                                                                                        |
          |      - Next, run this command to install a required module:                            |
          |                                                                                        |
          |           sudo apt install alsa-oss                                                    |
          |                                                                                        |
          |      - NOTE about PulseAudio's "padsp":                                                |
          |             There is also the padsp tool which is apart of the pulseaudio-utils        | 
          |               package for OSS emulation for PulseAudio.  I am not describing this      | 
          |               tool here as PulseAudio for Raspberry OS was added mid-stream for the    |
          |               Buster release and it also requires the Xwindows GUI to be running       |
          |               where as the ALSA emulation works fine for the command line              |
          |                                                                                        |
          |   - Next, you need to create a virtual ALSA device. In this example, I've left the     |
          |     built-in Raspberry Pi soundcard operational and use an external Syba USB sound     |
          |     device as the second available sound device:                                       |
          |                                                                                        |
          |      - Create the .asoundrc file in the home directory of the username that will be    |
          |        running Direwolf such as "pi" or "root". Add the following lines where you put  |
          |        in the matching ALSA sound device as found via running "aplay -l" tool          |
          |                                                                                        |
          |           #example for direwolf being run as the "root" user:                          |
          |           #                                                                            |
          |           sudo vim /root/.asoundrc                                                     |
          |           --                                                                           |
          |           pcm.dsp0 {      type plug      slave.pcm "hw:2,0" }                          |
          |           --                                                                           |
          |                                                                                        |
          |   - Next, edit the /etc/ax25/direwolf.conf file, remove the "#" in front of the        |
          |     ADVICE line and make it look like:                                                 |
          |                                                                                        |
          |      ADEVICE  /dev/dsp0                                                                |
          |                                                                                        |
          |                                                                                        |
          |   - Finally, when you start Direwolf, you need to start it with the following:         |
          |                                                                                        |
          |        aoss direwolf <various command line options>                              |
          |                                                                                        |
          |     See more examples in the next sub-section.                                         |

      Next change the CALLSIGN line:

              MYCALL N0CALL
              MYCALL <enter in your callsign here with SSID - I'm using KI6ZHD-6>

      change the line (this mostly documents the default) but:

         MODEM 1200 - for AFSK 1200 baud packet
         E+         - the default AFSK1200 modem for lower power CPUs
         /3         - divide 48000 sound card sampling rate by three (lowers CPU load)

             MODEM 1200
             MODEM 1200 E+ /3

      change the PTT line (for my specifically chosen GPIO pin) : You must specify the BROADCOM 
      pin number and not the physical Raspberry Pi pin:
             #PTT GPIO 25
             PTT GPIO 26
      optionally consider to enable a GPIO pin for the DCD signal
             #DCD GPIO 25
             DCD GPIO 13

      Under the "PTT" or "DCD" GPIO line, add the following parameters.  These 
      settings impact the key-up and key-down speed of your specific radio.  A setting 
      of 40 means 400ms which is VERY conservative (most radios are like 100-150ms).  
      The 5 sets 50ms of a post audio transmission delay as well.  You ideally want these 
      values to be as fast as possible but this will require tuning on your part, most likely
      using a service monitor or oscilloscope:

              #PTT delay of 400ms and a post-modem tone delay of 50ms
              TXDELAY 40
              TXTAIL 5

        NOTE: If the TXTAIL setting is too short, I've seen where an AX.25 
              connection cannot gracefully disconnect via issuing the "b" (bye) command
              on a remote KPC3 TNC.  I had to change the TXTAIL variable from 10ms to 
              50ms to get things to work properly!

              Please see the following for more details on tuning your various RF levels 
              and timing:


      Unless you plan on using the TCP KISS (not the same as "serial KISS") 
      feature or the AGW/PE API support  (Direwolf does *not* support connected 
      sessions for things like Outpost, etc), then plan on disabling both of these:

             AGWPORT 8000
             KISSPORT 8001
             AGWPORT 0
             KISSPORT 0

      Depending on your use of your packet station, you might want to enable the
      FIX_BITS section to be either APRS centric or classic AX.25 "packet" centric error 

        - The first parameters of 1 or 2 is the number of bits Direwolf will try to 

        - the second parameter of the FIX_BITS option setting to "AX25" essentially disables 
          the APRS-centric hinting within Direwolf.  This is useful if you're a classic 
          "connected" packet user on a classic packet frequency and not on an APRS frequency.
          Please see the Direwolf UserGuide for more detail:

            FIX_BITS 1 AX25


     GPS locations beacon for using on APRS:

        It's a good idea that your packet system beacons it's location on the chosen frequency
        and if you plan to IGATE from APRS-IS to RF, it's required.  When setting the location, 
        consider if your station is NOT expected to move or not.  Why?  I encourage you to:

       a. Configure a static location vs using fixed GPS coordinates.  Why? Avoid GPS noise which 
          might shift your location around from position to position.  This is VERY common when
          people use cheap GPSes or have GPS receivers inside their homes.  This can create a 
          LOT of useless APRS traffic on frequency.

          Direwolf supports both decimal degrees (-71.34717) format using the "." character (and 
          negative values) as well as the degrees.minutes.seconds (71^20.83W) format using the "^" 
          character (and the E/W indicator)

       b. I'd recommend to only beacon once an hour if your station is always up and available.
          Direwolf's PBEACON or Position Beacon has the following syntax:

           delay         - delays the initial transmission of the packet 15 seconds after direwolf startup
           every         - beacons every 60 minutes
           sentto        - if NOT specified, beacon will go out on ALL interfaces (RF and Igate)
           messaging     - set to 1 only if your station can receive and respond to APRS messages (default is 0)
           symbol        - using the house symbol per
           lat / long    - position
           power         - 5watts
           height (HAAT) - 20ft off the ground
           gain          - 7dbi gain on 20m into a co-linear vertical antenna

              power / height / gain of transmitter in increments of the following (you can't put in any other values) 

           Looking at the table at , you can see what to best match your 
           setup for a PHG circle:

               phgd Code:      0    1    2     3     4     5     6     7     8      9 Units
               Power:          0    1    4     9    16    25    36    49    64     81 watts
               Height:        10   20   40    80   160   320   640  1280  2560   5120 feet
               Gain:           0    1    2     3     4     5     6     7     8      9 dB
               Directivity: omni   45   90   135   180   225   270   315   360 	  n/a degrees
           For my home setup, I'm using the following.  You need to find and put in your own location:

              PBEACON delay=00:15 every=60 SYMBOL=/- lat=37^20.00N lon=121^00.00W power=4 height=20 gain=6 comment="was KI6ZHD Change me, CA" via=WIDE1-1

       c. As a quick test for Direwolf's PTT and transmit functions, create the following 
          APRS Object beacon that transmits every minute:

          #Create a test object beacon that will be transmitted every 60 seconds that will be located north of Boston, MA in the town of Middleton
          #  Should show up here if your Object is heard by a local Igate -!addr=FN42MO08AA
          OBEACON delay=0:01 every=1 overlay=S symbol="digi" lat=42^37.00N long=071^00.00W power=50 height=20 gain=4 OBJNAME=TESTBCN comment="test beacon" via=WIDE1-1

       | Optional:                                               |
       |           Enabling APRS IGate functionality in Direwolf |

       d. APRS Igate: 

          If you intend on setting up an APRS Igate, below are the settings to create a receive-only RF to 
          APRS-IS Igate for general packets.  This also includes gating APRS-IS messages to RF for APRS 
          messages.  In the /etc/ax25/direwolf.conf file, find the following commented lines. Uncomment 
          them and change them to reflect your callsign, etc

          NOTE:  All of these setting assume your Raspberry Pi has Internet access.  If it doesn't have 
                 Internet access, there is no reason to setup Igating.  Direwolf should work just fine 
                 for local uses

          NOTE2: The APRS-IS system MUST have your station's location as set above in the "PBEACON" 
                 (Position Beacon) entry above.  If it's not set (and pretty accurate), things either 
                 won't work at all or you'll get data from APRS-IS that isn't appropriate for your area

          # Enable Igate connectivity - connects go on TCP port 14580
          #  If you are in other locations in the world, choose a closer APRS-IS pool listed at

          # Specify your CALLSIGN, SSID, and APRS passcode
          # Contact KI6ZHD if you can't figure out how to generate a APRS passcode for your callsign
          IGLOGIN N0CALL-6 <your callsign passcode here>

          #Enable Igate to RF transmissions on Direwolf "channel 0" being sent to the local WIDE1-1 
          IGTXVIA 0 WIDE1-1

          #Direwolf v1.4 defaults with an IGFILTER setting equivalent to having the APRS-IS system
          # sending you APRS "Item" objects within 30km of your location with "IGFILTER i/30".
          # You might want to apply a more custom filter for what packets will be received from the 
          # APRS-IS server.  Read about filters here:
          # In this example, I only want to receive APRS messages that are intended for stations
          # within 10km of my station's location
          IGFILTER m/10

          #In addition to the APRS-IS system only sending you data you want, sometimes it will
          # still send too much or unexpected data.  It's recommend to also setup a CLIENT side
          # APRS filter within Direwolf.  In this example, we will transmit only APRS "messages" 
          # Direwolf on channel 0
          FILTER IG 0 t/m

          # To avoid sending out too much data which might overheat your radio, discharge your battery
          # too quickly, etc, I recommend to enable the packet rate limiter.  This example will only
          # allow 6 packets in 1 minute or 10 packets within 5 minutes.  Any packets that will be
          # dropped due to the rate limit is logged.  If you want to allow more packets, increase
          # these specific configuration items to suit your needs
          IGTXLIMIT 6 10

24.j. Testing Direwolf

Test out Direwolf in it's stand alone more and enable all it's settings to better 
tune it's levels

      #Other options you might be interested in
      #-q d : suppress APRS decodes
      #-q h : suppress heard levels
      #-t 0 : disable colors
      #-d o : show output for asserting DCD and PTT lines
      #-a n : print out number of samples for N sections
      RECOMMENDED: For normal ALSA sound system users:
         sudo direwolf -t 0 -d o -a 100 -c /etc/ax25/direwolf.conf

            If you see an error when starting up, see below for troubleshooting ideas:

      For Older RPI users attempting to use the non-recommenced OSS wrapper approach:
      NOT RECOMMENDED: For ALSA-OSS wrapper users on older Rpi hardware with USB sound devices:

         sudo aoss direwolf -t 0 -d o -a 100 -c /etc/ax25/direwolf.conf

       Troubleshooting ideas:
          - For ALSA users running on say Raspberry Pi Buster with a Fe-Pi Audio Z v2 or an Rpi4 
            with a Syba USB sound device:

            1. If you see the error:
               Could not open audio device plughw:2,0 for input
               Device or resource busy
               Pointless to continue without audio device.

               One solution is if your Raspberry Pi is running a GUI interface, PulseAudio is 
               taking over the Fe-Pi.  To solve this, go into the GUI and go under:

                  Upper Left Raspberry Pi icon --> Sound & Video --> PulseAudio Volume Controle
                    Under the "Configuration" tab, change the bottom "Built-in Audio" to "Profile: OFF"

          - For OSS wrapper running on older Raspberry Pi hardware:

             1. If you get an error of:
                Can't read from audio device: Input/output error
                Terminating after audio input failure.

                   Confirm you created the required .asoundrc file in the home directory of the username
                   you're running Direwolf as (see the above sub-section).  

    HINT:  If you started Direwolf with it's coloring enabled and now all your 
           console text is blinking, you can use the command "tput reset" to 
           clear things out.  

  When Direwolf is running, there are two key things to monitor

    1. The sampling rate matches the configured rate.  If it deviates beyond the 
       expected rate too much, things won't work at all.  

          ADEVICE0: Sample rate approx. 44.1 k, 0 errors, receive audio level CH0 92

    2. Direwolf reported audio levels is roughly around a level of 50 on average 
       for various heard remote stations.  For example, here is one packet my station heard:

         K6FB-1 audio level = 57(26/14)   [NONE]   ___||||||

           How to read this above line:

               - K6FB-1 is the station heard

               - "57" is the heard audio level of this packet 
                      : goal here is to have all station be around a level of "50"

               - "26" is the heard audio level of this packet's "MARK" tone 
                      : ideally should be the same as the "SPACE" tone.  Major differences
                      : in these numbers indicate "twist".  Direwolf deals with this well but
                      : many legacy TNCs cannot (see Febo site to understand more)
               - "14" is the heard audio level of this packet's "SPACE" tone 
                      : ideally should be the same as the "MARK" tone.  Major differences
                      : in these numbers indicate "twist".  Direwolf deals with this well but
                      : many legacy TNCs cannot (see Febo site to understand more)

    3. With the test beacon running every minute, you should see a log item like the following
       (using your configured callsign and SSID):

          [0L] KI6ZHD-6>APDW14,WIDE1-1:;TESTBCN  *111111z4237.00NS07100.00W#PHG7140test beacon

       If you don't see your radio transmit every minute, you might have a wiring issue.  To 
       test things a bit more, disconnect the PTT GPIO pin from the Raspberry Pi and connect
       an LED in series with a 470 Ohm resistor:

          - connect to cathode of LED (short lead / smaller metal inside LED) to GPIO pin
          - connect to anode of LED (long lead / larger metal inside LED) to one side of the 
            470 Ohm resistor and the other side of the resistor to a GND pin

       You should see the LED light up every 60 seconds.  If you don't, recheck your 
       configuration until you get things working.

    4. Once things are working, edit your direwolf.conf file and disable the test OBEACON
       object line

24.k. Testing APRS-IS filters with TELNET

Interactive APRS-IS filter testing over the Internet:  

   Configuring and tuning appropriate APRS-IS filters to:

      - Ensure you're not gating too much data

      - Not congesting the local APRS RF frequency, etc. 

   is NOT trivial nor simple.  It really takes a lot of experimentation until you get the hang of 
   it.  Fortunately, you can do interactive filter testing without using Direwolf simply with the 
   "telnet" program.  For example, if you wanted to test receive APRS-IS APRS messages within 5km 
   of your location.  To test this, you'd run the following commands:

      #You must substitute in your specific callsign, SSID, APRS passcode, and decimal based 
      #location just like you configured above in your direwolf.conf file:

      NOTE:  The "#" character in front of the filter lines are REQUIRED for them to be accepted
      by the APRS-IS server
      telnet 14580
      user n0call-6 pass <your callsign passcode here> vers TestSoftware 1.0
      #filter m/5
      #filter t/m

25. Configure the AX.25 system

Now that you have the Direwolf TNC running, let's also enable Linux's native AX.25 stack for
advanced packet functionality.  This is NOT required if you only want to do APRS or AGW-based 
TCP/IP connectivity within Direwolf but it does allow you to perform all kinds of advanced 
packet functions as well as play with classic AX.25 packet.  Interested? Ok, let's set it up:

   a. cd /etc/ax25

   b. Edit the /etc/ax25/axports file by running the following commands and change it 
      to reflect your own settings:  

      sudo cp axports axports.orig

      sudo vi axports
      - Comment out or delete all the port definitions except "vhfdrop" at the bottom of the file

      - On the "vhfdrop" line, the next field is the callsign and SSID.  I'm using "KI6ZHD-6" 
        as I already have other packet stations on KI6ZHD (aka KI6ZHD-0), KI6ZHD-1, KI6ZHD-2, etc.
        This callsign+ssid MUST be unique on that connected radio's frequency.

      - The next field is the Data Terminal Equipment (DTE) speed which is the speed between
        the computer and the TNC.  This is generally set to be a FASTER rate than your Data 
        Communications Equipment (DCE) speed like 1200bps packet.  I would recommend to set this
        to "19200" which means 19200bps though with Direwolf, it's totally meaningless

      - The next field is the PACLEN (packet length) or maximum transmission unit (MTU).
        Increasing this value allows more data will flow per packet (with risk).  Depending on 
        the quality/power of your radio, antenna, other nearby stations you wish to communicate 
        with.  Larger PACLEN settings will provide higher performance assuming you don't have 
        many retries.  If you have a weak link and thus more retries, larger values will slow 
        things down.  Changing this value is a compromise that you must find.  The value of 128
        is a reasonable default and the maximum value is 255.

         NOTE:  If you plan on running Netrom, the maximum PACLEN you can use is 236

      - The next field is the WINDOW field which is related to the PACLEN field.  This value 
        controls the number of packets your station can send until it waits for an acknowledgment
        that your packets were received ok.  The more packets sent in a window, the faster the
        throughput BUT there is a risk.  With AX.25 v2.1, if one of those packets is corrupted,
        the entire window worth of packets will be resent!  That can REALLY slow things down if
        you have many retries.  The default of 2 is fairly conservative and I generally recommend
        a value of 4 if your links are pretty strong and reliable.

      - The last field is a comment field.  You can put anything in here that helps identify 
        this AX.25 device

      The line should look like the following for me (make the required changes for your setup):

         vhfdrop KI6ZHD-6 19200 236 4 TNC setup on 145.050Mhz

   c. Download my two example AX.25 startup scripts

      As part of my setup, I have several AX.25 startup and shutdown scripts available.
      I recommend that you look them over and make them your own to fit your needs.

      cd /tmp
      chmod 744 ax25-*
      sudo mv ax25-* /etc/ax25

   d. Install some required Raspbian packages that are needed for these scripts

      #Need killall and ifconfig  (if not already installed)
      sudo apt install psmisc net-tools

   e. You will need to do minor edits the file to suit your needs but 
      the key parameters to change are:

        cd /etc/ax25
        sudo vim
        #Change these two key parameters to match that of your direwolf.conf
        #  Please note the ADDITIONAL zero here for each parameter as the two files
        #  use different units

      | IMPORTANT:                                                                      |
      |                                                                                 |
      | You'll recognize that these are the same items as configured in Direwolf.conf.  |
      | Please read the Direwolf tuning section above and make sure THESE settings here |
      | align with the settings you put in the direwolf.conf file                       |

      Please understand that the AX.25 parameters configured in the script 
      will OVERRIDE the parameters originally configured in /etc/ax25/direwolf.conf.  
      It's recommended to have the TXDELAY and TXTAIL parameters in both files aligned
      for clarity sake.

26. Bring up the AX.25 system with a script

Assuming that everything is configured from all the steps above, start up the
Linux AX.25 stack with the following command:

  sudo /etc/ax25/

That command should look something like the following and if you have the speaker
still connected to the configured sound card, you should eventually hear a packet
burst!  You should see this on your screen as it starts up as well as in

   -- starting up

   Sun 30 Jun 2019 04:39:26 PM PDT
   axudp port not enabled in /etc/ax25/axports.. skipping
   TNC Type: direwolf
   Restoring audio levels on soundcard
   Starting direwolf (OSS support)A
   Dire Wolf DEVELOPMENT version 1.6 C (Jul 14 2019)
   Includes optional support for:  gpsd
   Reading config file /etc/ax25/direwolf.conf
   Audio device for both receive and transmit: /dev/dsp0  (channel 0)
   Channel 0: 1200 baud, AFSK 1200 & 2200 Hz, E+, 44100 sample rate / 3.
   Disabled AGW network client port.
   Disabled KISS network client port.
   Virtual KISS TNC is available on /dev/pts/0
   Created symlink /tmp/kisstnc -> /dev/pts/0

   Installing one KISS connection on PTY port /tmp/kisstnc
   PTS0 device: /dev/pts/2
   Setting advanced Linux AX25 stack settings - part 1
      Values only shown in /var/log/packet.log file via Direwolf's STDOUT)
   KISS protocol set TXDELAY = 40 (*10mS units = 400 mS), port 0
   KISS protocol set TXtail = 5 (*10mS units = 50 mS), port 0
   KISS protocol set Persistence = 63, port 0
   KISS protocol set SlotTime = 10 (*10mS units = 100 mS), port 0
   KISS protocol set FullDuplex = 0, port 0
   Displaying current system kissparms
   AX25 protocol mode (0=Norm* 1=Extd)                : 0
   AX25 backoff type (0=Linear 1=Expon*)              : 1
   AX25 connect mode (0=none 1=network 2=all*)        : 2
   AX25 Extd window size (num of unacked packets 32*) : 32
   AX25 idle timeout (idle session timeout in M 20*)  : 0
   AX25 AXIP mode (0=Datagram* 1=VirtConnection)      : 0
   AX25 max packet size (256*)                        : 256
   AX25 max packet retry count (10*)                  : 10
   AX25 protcol version (DAMA Slave)                  : 0
   AX25 STD window size (num of unacked packets 2* )  : 2
   AX25 T1 timer (unacked packet retry 10000mS*)      : 10000
   AX25 T2 timer (wait for 2nd RX packet 3000mS*)     : 3000
   AX25 T3 timer (link still up check 300000mS*)      : 300000

   Port vhfdrop attached to ax0
   Listen started and displaying on tty8

   Listen started and logging to /var/log/ax25-listen.log
   Preparing for ax25-up.new2 - sleep for 4 seconds
   ax25-up.new2 starting up

   Sun 30 Jun 2019 04:39:40 PM PDT

   beacon started

   mheardd Started

   ax25-up.new2 done

You can also see the same as well as some addition details from Direwolf by looking 
in the /var/log/packet.log file

To manually shutdown your packet station, run the command:

   sudo /etc/ax25/ax25-down
   Shutting down Linpac
   linpac: no process found
   nodesave: no NET/ROM port data configured
   N/R routes saved
   Ending beacon - 29259
   Ending mheardd - 29261
   Ending listen - 29245 29244
   Stopping Kissattach
   spattach: no process found
   Detach Ax/Nr/Sp Devices
   ls:: ERROR while getting interface flags: No such device
    ls: stopped
   Stopping mkiss
   mkiss: no process found
   Stopping Direwolf
   Ax25 Stopped

26.a. Linux AX.25 stack testing:

Ok.. we're getting close to having a fully functional packet setup.  Now grab another amateur radio and 
put it on the same frequency as your Direwolf packet radio frequency.  Now do the following:

   a. On the monitoring HT, key up the radio and verbally call out your callsign to make
      things legal (at least here in the US for Part 97 rules)

   b. Manually push the PTT button on your *Direwolf radio* and listen to the empty FM modulation 
      on this second radio.  There should NOT be --any-- hiss, whine, or any other noise.  This 
      should have already been tested in the previous section but just in case you skipped that 
      section, you need do this test now.  If there is any issues with your transmitted signal, 
      you need to resolve that now with better cable routing, cabling (shielded), the use of the
      correct mix RFI toroids, etc. If you don't resolve this, your transmissions won't be decoded 
      very well or at all!


   c. Type in the following command (assuming your /etc/ax25/axports device name is
      "vhfdrop") while holding down the "monitor" button (disables squelch on your monitoring 

         beacon -s vhfdrop "this is a test-this is a test-this is a test-this is a test-"

      At first, you will hear static noise all the time which is normal since you're using the 
      "monitor" button which disables the squelch feature on your radio.  This usually also 
      temporarily disables any RX power saving settings on your HT.   

      You should soon hear a longer AFSK1200bps AX.25 packet with an audio level that should 
      be not too loud, be 100% clear, non-distorted / no clipping qualities, with no background 
      noise, whine, or clicking sounds.  If you heard any of these artifacts, I again recommend 
      to read this excellent URL on how to tune your TNC's transmission levels to ensure you have 
      a solid signal:

   d. Next, try making a fictitious AX.25 connected session:

         call vhfdrop n0call

      You should see the following text in the terminal window:
         GW4PTS AX.25 Connect 2.0.1

      You should have heard AFSK1200 packet sounds trying to reach that remote, fictitious 
      callsign.  If you did hear the audio, type in control-c to exit.  If you instead see 
      "call: no AX.25 port data configured", you probably made a mistake in the 
      /etc/ax25/axports file.  Make sure that your "vhfdrop" line in that file is the VERY 
      last line in the file and all preceding lines start with a # character.

   e. Next, see if you can hear some AX.25 traffic.  Assuming say the local APRS frequency
      is busy in your area (144.390Mhz here in the US), QSY your Direwolf connected radio to 
      that frequency and issue the command:

         sudo listen -arp vhfdrop

      If your radio is working properly and have your audio levels set right, you should see 
      all kinds of traffic such as:
      vhfdrop: fm KJ6IX-9 to S8USPQ via ALDER* N6ZX-3* WIDE2* ctl UI pid=F0(Text) len 13
      vhfdrop: fm KE6AFE to APS250 via WR6ABD* NCA1* ctl UIv pid=F0(Text) len 64
      vhfdrop: fm K6ODX to APOT30 via WA6YLB-7* N6ZX-3* WIDE2* ctl UI pid=F0(Text) len 50
      vhfdrop: fm K6TJS to APU25N via WR6ABD* ctl UI pid=F0(Text) len 74
      @301626z3703.50N/12048.48W_329/008g017t067r000P000p000h74b10093/ {UIV32N}

      Type in control-c to exit the listen program

27. Enable log rotation for AX.25 packet logs

Now that your system has a working packet radio system and we're going to enable it upon
every boot, you'll need to rotate the generate logs so they don't fill the RAM drive:

# add log rotation for ax25-listen log
sudo vi /etc/logrotate.d/ax25-listen
/var/log/ax25-listen.log {
	rotate 3
        size 10M
	compresscmd /bin/bzip2
	uncompresscmd /bin/bunzip2
	compressoptions -9
	compressext .bz2

# add log rotation for the packet.log that records the start/stop and direwolf
sudo vi /etc/logrotate.d/packet
/var/log/packet.log {
	rotate 3
        size 10M
	compresscmd /bin/bzip2
	uncompresscmd /bin/bunzip2
	compressoptions -9
	compressext .bz2

NOTE: It's important to use the "copytruncate" command for some logs as these 
      files are getting appended from various Unix redirects and NOT syslog.  
      Since you cannot send say SIGUSR1 to re-evaluate their new file handle 
      for the newly created file

NOTE2: Once these two files are added, the logrotate system will automatically
       start using them the next time the cron system runs logrotate

27.a. Enable better AX.25 packet log timestamping

Now that you have your packet system logging all local AX.25 traffic, we should tune it up
a bit.  Why?  For example, if you ever tried to review that file, you would soon notice a big 
problem trying to understand which *day* a specific packet came in.  To make this
simpler, let's put hourly timestamps in the file!

   NOTE:  This "date-listen-log" script cannot end in the normal ".sh" shell script convention
          as the run-parts tool intentionally IGNORES those files

      cd /tmp
      chmod 744 /usr/local/sbin/date-listen-log
      sudo mv date-listen-log /usr/local/sbin/date-listen-log

      #Timestamp it it hourly
      ln -s /usr/local/sbin/date-listen-log /etc/cron.hourly/date-listen-log

28. Install Linpac and ax25mail-utils for Connected and UnConnected packet QSOs and PBBS

OPTIONAL for APRS users :: Good for Connected Packet users

   Linpac is a classic packet program for Linux that runs in an Ncurses terminal window 
   which is similar to the Pakkratt or PKGold programs for DOS.  It supports multiple 
   simultaneous keyboard to keyboard chats, sending unproto or UI packets through digi 
   paths, sending and receiving packet messages, etc.  You can learn more about it here:

Ok, interested?  Good!  There is two ways to install Linpac today:

   | NOTE: Significant issue with AX.25 and Raspbian Buster / Stretch (mentioned above)    |
   |                                                                                       |
   |    I have confirmed that with Raspbian Stretch, there is some sort of conflict with   |
   |    it's newly enabled predictable network interface names.  What are those?  If you   |
   |    run the command "ifconfig" or "ip addr", you will no longer see Ethernet           |
   |    interfaces with names like "eth0", "eth1", etc.   Instead, you'll see names like   |
   |    "enxb827eb5f05".  For known reasons, Raspbian allowed very long interface names    |
   |    and in the AX.25's sa_data kernel data structure, both the stock Raspbian AX.25    |
   |    .debs and the 3rd party VE7FET ax.25 debs will give errors like the following when |
   |    ANY network interface name is longer than 13 characters:                           |
   |                                                                                       |
   |       SIOCGIFHWADDR: No such device                                                   |
   |                                                                                       |
   |    ANY AX.25 programs like beacon or Linpac will fail.  Linpac will crash with:       |
   |                                                                                       |
   |       /usr/bin/linpac: line 181:  9811 Segmentation fault   $PKG_BINDIR/linpac $*     |
   |                                                                                       |
   |    Fortunately, if you disable predictable network interface names, things work fine. |
   |    To do this, do the following steps:                                                |
   |                                                                                       |
   |       sudo vi /boot/cmdline.txt                                                       |
   |       --                                                                              |
   |       #append the following to the end of the one line in this file                   |
   |       net.ifnames=0 biosdevname=0                                                     | 
   |       --                                                                              |
   |                                                                                       |
   |    Reboot your Raspberry Pi and things will work from there on out. Btw, if Linpac    |
   |    crashed on you,  your terminal might be screwed up and not working properly.       |
   |    To fix that, run the commands:                                                     |
   |                                                                                       |
   |       stty sane                                                                       |
   |       rm -f rm /var/lock/LinPac.0                                                     |

   | Critical / Mandatory NOTE:                                                            |
   |                                                                                       |
   |   As of Raspbian 9 / Debian 9 Stretch, this distribution has upgraded the version     |
   |   of the GCC compiler that BREAKS Linpac with versions LESS than 0.25.  You will see  |
   |   the issue where you'll start Linpac and get "Segmentation faults" at various points |
   |   in the program.  This issue is being tracked here:                                  |
   |                                                                                       |
   | |
   |                                                                                       |
   |   As such, it's MANDATORY that you upgrade to at LEAST Linpac version 0.25 or apply   |
   |   at least the  patch in the URL above.                                               |

   #NOTE #3:  There might be issues with these binaries looking for the program "axlisten"
   #          instead of "listen".  This is due to the fact that Debian changed the name of these 
   #          ax25 programs but the AX.25 repo this document builds from did NOT change
   #          their name.  I will research this where the fix could be simple symlinks
   #          to a recommendation of removing the VE7FET AX.25 programs and installing
   #          Raspbian stock ax.25 programs.  TBD

28a. Compile and Install Ax25mail-utils

   This package is used by Linpac to exchange BBS messages with nearby FBB BBSes.  This package
   is technically not required for Linpac to function but I would recommend to install it to
   have a complete setup.

     | NOTE:                                                                                         |
     |     The BBS message relaying functionality of Linpac and ax25mail-utils is known to           |
     |     be buggy.  It can work in some circumstances ONLY with remote FBB BBSes or KPC3 PBBSes    |
     |     but you shouldn't get your hopes up with this functionality with Linpac today.            |

   - ** RECOMMENDED **: Building Linpac and ax25mail-utils from sources:

     It's best to build Linpac from sources to get the newest fixes.  Below are the needed 
     steps on how to build the newest version of ax25mail-utils and Linpac from sources.   If you 
     choose do install Linpac binaries via the Raspbian repos mentioned above, please skip this 
     build section and go to the configure section below.

     Assuming a USB HD is mounted per the previous section

     Get the newest ax25mail-utils sources  - 0.15 is current as of 02/04/21

      cd /usr/src/archive/Rpi-scratch
      mkdir Ax25mail-utils
      cd Ax25mail-utils

   Ok, let's build and install the ax25mail-utils program

      tar xzvf ax25mail-utils-0.15.tar.gz
      cd ax25mail-utils-0.15

      ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var

      #Compile the sources using all four cores on your RPi 4, 3+, 3
      #  If you have an Rpi Zero-W, Zero, or v1, use "-j2" instead
      make -j8

   Now let's package and install it:

      sudo checkinstall --pkgname ax25mail-utils --pkgversion 0.15 --pkgrelease 1 --pkggroup \
      hamradio --pkgsource --maintainer \ --provides ax25mail-utils --requires ax25-tools,perl \
      make install

   Follow the checkinstall prompts:

          Should I create a default set of package docs?  

             Type in "Y" and hit enter

          Description for the package: 
          A set of utilities for packet radio mail exchange with the BBS. For use with the Linpac terminal programs as well as others

   Validate the output:
      0 -  Maintainer: [ ]
      1 -  Summary: [ A set of utilities for packet radio mail exchange with the BBS. For use with the Linpac terminal programs as well as others ]
      2 -  Name:    [ ax25mail-utils ]
      3 -  Version: [ 0.13 ]
      4 -  Release: [ 1 ]
      5 -  License: [ GPL ]
      6 -  Group:   [ hamradio ]
      7 -  Architecture: [ armhf ]
      8 -  Source location: [ ]
      9 -  Alternate source location: [  ]
      10 - Requires: [ ax25-tools,perl ]
      11 - Provides: [ ax25mail-utils ]
      12 - Conflicts: [  ]
      13 - Replaces: [  ]

   If your output looks similar to your screen, hit ENTER to begin the packaging.
   checkconfig will automatically install the package for you. If you manually 
   want to install it say on another machine, use the following (configuration files 
   aren't included in the checkinstall based deb)

   sudo dpkg --install ax25mail-utils_0.15-1_armhf.deb

   | CRITICAL NOTE:                                                             |
   |      With a recent toxic release of the AX.25 packages from Debian, it     |
   |      became obvious that Debian's APT system makes no distinction between  |
   |      this home-built package and the old Debian built package.  To protect |
   |      system from overwriting your built packages, run the following        | 
   |      command:                                                              |
   |                                                                            |
   |         sudo apt-mark hold ax25mail-utils                                  |
   |                                                                            |

   - NOT RECOMMENDED approach:  
         You can either install pre-built binaries from the Raspbian repositories 
         by doing the following but there are KNOWN issues with that older :

            #Make sure you get the Linpac 0.25 version or newer with this release of ax25mail-utils
            sudo apt update
            sudo apt install linpac ax25mail-utils

28b. Compile and Install Linpac

Ok, now let's now move on and build and configure Linpac:

   #RECOMMENDED - gets the newest DEVELOP release 
   Get the newest pre-release version of Linpac - 0.29 is current as of 02/01/21:

      cd /usr/src/archive/Rpi-scratch
      mkdir Linpac
      cd Linpac
      git clone linpac-linpac
      cd linpac-linpac
      git checkout develop
      git pull #only needed if you had already cloned the repo before)

      #This step will just sit there for 10 seconds but it will work
      autoreconf --install
      ./configure --prefix=/usr
      #Now skip down a little bit to the compile part of this section

   #LESS RECOMMENDED - downloads the previous release (quite old)
     Get the newest RELEASE version of Linpac - 0.25 is current as of 12/10/17:

      cd /usr/src/archive/Rpi-scratch/
      tar xzvf linpac-0.25.tar.gz
      cd linpac-0.25

      #Prepare the package to be compiled - takes about 31 seconds on a Rpi3
      ./configure --prefix=/usr

      #Now skip down a little bit to the compile part of this section

        If you are trying to build Linpac 0.24 or older for Raspbian (NOT recommended - 
        please use 0.25 if at all possible), you MUST download and apply a patch from 
        Martin Cooper KD6YAM to resolve recently exposed POSIX issues:

           patch -p1 < segfault-patch.diff

Now let's compile / install Linpac:

   #Compile the sources 

      # RPi 4, 3+, 3 and other boards with 4 cores :: takes about 31 seconds on a Rpi3
      make -j8
      # Rpi 2, 1, Zero-W, Zero or other boards with 1 core
      make -j2

     There seems to be some strange bugs with Linpac's installer on Debian Buster, Stretch, and  Jessie
     where it's not creating some directories for the first time install.  If you've already installed
     Linpac before on this particular machine, you don't have to do this step.  If this is a NEW install,
     the following commands will help work around the issue before you start the next packaging step:

        sudo /bin/mkdir -p "/usr/share/linpac/contrib"
        sudo /bin/mkdir -p "/usr/share/doc/linpac/czech"
        sudo /bin/mkdir -p "/usr/share/linpac/macro/cz"
        sudo /bin/mkdir -p "/usr/libexec/linpac"

   Now figure out what version of Linpac you're installing and be prepared to use that version number below:

      grep " VERSION" config.h

         As of 02/01/21, it shows:
         #define VERSION "0.29"

   Now let's package and install Linpac - Be sure to update the version number learned above in the command

      For Raspbian version Buster (Debian 10.x) ONLY:
         sudo checkinstall --pkgname linpac --pkgversion 0.29 --pkgrelease 1 --pkggroup \
         hamradio --pkgsource --maintainer \ --provides linpac --requires libax25,ax25-apps,ax25-tools,libncurses6 make install

      For Raspbian versions Stretch (Debian 9.x) or Jessie (Debian 8.x):
         sudo checkinstall --pkgname linpac --pkgversion 0.28 --pkgrelease 1 --pkggroup \
         hamradio --pkgsource --maintainer \ --provides linpac --requires libax25,ax25-apps,ax25-tools,libncurses5 make install

   Follow the checkinstall prompts:

          Should I create a default set of package docs?  

             Type in "Y" and hit enter

          Description for the package: 
          A modular TUI-based packet radio terminal with concurrent connected/unconnected sessions and a built-in messaging client 

   Validate the output (example is given for Raspbian Buster):
      0 -  Maintainer: [ ]
      1 -  Summary: [ Linpac is a modular console-oriented packet radio terminal for Linux with a built-in messaging client. ]
      2 -  Name:    [ linpac ]
      3 -  Version: [ 0.29 ]
      4 -  Release: [ 1 ]
      5 -  License: [ GPL ]
      6 -  Group:   [ hamradio ]
      7 -  Architecture: [ armhf ]
      8 -  Source location: [ ]
      9 -  Alternate source location: [  ]
      10 - Requires: [ libax25,ax25-apps,ax25-tools,libncurses6 ]
      11 - Provides: [ linpac ]
      12 - Conflicts: [  ]
      13 - Replaces: [  ]

If your output looks similar to your screen, hit ENTER to begin the packaging and install
the resulting package

   | CRITICAL NOTE:                                                              |
   |      With a recent change to Raspbian 9 / Debian 9 Stretch, changes to      |
   |      the version of GCC has made the pre-build version available in the apt |
   |      repos TOXIC (will crash on your system).  To protect your system from  |
   |      having Apt overwriting your newly compiled version of Linpac, run the  |
   |      following command to have apt IGNORE the repo-made version:            |
   |                                                                             |
   |         sudo apt-mark hold linpac                                           |
   |                                                                             |
   |      Linpac 0.25 resolves this issue and I've requested the debian-hams     |
   |      packaging team to release Linpac 0.25 for Stretch and Jessie as of     |
   |      12/11/17.                                                              |

   If your output looks similar to your screen, hit ENTER to begin the packaging.
   checkconfig will automatically install the package for you 

     NOTE: If you manually want to install this newly compiled and packaged version of Linpac
           on some other Rpi running the same OS version, use the following 
           (configuration files aren't included in the checkinstall based deb)

           sudo dpkg --install linpac_0.28-1_armhf.deb

28.c. Configure Linpac

   | IMPORTANT:                                                                                |
   |                                                                                           |
   | Before you get started, it's very important that you completed the above "Linux AX.25     |
   | stack testing" testing section to confirm your AX.25 stack is properly working.  Without  |
   | a proper setup, I've seen Linpac give Segmentation fault and other weird issues.          |

A few things you need to consider before configuring Linpac:

   If you want to see and use the built-in AX.25 Linux traffic monitor "listen" which is VERY useful, 
   you either need to:

     a. It's the easiest to run Linpac as root  (what I am doing in this doc for now but I know
        this isn't a great security model)

     b. Make the ax.25 listen program ( /usr/bin/listen or /usr/bin/axlisten ) SUID root

     c. Compile, setup and configure the "ax25spyd" program as a proxy (not documented here but you
        can read how to build that here:


Anyway, let's focus on configuring the core Linpac program for now:

   1. Create the mail holding area

         sudo mkdir -p /var/ax25/mail

   2. These instructions are currently assuming you're going to run Linpac as root.  If you
      ARE NOT going to run Linpac as root and instead, you want to run the Linpac program as a 
      regular user, you'll need to do two other steps:

         #To have the listen function work properly, also consider doing the following 
         #   has security concerns though
         sudo chmod 4755 /usr/bin/listen
         sudo chmod 4755 /usr/bin/axlisten

   3. Make sure you have root permissions via running the command as the setup wizard
      has issues with being run with sudo:

         sudo chown $USER /var/ax25/mail

   4. Now start Linpac program by running the command as your desired user be it the "root"
      user or your chosen non-root user:

   5. When prompted for your callsign, enter in your callsign WITHOUT any SSID.   For me, I 
      typed in:


   6. When prompted for your home BBS callsign, you should to enter in something.  It needs to be a 
      valid or at least valid-looking packet BBS address.  It should be noted that this is only used 
      when the ax25mail-utils package is installed and configured.  If the ax25mail-utils package is not 
      installed, this automated packet mail relay feature of Linpac won't function.  It's not a big
      deal if you don't enable this feature but you still need to put in something or the Linpac
      installer won't complete.  It should also be noted that Linpac and the message relay system ONLY 
      supports F6FBB BBS type system today.  It doesn't understand the prompts of other alternative
      BBSes like JNOS, KPC3 PBBS, etc.  

      For this example, I'm using:


      This is my local, full service BBS.  Don't worry about these settings as they won't start polling 
      for packet messages, etc. until configured later.  You can learn more about BBS hierarchical 
      addressing here:

   7. When prompted for "name of port to connect to" (used to connect to your real or fictitious BBS), 
      you need to specify your AX.25 port configured in /etc/ax25/axports.  For this example, I am 


      Please note.. that's different than the Linpac default of "vhfport"

   8. When prompted for "the digipeaters used to connect", I just hit ENTER to mean NO digipeaters
      as I can hear my local BBS directly

   9. When prompted for "Enter the full hierarchical address", put in a correct looking packet
      address.  For my example, I'm using "#NCA.CA.USA.NOAM" (yes, including the preceding #) for 
      my specific path which means:
         - Northern California
         - California
         - United States of America
         - North America

      Notice it's EXCLUDING the name of the actual BBS.  See the above URL for more details and 
      understanding of other geo-centric addresses.

  10. At this point, hit enter again and Linpac will create a set of configurations into 
      /root/LinPac/ and the Linpac program should then start up.  You should see a black background 
      with a green bar towards the top of the screen.  Unfortunately, the system is not quite ready 
      to fully support running Linpac and you might even see various errors upon start up.  

      Please exit Linpac by typing in:


      (yes, you need to include the preceding colon which is apart of Linpac's command syntax).  
      After exiting, we need to further continue to configure Linpac.

  11. Now edit /root/Linpac/macro/init.mac and find the lines that start with:

         sudo vi /root/LinPac/macro/init.mac

      If you're running Linpac as a non-root user, you would edit your own config file with:

         sudo vi /home/$USER/LinPac/macro/init.mac

      Now find the line that has your callsign in it.  For example, my setup has:
         mycall@1 KI6ZHD

      In this example, I ONLY only want to associate the KI6ZHD-6 callsign+SSID combo and NOT
      the KI6ZHD (aka KI6ZHD-0) combo to the F1 and F2 keyboard keys (by default, Linpac will assign
      the previously entered CALLSIGN to all eight F1-F8 keyboard assignments.  Notice I'm using
      two F-keys for the mapping of SSID to terminal "view" or F-key views.  In this example, 
      Linpac will allow one incoming connection going to SSID KI6ZHD-6 on the F1 terminal but if
      a different packet radio station tries to connect to you, it will assign that connection to 
      the F2 terminal.  This effectively makes Linpac able to support simultaneous QSOs to the same 
      callsign+SSID like KI6ZHD-6!  That's NOT a common capability for packet radio software and
      most systems would just say that KI6ZHD-6 is busy.  Pretty slick!  To support this this setup, 
      edit these lines to read:

        mycall@1 KI6ZHD-6
        mycall@2 KI6ZHD-6

      I then insert ";;" in front of the other "mycall" lines to comment them out (disabling them).
      If you want to have other CALLSIGNS+SSIDs associated to other F-keys, enter them in now.

      Thoughts on SSIDs
      It's important to note that depending on the specific packet radio frequency you intend to 
      operate on, there can be different SSID allocation schemes in use.  There are only defacto 
      standards user here and schemes will vary from region to region.  A few points here:

         - Do not configure any SSIDs in Linpac that are also configured in the /etc/ax25/direwolf.conf 
           file if you're using Direwolf

         - If you're going to be operating your station on an APRS frequency, make sure that Linpac 
           isn't using one of the common APRS SSIDs.  APRS SSIDs have special meanings and most commonly
           are configured in the direwolf.conf file.   If you intend to use the built-in APRS functionality 
           in Direwolf itself, you can see what different APRS SSIDs are recommended here:


         - For classic connected packet radio use, the SSIDs also differ from region to region.  In Northern 
           California on 145.050Mhz, we've standardized on:

            SSID :: Description
              -0 :: (aka.. no SSID) direct human to human / keyboard to keyboard chat
              -1 :: PBBS mailboxes
              -2 :: not specifically used
              -3 :: not specifically used
              -4 :: not specifically used
              -5 :: netrom nodes and digipeaters
              -6 :: not specifically used
              -7 :: netrom nodes and digipeters (alternate)
              -8 :: not specifically used
              -9 :: not specifically used
             -10 :: for Winlink nodes

             -11 through -15 are generally NEVER used since NETROM connections will automatically use
             these high SSID numbers starting with -15 when creating secondary connections.  For each 
             hope, netrom will continue subtracting from the SSID number through the lower SSIDs to 
             manage link by link connections

   11.  If you plan on making any UNPROTO messages, consider editing the "undest" line to include
        your name and any required digipeaters.  In this example, I'm using the following.  Notice
        the undest line includes quotes.  Those are REQUIRED if you're going to use a chain of

           unsrc KI6ZHD-6

   12. Configuring other aspects of Linpac is beyond this document but you might
       consider to update the Linpac display parameters to be a little more attractive 
       but these settings are both a personal preference and what fits my screen.

         statline 15
         chnline 30
         infoline 5
         NOTE:  If you start Linpac say from within screen session (shown later in this document) and 
                the display looks all squashed up and ultimately see an error:

                   "invalid value"

                Linpac is complaining talking about these various statline, chnline, infoline line 
                count numbers above depending on your terminal.  Try reducing some of the line count 
                sizes for say the "chnlin" value to a smaller number

       You can find more advanced Linpac configuration tips at:

   13. Finally, I recommend to NOT start Linpac via command line and instead, start it using the included 
       shell script found in /usr/share/linpac/contrib/  This same script is also called
       from the /etc/ax25/ suite.  This script will start Linpac within a "screen" terminal 
       session.  What this means is "screen" will allow you to disconnect and reconnect to a running
       Linpac at any time.  If you want to use this script, you'll also need to do two things:

          a. Install the screen package with:
             sudo apt install screen

          2. Per this example, we are running linpac as the ROOT user.  If you want to run Linpac as
             a different user, please edit the script and change the line that reads:

                sudo vim /usr/share/linpac/contrib/ 
                screen -c $HOME/.screenrc-svxlink -S linpac sudo linpac


                screen -d -m -S linpac sudo linpac
                #screen -d -r linpac

            It's important to have that last line commented out or screen will try to reconnect
            to the current TTY but no one is logged in!

28.d. Using Linpac via screen

Linpac is a powerful, Ncurses based packet program but the full use of it is beyond this
document.  Please read all of the documents available on your Raspberry Pi in the
/usr/share/doc/linpac/ directory or at .
you can find more tips at

Anyway, to get you started, once you SSH into your Raspberry Pi and configure your packet system
to auto-start upon boot (starts Linpac too), you'll be able to connect to the "screened" Linpac 
session at any time.  

Ok, start up Linpac and then re-attach to it's screen session:

   sudo /usr/share/linpac/contrib/
   sudo screen -dr linpac

At this point, you should see the Linpac main interface where:

   - At the top are the commands to send to either Linpac or to the remote station you've
     connected to
   - In the middle is the text your station receives from the remote station
   - At the bottom is all the packets your system is hearing

A few quick commands to get you around:

   - To connect to a remote station, say the remote "lprc3" node that in my area, I would issue 
     the following command INCLUDING the first ":" character too:

        :c lprc3

     The system should then connect and you'll see the text coming in from the remote system!

   - To force a disconnection of the current session, use:


   - If you configured Linpac to use to different SSIDs, you can use the respective
     F1, F2, F3, etc keys to use which can either initiate or receive multiple, simultaneous 
     connections.  The F10 key is dedicated to sending and monitoring unproto or UI packets
     for unconnected chats, etc.

   - To disconnect from the current screen session but leave Linpac running, simply issue the 
     screen command:

        control-a d

     and you'll disconnect from the session but it keeps running.  Cool huh!

   - If you want to shutdown Linpac instead of disconnecting from it's screen, you'd instead issue 
     the following Linpac command (yes, you need the double slashes):


29. Auto start the packet system and advanced services

Ok.. so the packet system is up and running and you want it to start upon every boot.  Cool!
To do that, do the following:

   1. Edit the /etc/rc.local file and just above the line reading "exit 0", add the following 

      sudo vi /etc/rc.local
      echo -e "\nStarting packet system"
      /etc/ax25/ &

   2. Next, if you want to auto-start some of the additional packet services including Linpac, 
      edit the /etc/ax25/ file and at the bottom of the script, remove the #ed out 
      line that runs the follow-on /etc/ax25/ax25-up.new2 script:

         sudo vi /etc/ax25/
         #remove the # in front of this line to now let it run
         /etc/ax25/ax25-up.new2 $TNCTYPE

   3. Now let's edit the /etc/ax25/ax25-up.new2 script and at least enable beacons and to have
      Linpac to auto-start.  If you've configure any other AX.25 services, you can remove the 
      #s in those lines to have them auto start too.  For now, let's do beacons and Linpac:

         sudo vi /etc/ax25/ax25-up.new2
         #Find the beacon section and change the CALSIGN+SSID, CALLSIGN and status text to match 
         #your own callsign, desired SSID, beacon text, etc:
         /usr/sbin/beacon \
         -c ki6zhd-6 \
         -d 'info KI6ZHD' \
         -t 15 \
         vhfdrop \
         "low-level KB2KB netrom node in Santa Clara  "

         #Make sure the Linpac section is present.  If not add it
         # Start LinPac
         if [ -f /root/LinPac/macro/init.mac ]; then
            if [ $? -ne 0 ]; then
               echo -e "LinPac failed to start"
               echo -e "LinPac failed to start" >> $LOG
               echo -e "\nLinPac Started"
               echo -e "\nLinPac Started" >> $LOG

That's it!  All the basics of your packet station should be working and ready to auto-start when
you boot your RPi!  So.. let's test it.  Shutdown the Rpi with the shutdown button (if you followed
that section) or run the command:

   sudo /sbin/shutdown -h now

Wait for the Rpi to shutdown and watch the Rpi's green LED blink 10 times and then go completely
off to mean it's safe to remove the power.  Remove the power, wait 5 seconds, and re-connect it.  
When the Rpi comes back up, log back into the Rpi a look for:

   - If you're using a Syba USB soundcard, check that it's green LED is quickly blinking.  You'll
     noticed that after the first transmission from Direwolf, the LED will blink slower.  This
     is expected.
   - Running "ifconfig" will show the "ax0" interface

   - Run the following commands to make sure they are running:

      ps aux | grep pishutdown

      ps aux | grep direwolf

      ps ax | grep listen    #There will be three of these

      ps ax | grep linpac

      ps ax | grep beacon

      ps ax | grep mheardd

If all of these process are listed.. you're set!   Now, time to get things working with out a 
wired connection... on to Wifi!

30. OPTIONAL: Configuring your Rpi to either connect to an existing Wifi AP or act as a Wifi AP for providing local connectivity:

| Raspbian Bullseye and Buster:                                                       |
|                                                                                     |
|        Simultaneous client and AP operation still needs to be updated and validated |

Configuring a Raspberry Pi 4, 3+, 3,Zero2-W, or Zero-W to act as either a standard Wifi 
client connecting to an existing Wifi AP --or-- have it act as a full Wifi access Point isn't 
too difficult.  This section will tell you how a Wifi-enabled Rpi can do both functions 
SIMULTANEOUSLY.   The Wifi range is pretty decent considering that the Rpi only have either 
a small PCB or small chip antenna.  If you want better range, consider doing a hardware 
modification to add a u.fl connector and use an external Wifi antenna (mentioned below - 
not possible on the Rpi 4, 3B+, and Zero-W):

   NOTE: Previous doc versions focused on working with an RTL8192CUS based Wifi device but this 
         has been dropped


         The above work is now mostly unneeded now as the Raspberry Pi line now has Wifi built in.  
         Also and unfortunately, the Linux support for Realtek RTL8192 within the hostapd program 
         is NOT in the mainline release nor does it sound like it EVER will be (been this way for 
         years now).  Add in that there is a lot of conflicting and stale setup information out on 
         the web of how to do it and it's become a bit of nightmare to setup.  I've kept this older 
         detail in a later section in this doc farther down in a "deprecated" section but with the 
         new Rpi v3 / Rpi Zero W and their built-in Wifi hardware, I wouldn't recommend to go the 
         RTL8192CUS route anymore.  Save yourself time and money and just buy a new Raspberry Pi!

30.a Configure your Rpi to connect to an existing Wifi AP for network access

Connecting to an existing Wifi AP from a Wifi-capable Raspberry Pi is quite easy from the command line
and actually can be done one of two ways:

   Raspberry Pi OS (Buster version):

      - Method 1: Configure Wifi before you first boot your Raspberry Pi:

         - Create the file /boot/wpa_supplicant.conf with APPENDING the following info this file.  
           You *MUST* replace various settings for your specific region 
           (per ), Wifi SSID name, and 
           Wifi SSID key:

        - Once you boot your Raspberry Pi, this file will be automatically copied into /etc/wpa_supplicant/wpa_supplicant.conf
          and will configure Wifi services to auto-start

      - Method 2: Configure Wifi via the console using an HDMI display and a keyboard

         - Create the file /etc/wpa_supplicant/wpa_supplicant.conf with APPENDING the following into
           this file.  You *MUST* replace various settings for your specific region (per 
  ), Wifi SSID name, and 
           Wifi SSID key:

           - If you are unaware of what your Wifi SSID is, you can run this command to get a list of 
             APs in range:

                iwlist wlan0 scanning | grep ESSID

           - Once configured, try manually bringing up the Wifi interface and see if it got an IP
             address with the following commands:

                sudo wpa_cli -i wlan0 reconfigure
                ifconfig wlan0

           - If that worked, now reboot your Pi and make sure wifi comes up as expected 

                sudo /sbin/shutdown -r now

30.b Configure your Rpi to act as a Wifi AP using the built-in Raspberry Pi 3 Wifi support

With the debut of the Raspberry Pi 3 and Rpi Zero W, these new SBC versions and all versions 
since support built-in 802.11AC or 802.11N Wifi and Bluetooth 5.0, 4.2, and 4.1.  The initial versions
of Wifi hardware only the 802.11 2.4Ghz band but the v4 and 3+ added 5.0Ghz support.  The only 
downsides to this built-in wireless support in my opinion is:

   - The stock antenna on the Rpi3,3+,and Zero-W is considered to be pretty good.  The Rpi3's "chip 
     antenna" was only considered decent which means your Wifi distance and speed will be limited.  
     You can find this white antenna chip on your Rpi3 just to the right of the 40pin header when 
     the HDMI port is facing you.  The stock antenna's range isn't bad but can't be greatly improved 
     with hacking the Rpi v3's hardware a bit by soldering on a U.FL connector and using an external 
     Wifi antenna.  More on that later.  Please note that this option is NOT possible on the 
     4,3B+,Zero-W  as they removed the solder pads.  

   - There aren't any Wifi or BT network traffic LEDs to indicate that the AP is active, being used, 

Anyway, for now, let's move forward with first enabling the Rpi to act as a Wifi AP ONLY 
(aka.. (infrastructure mode"):

   Like everything Linux, there are several ways to do everything.  Here are the design choices
   this document is making:

   Use an existing AP or  If you're using Wifi on your Rpi today being it's primary Internet connection, 
     or become* an AP:    these steps will BREAK that network connection.  This doc will make the Rpi act 
                          like it's an access point but below, I have added where the Rpi can act BOTH as
                          an AP but also connect to an existing AP *simultaneously*.  In the future, I might
                          add a physical switch connected to GPIO pins to allow you to choose how the Rpi 
                          will exclusively act but that's not documented here yet (is mentioned in my old
                          Rpi doc available at: 


      This doc section:   Based on recommendations from 
                          but I've added informational and troubleshooting commands, modernized it's 
                          commands to use native Systemd commands and added IPTABLES firewall sections to 
                          protect your system

      IP Addressing:      This doc will use the network on the Wifi network

      Local or Internet:  My initial intention for wireless access is to get my smart phone to SSH
                          into the Raspberry Pi directly.  This section is to NOT provide Internet access 
                          to any of the Wifi devices connected via the Raspberry Pi's Wifi.  Adding this 
                          routing functionality is actually pretty easy (NAT or bridging) but it's not 
                          covered here.

      Stateful Firewalls: It enables firewalling which is always an important security practice

      DHCP and DNS:       For my lightweight uses, I'm going to use hostapd and dnsmasq.  Other 
                          HOWTOs on the internet use ISC's DHCPd server and ISC's Bind DNS servers but they 
                          are additional packages to install and using ISC's industrial strength programs 
                          are major overkill for this simpler use-case


To start off with, let's make sure Linux sees the Wifi hardware.  Run the command:

   dmesg | grep brcmfmac

and you should see something similar to these Wifi details:
   brcmfmac: brcmf_c_preinit_dcmds: Firmware version = wl0: May 27 2016 00:13:38 version (r640327) FWID 01-df77e4a7

   NOTE:  If you see don't see anything, try again just running "dmesg" and if you're only seeing lines like 
          the following, you're best off just rebooting your Raspberry Pi for now and again looking at the 
          output to confirm the Wifi chip is seen.  Btw, this IPTABLES "log noise" can  be fixed by enabling 
          ulogd logging by following that previous section in this doc).  Here is an example of this "log 
          noise" that you might see:
   iptables denied: IN=eth0 OUT= MAC=ff:ff:ff:ff:ff:ff:60:57:18:ca:a3:32:08:00:45:00:00:4e:20:63:00:00:80:11:97:71 SRC= DST= LEN=78 TOS=0x00 PREC=0x00
TTL=128 ID=8291 PROTO=UDP SPT=137 DPT=137 LEN=58

If the wifi hardware was seen, it's most likely the OS has automatically created the "wlan0" interface.  Run the 
following command to confirm you see the "wlan0" interface:

   /sbin/ifconfig -a

wlan0: flags=4099  mtu 1500
        ether b8:27:eb:0a:50:6e  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

There isn't an IP address on it right now which is perfectly fine.  Let's also confirm the Wifi device 
can be interrogated:

   iwconfig wlan0
   wlan0     IEEE 802.11  ESSID:off/any
             Mode:Managed  Access Point: Not-Associated   Tx-Power=31 dBm
             Retry short limit:7   RTS thr:off   Fragment thr:off
             Encryption key:off
             Power Management:on

   or the command "iw dev"

In the next steps, you need to understand that the Stretch and Jessie versions of Raspbian uses  
the SystemD style of Linux system management.  This means everything in Linux is COMPLETELY changed 
the way that the Linux network stack gets configured.  Love it or hate it.. it's here.  Raspbian also
now uses the dhcpcd (read that as DHCP *client*) process for all network interfaces (strangely enough..
even for static IP addresses!).

    Yes.. I know what you're thinking.. .. what does DHCP have to do with static IP addresses?! 
    I agree with you that it's totally backwards but it's TRUE.  Take up your complaint with with 
    the SystemD guys and not me. 

Back to it, you first need to install some key software:

   #Update your software list
   sudo apt update

   #Accept all additional package dependencies
   sudo apt install dnsmasq hostapd rfkill

Next, you need to enable the dhcpcd service and configure a static IP of on the 
wlan0 interface.  If you'd like to use a different TCP/IP subnet, make your changes here and as 
appropriate in all future configuration stanzas.  Step one is to to NOT try to get a DHCP client IP 
address on the wlan0 interface.  Add the following line at the bottom of the file:

   Raspbian Stretch ONLY:
      sudo vim /etc/dhcpcd.conf
      interface wlan0
      static ip_address=
      static routers=

   Raspbian Jessie ONLY (Not stretch):
      sudo vim /etc/dhcpcd.conf
      denyinterfaces wlan0

Pre Raspbian Stretch users:
  Edit the interfaces file to create a static IP for the wlan interface.  Specifically, 
  you might need to alter the lines to reflect what you want to use:

   Raspbian Stretch ONLY:
      Do NOT edit the /etc/network/interfaces file at all!

   Raspbian Jessie ONLY (NOT Stretch):
      sudo vim /etc/network/interfaces
      allow-hotplug wlan0  
      iface wlan0 inet static  
      #    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

   IGNORE ME- I'm leaving this legacy entry in this document for now to ensure I don't see any 
              strange behavior and might need to re-add it:

              disable SystemD from trying to associate to any local APs:
              #Find the line that looks like the following and it DOESN'T have a # in front of it
              allow-hotplug wlan0

Ok, now let's activate this base wlan0 configuration.  Run the following commands:

   #restart the dhcpcd client
   sudo systemctl restart dhcpcd.service

   #Reset the wireless interface
   sudo systemctl restart systemd-networkd.service

   #Remove any disabling of the wlan interface
   sudo rfkill unblock 0

At this point, not a whole lot will be changed as the wireless interface still doesn't have any
network associations but

   Raspbian Stretch:
      Won't show any IP address in the output of "ifconfig -a" just yet

   Raspbian Jessie:
      If you run "ifconfig -a" should show the IP address on the interface.

Now it's time to configure hostapd which makes the wireless device enter "Access Point" mode.

   NOTE:  Raspbian Stretch doesn't copy over the default configuration file by default but
          if you want to start with that you can issue the command:

             sudo zcat /usr/share/doc/hostapd/examples/hostapd.conf.gz > /etc/hostapd/hostapd.conf

   NOTE2:  There are a LOT of configuration options in the default /etc/hostapd/hostapd.conf
           file.  If you know EXACTLY what all these items do, feel free to customize the settings
           but I've only tested the below changes:

   sudo vim /etc/hostapd/hostapd.conf
# The Rpi3s default wifi interface

# Use the nl80211 driver which includes support for the Broadcom brcmfmac hardware driver

# This is the name of the Wifi network you're creating.  Change this to be what you want
#  but it MUST be a MINIMUM of 8 characters and a MAXIMUM of 63 characters.  Consider 
#  using your callsign

# Change this to the correct country you're in - I'm in the US

# Use the 2.4GHz band and disable legacy 802.11b which slows the network down

#  ACS support not enabled in the nl80211 driver for hostapd 2.3 so you cannot
#  use channel=0.  As such, try to determine the least used channel around you 
#  It might be worth noting that HAMs with our amateur radio license give us
#  special high power privileges on channel 1.  Though you'll need a high power 
#  Wifi amp to use it, you might as well start there
#  You can also use the next sections recommendations to see what might be 
#  a better channel to use but for now, use channel 1

# Accept all MAC addresses

# Use WPA authentication ONLY

# Require clients to know the network name

# Enable Wireless MultiMedia class of service (WMM)

# Enable 802.11n support

# Enable 40MHz channels with 20ns guard interval

# Use WPA2 wireless security only

# The network passphrase

# Use a pre-shared key

# Use AES, instead of TKIP

30.c Temporarily testing the AP Wifi system out

Ok, you should have the basis of a working Wifi setup.  To test it, try running the hostapd service
manually by running the following:

   sudo /usr/sbin/hostapd /etc/hostapd/hostapd.conf &
   Configuration file: /etc/hostapd/hostapd.conf
   Failed to create interface mon.wlan0: -95 (Operation not supported)
   wlan0: interface state UNINITIALIZED->COUNTRY_UPDATE
   wlan0: Could not connect to kernel driver
   Using interface wlan0 with hwaddr b8:27:eb:0a:50:6e and ssid "ki6zhd-ap"
   wlan0: interface state COUNTRY_UPDATE->ENABLED
   wlan0: AP-ENABLED

   If you see something like the above where it ends in "wlan0: AP-ENABLED", things are looking GOOD.  
   You can also run "ifconfig wlan0" which should now have an IP address on it:

      ifconfig wlan0
      wlan0: flags=4163  mtu 1500
        inet  netmask  broadcast
        ether b8:27:eb:0a:50:6e  txqueuelen 1000  (Ethernet)
        RX packets 52  bytes 7688 (7.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 14  bytes 1787 (1.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
   Go ahead and try enabling Wifi on your desired Wifi client device (like a smartphone) where
   it should see your new Rpi based Access point as named above.  If you do see it, that's good but 
   don't bother trying to connect to it just yet as DHCP isn't configured on your Raspberry Pi just 
   yet.  If you do try, your remote Wifi device should associate but hang on waiting to get an IP 

   If the test was successful, Type in the following to foreground the hostapd program and then exit it:
   fg %1

   If the above tests DIDN'T WORK, you can try a few things:

     1) You might have an incompatible Wifi channel configured.  Maybe you're seeing
        ""ACS: Unable to collect survey data" where you've configured Automatic Channel Selection 
        (ACS).  Unfortunately, ACS does not work in hostapd v2.3 and the nl80211 driver so a 
        setting of "channel=0" or "channel=acs_survey" will *not* work.  Set a channel of say
        1 through 11.

     2) run the "raspi-config" program and make sure the following areas are properly set
        for your region (I'm in the US):

           Internationalization Options
              +--> Change Wi-fi Country --> US

     3) Update your RPi v3's firmware using "rpi-update".  Once complete, reboot your Rpi v3
        or Rpi Zero W and try the above steps again

Assuming things worked OK in the above tests, we now need to enable this configuration file.  Edit the 
following file, and remove the # in front of the following line:

   sudo vim /etc/default/hostapd

   | Channel Tuning:                                                                       |
   |                                                                                       |
   |  If you're worried about the Wifi channel you selected above, you can look at look at |
   |  what other wifi networks are around you and their signal strength by running:        |
   |                                                                                       |
   |      iwlist wlan0 scanning | less                                                     |

Back to it... now we need to configure DNSMasq:

   | NOTE: New recent issue - 10/26/17                                                                  |
   |                                                                                                    |
   |    There has been a recent issue seemingly introduced with a recent Raspbian patch where           |
   |    dnsmasq won't start.  Specifically, the error you'll see is:                                    |
   |                                                                                                    |
   |       dnsmasq: failed to create listening socket for Cannot assign requested address |
   |                                                                                                    |
   |    The issue seems to be a race condition where hostapd isn't required to be fully up before       |
   |    dnsmasq comes up.  A temporary solution is to # out the line "bind-interfaces" line in the      |
   |    dnsmasq.conf file below.  I am actively researching how to fix this within SystemD but this     |
   |    may take some time.                                                                             |

   NOTE#2:  There are a LOT of configuration options in the default dnsmasq.conf file.
            If you know what all these items do, feel free to customize the settings
            but I've only tested the below changes

   NOTE#3: Be sure to change the IP address here to match the static IP address 
           you set above

  sudo vim /etc/dnsmasq.conf 
  # Don't resolved non-FQDN hostnames  

  # Never forward addresses in the non-routed address spaces.  

  # Use interface wlan0  

  # Explicitly specify the address to listen on  

  #Disable DNS and DHCP from running on the wired Ethernet interface

  # Bind only to the defined interface so other interfaces don't get unwanted traffic
  #   This is INTENTIONALLY commented out per the comment above

  # Assign IP addresses between and with a 4 hour lease time 

  #NOT sure if we need this - dnsmasq should use DNS servers it sees in the resolv.conf file
  #server=       # Forward DNS requests to Google DNS  

Next, if you configured the IPTABLES firewall from the section above, you'll need to 
update the firewall ruleset to now enable DHCP for the wlan0 interface.  It's also worth
noting that I'm *NOT* enabling NAT here to allow Wifi devices to access say the Internet
via the Rpi's wired eth0 interface.  This is NOT not the purpose of this document. 

   NOTE: if you really want to do that, review the previous iptables section which actually
         has the require lines commented out.  Then, carefully the bottom of the next section 
         area at the bottom of this section on how to complete the setup

Anyway, let's make the minimum changes to allow DHCP on wlan0 by do the following:

   #First, make a backup of the running rules now
   sudo cp /etc/iptables/rules.v4 /etc/iptables/iptables.checked

   #enable the following line in the rules.v4 file and ADD the following
   # line BELOW the line:
   #     -A INPUT -p udp -m udp --sport 67 --dport 68 -j ACCEPT

   sudo vim /etc/iptables/rules.v4
   -A INPUT -p udp -m udp -i wlan0 --sport 68 --dport 67 -j ACCEPT

Load the new ruleset with the following commands (previously discussed in
the IPTABLES section):

   sudo su
   /usr/local/sbin/firewall-confirm &
   touch /tmp/fwok

If that worked ok, let's make this new firewall ruleset the new default:

   sudo cp /etc/iptables/rules.v4 /etc/iptables/iptables.checked

30.d Final testing of the Wifi system

Ok, we should be set for a full test to make sure the Raspberry Pi acts as a full Wifi AP:

  1. Temporarily start up hostapd and dnsmasq

     #Running these commands won't give any specific output
     #Do the individual commands to avoid some strange behavior on Stretch
     sudo systemctl stop hostapd
     sudo systemctl start hostapd
     sudo systemctl restart dnsmasq

  2. Run "ifconfig" and confirm you see:

     2.a - does the wlan0 interface exist?
     2.b - does it have the expected IP address on it ( in this example

  3. Run "iwconfig" and confirm you see:

     3.a - does the wlan0 interface exist?
     3.b - does it show "Mode:Master" meaning it's in Access point mode?

Assuming all of the tests above PASSED above, now go back to your desired Wifi 
device (smartphone, etc) and try to associate to your Raspberry Pi AP using the 
configured Rpi's configured SSID and WPA2 passphrase:

    - Did the device associate on the Wifi level (connected but didn't get an 
      IP address just yet)?

    - Did it get an IP address?  On my Android device, go into the Android system
      settings, go to the Wifi setup area and in there, I click on the three vertical
      ". . ." icon in the very upper right part of the screen.  There I select 
      "Advanced Wifi", and scroll down to the very bottom until I see the Wifi Ethernet
      MAC address and it's IP address.  In this example, I see which
      is in the expected range!

    - I now recommend to install use an SSH client on your device to connect to the Raspberry
      Pi at  I use the Android ConnectBot which works pretty well except it's
      use of the F-keys is broken.  You might consider using JuiceSSH as an alternative.

      Using the username and password you created in an earlier section of this doc, can
      you log in?

         NOTE:  Using your smartphone as a display and a keyboard will work
                in a pinch but it's pretty cumbersome and doesn't work well
                for full-screen programs like Linpac.  Consider buying 
                a compact bluetooth keyboard and pairing it with your
                smartphone.  At this point, you should be able to hide 
                the virtual keyboard on your smartphone and use the BT 
                keyboard for all your input needs.  Pretty slick!

If everything worked up to this point and you want this Wifi Ap system to work 
at every boot up, let's enable it permanently:

   #Enable the Systemd services to start on boot
   sudo systemctl enable hostapd
   sudo systemctl enable dnsmasq

Ok.. now reboot your Raspberry Pi with either:

   sudo /sbin/shutdown -h now


   Press the shutdown button you build and created in the previous section
   of this doc

Wait until the green LED on the Rpi blinks 10 times quickly and then goes out.
Now remove power from the Raspberry Pi.  Next, check that on your remote Wifi device,
you no longer see your Rpi's Wifi SSID.

Now re-connect the USB power to the Raspberry Pi:

   - Do you see the Rpi Wifi SSID?

   - Try connecting to it and make sure that the Wifi system came back 
     up as you'd expect!

  NOTE:  Check out the HW-Tricks section below in this doc on how you can change 
         the onboard RPI v3 LEDs from being the SD card read/write activity indicator
         to say Wifi network activity, etc.  Pretty slick!  Just too bad there is
         only one LED to use!

  | TBD: Similar to the old wireless section shown below, add a switch |
  | #1   on a few GPIO pins to switch the Wifi connection between      |
  |      acting as an AP vs. act like a wireless client and associate  |
  |      to a nearby AP                                                |

  | TBD: Notes on how to add an external Wifi antenna to the Rpi v3    |
  | #2   (not 3B+) for better reach - read more for now at             |
  |                                                                    |
  | |

Per the beginning paragraph in that section, this setup does NOT provide the associated
wifi devices any Internet access.  You *can* optionally enable IP forwarding on your Rpi3
which will share it's Internet access to all associated Wifi devices.  I'm not going to detail 
this as it's not my goal but if you want to enable it, you'll need to

   -  enable IP forwarding by adding the line "net.ipv4.ip_forward=1" to the /etc/sysctl.conf 
      file.  You can temporarily test this by running the command:
         sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"

   - uncomment out the masquerade NAT rule in the iptables ruleset.  See the above referenced
     rules.v4-test file and remove the # in front of the relevant three lines and then enable
     the temporary ruleset with:

          sudo iptables-restore < rules.v4-test

   - If everything works, make sure you enable the new firewall ruleset to 
     load every time with:

       sudo iptables-save < /etc/iptables/rules.v4

30.e Configure simultaneous Wifi client and Wifi AP connectivity

| IMPORTANT:                                                                       |
|            This section is a work in progress and it currently does NOT work and |
|            actually breaks all Wifi access.                                      |
|                                                                                  |
| +--------------------------------------------------+                             |
| | CURRENT STATUS -- Sort of works, sort of broken  |                             |
| |                   see the bottom of this section |                             |
| +--------------------------------------------------+                             |

   One excellent feature of the new Raspberry Pi3/ZeroW hardware is that it's Wifi system can 
   act as both a Wifi client and be a Wifi access point *at the same time*.  This will let you
   connect to the Rpi either directly or through an AP (which usually has Internet access).

To get this "second" connection working, we need some information first.  We need the Ethernet
MAC address of your specific Rpi's wifi chip.  To do that, run:

   root@rpi0w:/etc/hostapd# ifconfig wlan0

   You should see:
   wlan0: flags=4163  mtu 1500
        inet  netmask  broadcast
        ether b8:27:eb:79:82:2c  txqueuelen 1000  (Ethernet)
        RX packets 344  bytes 24486 (23.9 KiB)
        RX errors 0  dropped 1  overruns 0  frame 0
        TX packets 266  bytes 33726 (32.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

See that "b8:27:eb:79:82:2c" string?  That's the MAC we'll need.  

Now, from this point forward, I *highly* recommend you either do this configuration on the Rpi's 
console (connected HDMI monitor and keyboard) or via a wired USB-based Ethernet connection.
If you don't do this, you might loose connection and then break your access to the Rpi.

   We need to create another wifi device to act as the new wifi AP device.  This changes the 
   above sections naming conventions as we'll now have:

      wlan0 - Interface used for connecting to your local AP (this is standard)
      ap0   - Interface used for devices connecting TO the Rpi

   One thing I did notice in writing this section up is that the previous section to make
   the Rpi act as an AP, it output of "iw dev" shows the wlan0 device STILL as a wifi client
   (managed) when in fact it was acting as an AP.  I also noticed that you CANNOT have two
   "managed" devices aliased to the same physical device.  In the future, I might reverse
   everything around in the above section but for now, I'm not going to do that.

Let's create the "ap0" device name by editing the right Udev file:

   sudo vim /etc/udev/rules.d/70-persistent-net.rules
   #Add the following line with substituting in your correct MAC address in both places
   SUBSYSTEM=="ieee80211", ACTION=="add|change", ATTR{macaddress}=="b8:27:eb:79:82:2c", KERNEL=="phy0", \
RUN+="/sbin/iw phy phy0 interface add ap0 type __ap", \
RUN+="/bin/ip link set ap0 address b8:27:eb:79:82:2c"

Next, we are going to STOP using dhcpcd on wireless interfaces but if you plan on connecting an 
Ethernet USB-dongle to the Rpi, I add the "eth0" statement to the /etc/dhcpcd.conf file and 
towards the end:
   #These #s will disable the previous wlan0 DHCP scope as configured in the previous section
   #interface wlan0
   #static ip_address=
   #static routers=
   #static domain_name_servers=

   #This will enable DHCP on the eth0 interface
   interface eth0

Now, edit the /etc/dnsmasq.conf file and now make the lines read:
   #If you plan on allowing Rpi-connected Wifi devices to get 
   # internet access from the Rpi itself, comment out the next line
   #We now need this option

Now, edit the /etc/hostapd/hostapd.conf file and now make the lines read:
   #Change this if you aren't in the US
Next, we need to change the the /etc/wpa_supplicant/wpa_supplicant.conf file to connect your 
local Wifi AP (when it's in range):
   #Change this if you aren't in the US
   ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev

   #Your first AP you might want to connect to if it's in range
   #Change the SSID and PSK lines to match that AP's credentials

   #Your second AP you might want to connect to if it's in range
   #Change the SSID and PSK lines to match that AP's credentials

Now connecting all this together, edit the /etc/network/interfaces file

   auto lo
   auto ap0
   auto wlan0

   iface lo inet loopback

   #If you plan on having an Ethernet USB-dongle attached
   auto eth0
   allow-hotplug eth0
   iface eth0 inet dhcp

   allow-hotplug ap0
   iface ap0 inet static
       hostapd /etc/hostapd/hostapd.conf

   allow-hotplug wlan0
   iface wlan0 inet manual
       wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf

   iface AP1 inet dhcp
   iface AP2 inet dhcp

Now, per the details at
there is a race condition of the wlan0 interface coming up first and blocking the ap0 interface
from loading.  For now, here is the cited work around but I bet there is a way to delay this
wlan0 bring up via Systemd (needs some research):

   echo "running -- 30sec delay"
   sleep 30
   sudo ifdown --force wlan0 && sudo ifdown --force ap0 && sudo ifup ap0 && sudo ifup wlan0
   #IPMASQ NAT rules removed

   Now make it executable with:
   chmod 700 /usr/local/sbin/

To make this script run at boot, add the following to the /etc/rc.local file:

   #Bring up the Wifi workaround script
   /usr/local/sbin/ &

Assuming you setup the Iptables firewall per this document, you'll need to allow:

  - allow DHCP client traffic on the new ap0 interface
  - allow DHCP server traffic on the wlan0 interface
  - allow DNS client traffic on the new ap0 interface
  - SSH traffic was already allowed on all interfaces before

Edit the /etc/iptables/rules.v4 file and add the following lines:

   -A INPUT -p udp -m udp -i ap0 --sport 68 --dport 67 -j ACCEPT
   -A INPUT -p tcp -m tcp -i ap0 --dport 53 -j ACCEPT
   -A INPUT -p udp -m udp -i ap0 --dport 53 -j ACCEPT
   -A INPUT -p udp -m udp -i wlan0 --sport 67 --dport 68 -j ACCEPT

Now go re-run the script to activate those changes.  If you don't
remember how to use that script, re-read the end of that section now so you don't
lock yourself out of your own Pi!

Based on the guide found at:

| CURRENT STATUS -- Sort of broken                                                            |
|                                                                                             |
|   I currently use a USB to Ethernet adapter to run updates, etc. as wlan0 operation         |
|   is currently unreliable                                                                   |
|                                                                                             |
| * So what's busted?                                                                         |
|                                                                                             |
|   Upon boot, the ap0 interface comes up fine and I can both associate to it and             |
|   SSH into the Rpi0w.  The strange thing is that the wlan0 interface doesn't automatically  |
|   come up.  If I issue:                                                                     |
|                                                                                             |
|      sudo ifconfig wlan0 up                                                                 |
|                                                                                             |
|   everything then seems to work.. for a while.  After some random period of time            |
|   any association in the ap0 interface seems to stop responding (say from a smartphone      |
|   to the Rpi0w).  If I then cycle the Wifi on my phone, I can re-establish a connection     |
|   to the Rpi0w but now, the association from the rpi0w to remote AP via the wlan0 interface |
|   keeps flapping over and over.                                                             |
|                                                                                             |
|   To stop this, I have to either reboot (to disable the wlan0 interface from coming up)     |
|   edit the /etc/network/interfaces file and disable the two AP lines like:                  |
|                                                                                             |
|      #iface AP1 inet dhcp                                                                   |
|      #iface AP2 inet dhcp                                                                   |
|                                                                                             |
|      sudo ifconfig wlan0 down                                                               |

31. DEPRECATED: Configure your Rpi Wifi in Adhoc mode using the RTL8192 Wifi devices

   | IMPORTANT: 09/04/17 (was 08/14/16)                                                       |
   |                                                                                          |
   | This entire section and all of it's sub-sections are DEPRECATED!                         |
   |                                                                                          |
   | Why?  The RTL8192 code support for Linux has never been properly maintained and is most  |
   | likely probably completely broken now Raspbian Stretch and Jessie .  Consider buying a   |
   | Rpi v3 or Zero W with built-in Wifi instead and read the above section on how to get it  |
   | going.                                                                                   |
   |                                                                                          |
   |  Keeping this section around for posterity and it might help some Raspbian Wheezy users  |

Configure your Rpi Wifi in Adhoc mode using the RTL8192 Wifi devices

   - I have a Wifi device that has the 8192cu chipset but so many sites only talk to Atheros 
     (ath9k) and Broadcom (b43) chipsets and rarely give details about Realtek chips.  Why?
     It seems that Realtek has never really support with Linux.  

   - Various websites go and recommend to configure the use of the rtl871xdrv driver and not the rtl8192cu 
     driver that comes with the Raspbian distro but never say WHY

   - Many websites on the Internet to using a custom hostapd binary install from unknown sources to fix 
     known/broken code in the linux kernels 

   - Older pages talk about using different mechanisms to configure Linux to be a Wifi AP:

      - hostapd vs wicd
      - using bridging vs routing (uses iptables)
      - dnsmasq vs dhcpd

This is crazy!  Why is this?  Well, a few things I've learned in Aug, 2016:

   - It seems that Realtek never bothered to offer support of hostapd after they initially 
     contributed to the linux kernel and hostapd 0.8.x back in 2012:

   - Beyond Realtek's initial support for some chips in the RTL 871x driver (no idea why the 
     different chip family number), it seems that the RTL8188cus drivers supports *all* rtl81xx 
     based support (including the rtl8188 and rtl8192cu).  A great write up on the background of
     all this can be found here:

Anyway, the very top of this post talks to a scripted
setup to bring in new drivers for the TP-Link TL-WN725N V2 which uses the RTL8192cus chip.  This will work just fine
for my UL-Link device.

   # Recommended: hostapd and dnsmasq

      HostAP and a LB-Link BL-LW05-AR5 802.11n USB wifi device

   Other helpful sites:


The general recommendation for a Rpi based AP is to use hostapd and dnsmasq.  If you need more
advanced capabilities, you can consider replacing dnsmasq with the ISC dhcpd service instead

Anyway, for now, let's move forward with the Hostap + dnsmasq approach

31.a Picking what Wifi hardware to use:

   | 08/14/16                                  |
   | This section is DEPRECATED as the RTL8192 |
   | is not well maintained.  Consider buying  |
   | a Rpi v3 with built-in Wifi instead and   |
   | read the above section                    |

Not all Wifi chipsets are supported by Linux so it's important that you buy HW that will both
work under Linux but also support AP mode (not all HW does).  It's generally recommended to buy
a Wifi device that uses the Realtek RTL8188CUS chipset.  See
for a comprehensive list of devices that are known to work.

Let's confirm the hardware you have is compatible so go ahead and plug in your Wifi dongle into 
a powered USB hub that's connected to your Rpi

#   NOTE:  Do **NOT** plug the dongle directly into your Rpi or it will most likely reboot
#          due to the excessive power draw.  You *must* use an alternative way to power the
#          AP dongle (such as a USB powered hub or maybe you're using a Wifi HATT with external
#          power support

First, confirm your Wifi USB device is seen by running:

   dmesg | less

This is what one of these very small USB Wifi nubs look like from Edimax:
[667667.424884] usb 1-1.2.1: New USB device found, idVendor=7392, idProduct=7811
[667667.424928] usb 1-1.2.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[667667.424949] usb 1-1.2.1: Product: 802.11n WLAN Adapter
[667667.424968] usb 1-1.2.1: Manufacturer: Realtek
[667667.424998] usb 1-1.2.1: SerialNumber: 00e04c000001
[667668.197127] usbcore: registered new interface driver rtl8192cu

This is what one of these larger LB-Link BL-LW05-AR5 802.11n Wifi dongles with an attached 5dbi large Wifi antenna 
looks like:
[606160.906330] usb 1-1.3.1: new high-speed USB device number 6 using dwc_otg
[606161.008090] usb 1-1.3.1: New USB device found, idVendor=0bda, idProduct=8176
[606161.008121] usb 1-1.3.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[606161.008138] usb 1-1.3.1: Product: 802.11n WLAN Adapter
[606161.008154] usb 1-1.3.1: Manufacturer: Realtek
[606161.008188] usb 1-1.3.1: SerialNumber: 00e04c000001
[606161.231855] usbcore: registered new interface driver rtl8192cu
[606161.861557] IPv6: ADDRCONF(NETDEV_UP): wlan0: link is not ready

Next, see if the OS has automatically created the "wlan0" interface:


wlan0     Link encap:Ethernet  HWaddr 44:33:4c:58:dd:fa
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

LEGACY notes for Realtek RTL8192cu support on Raspbian Wheezy (NOT recommended):
    If you use a Wifi USB dongle using the Realtek RTL8192cu (aka RTL8188CUS) chipset like
    the tiny Edimax EW-7811n device and you're using Raspbian Wheezy (not Jessie), you're 
    going need to read this below URL.  Specifically, as of 06/07/15, hostapd 1.0-3+deb7u2 
    was broken for the RTL8192 chip but was resolved in Jessie.  It's possible to  update 
    the hostap binary to fix this
    This URL also gives more details and a possibly more supportable approach:

    Here are some of my legacy notes for this older install:

       If using a Realtek 8192 device, you need an alternative hostapd daemon:

          sudo mv /usr/sbin/hostapd /usr/sbin/hostapd.orig

       Next, you need to download the updated hostapd binary but it's too large to fit
       in the /tmp RAM drive.  As such, lets put it elsewhere:

          cd /var/tmp

          Or and alternative download site:

          sudo mv hostapd /usr/sbin
          sudo chmod 755 /usr/sbin/hostapd

31.b Wifi AP with Direwolf

   | 08/14/16                                  |
   | This section is DEPRECATED as the RTL8192 |
   | is not well maintained.  Consider buying  |
   | a Rpi v3 with built-in Wifi instead and   |
   | read the above section                    |

Ok, assuming you're using *Raspbian Jessie* here, let's install the required software:

   sudo apt update
   sudo apt install firmware-realtek dnsmasq hostapd

Next, confirm the Wifi device can be interrogated:

   sudo iwconfig
   wlan0     unassociated  Nickname:""
             Mode:Auto  Frequency=2.412 GHz  Access Point: Not-Associated
             Retry:off   RTS thr:off   Fragment thr:off
             Encryption key:off
             Power Management:off
             Link Quality:0  Signal level:0  Noise level:0
             Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
             Tx excessive retries:0  Invalid misc:0   Missed beacon:0

   lo        no wireless extensions.

   ax0       no wireless extensions.

   eth0      no wireless extensions.

Confirm that your Wifi device can act as an AP as not all can as described above
If this command doesn't report back with a "0", you need to use a different Wifi 
USB device:

   sudo iwconfig wlan0 mode master
   echo $?

   If your HW doesn't' report a "0" above, read the above URLS as well as
   this HW identification URL:

AP or client mode
There are a few ways to do this but I chose to use a GPIO switch to select if the 
Wifi should be an AP or a client.  In researching around, it sounds like some Realtek
devices can actually support AP and Client mode at the same time (STA+AP):

That's overkill for my needs but I thought I'd mention it.  Anyway, we need to disable 
the OS from starting the wlan0 device by default.  With changing this, we can start this 
function from /etc/rc.local.

   #For Jessie
   sudo systemctl disable hostapd

   #For Wheezy
   sudo update-rc.d hostapd disable

Now create and edit the /etc/hostapd/hostapd config file

   zcat /usr/share/doc/hostapd/examples/hostapd.conf.gz > /etc/hostapd/hostapd.conf

Now edit the file with the following settings:

   vim /etc/hostapd/hostapd.conf
   #Wireless device name

   #The bridge interface to connect to eth0

   #Wifi device driver depends on your USB device found above
   #  I'm using the LD-Link BL-LW05-AR5 device
   #  EXPERIMENT - 08/13/16 - for a rtl8192cu device, do NOT specify ANY driver
   #                          and let it auto-discover

   #Control interface for hostapd

   #SSID announcement for this device - change this to be whatever you want

   #Specific country you are locate in - this is for the Unite States

   #limit the allowed frequencies to specified country

   #This allows 802.11G but this will impact the performance of 802.11N networks
   #  If Wifi compatibility is more important than performance; set this to "g"

   #enable 802.11n if your hardware supports it

   #Select the least used Wifi channel in your area - ch 0 will auto-select on the
   #  most available channel - alternatively, use 1,6,11 for the US

   #How often to send SSID broadcasts

   #Station MAC address -based authentication
   # 0 = accept unless in deny list
   # 1 = deny unless in accept list

   #If you want to hide your SSID broadcasts, set this to 1

   #allow WPA/WPA2 only - # 1=wpa, 2=wep, 3=both

   #enable WPA2 only

   #enable multi-media priority

   #disassociate remote sessions that are taking on high errors
   #  enable this for better battery life; disable this to keep the link up at all costs

   #The WPA2 64 character HEX key or 8 to 63 character passphrase for your network

   #Use PSK and not EAP

   #Use AES encryption

   #Support high performance wifi
   #  HT40+ : support both 20 MHz and 40 MHz BW with secondary channel ABOVE the primary channel
   #  HT40- : support both 20 MHz and 40 MHz BW with secondary channel BELOW the primary channel
   #  SHORT-GI-40 : Short GI for 40 MHz
   #  RX-STBC12 : one or two spatial streams

   #Don't refuse association with remote client if they don't support HT Phy negotiation

Now update the SysV config startup script to load a custom config file:

  sudo vi /etc/default/hostapd

# Next, edit the /etc/network/interfaces file
auto lo eth0 wlan0
iface wlan0 inet static
#allow-hotplug wlan0

  - Skip this section for now
Next, it's very important to disable Network-Manager from trying to manage this device 
From the output of the "ifconfig" command above, note the MAC address of your Wifi device
and change the MAC address in this file
vim /etc/NetworkManager/NetworkManager.conf

Set your Geo

   iw reg set US

Next. we need to configure the Bridge interface which will link the eth0 and wlan0 interfaces
together.  Add the following lines to the interfaces file and you can change the management IP 
address of this bridge group to whatever subnet you like:

vim /etc/network/interfaces
   auto br0
   iface br0 inet static
           bridge_ports none
           bridge_fd 1
           bridge_hello 1
           bridge_stp on

Go ahead and manually start it with:

   ifup br0

#If things don't work right, try debugging with:
service hostapd stop
hostapd -dd /etc/hostapd/hostapd.conf

# Legacy Wifi Ad-Hoc approach (works with Motorola Droid2 running Android GingerBread
# (does not work with LG G3 running Android Kitkat or Lolipop
#    see /usr/local/sbin/ for all details

sudo apt install dnsmasq dnsmasq-base dnsmasq-utils
#We only want it to start manually
update-rc.d dnsmasq remove

vim /etc/dnsmasq.conf

#Make the required dnsmask dir if it was removed
mkdir /var/run/dnsmasq/

sudo nano /etc/network/interfaces
#if there is any other line that has "auto lo" in it, REMOVE it

auto lo eth0 wlan0
iface lo inet loopback

iface eth0 inet dhcp

#This is intentionally set to manual to support the selection of client or server AP mode
iface wlan0 inet manual

allow-hotplug wlan0

Verify / Update the system's hostname:

  - Edit the /etc/hostname file and put the name of your raspberry Pi in there.  For example,
    I'm naming my unit "rpi3" so the line would read:


  - Next, edit the file /etc/hosts and update the line that has "" to reflect your 
    desired raspberry pi fully qualified hostname (FQDN).  For example, I'm naming my unit 
    "" so the line would read:    rpi3    localhost

  - Now add your desired Rpi's hostname alias for local wireless network address

  - Add addresses to reflect any IP addresses enabled in the /etc/ax25/ax25ipd.conf file
     --                 f3kt-0          iz3lsv-0                 on4hu-0                 k4gbb-0

  - Confirm that the host recognizes it's new hostname with running:

       hostname -f

#Update the FBB stuff
  update the details in /etc/ax25/fbb/beacon0.sys

  port.sys needs updating too --RESEARCH--

  dir /etc/ax25/fbb needs sed search/replace for all CAPS F6BVP

#Update the default editor
update-alternatives --config editor

# ----------------

#Now configure your primary Wifi interface
ifconfig wlan0 down
sudo wpa_cli

#  Note: if this program won't start, pull out the USB Wireless device and put it 
#        back in again that should re-prod NetworkManager to get it running

#Now, get the name of any pre-configured wireless devices and put them into the 
# start-adhoc script
 --> scan
 --> scan-results
 --> add_network
     --> set_network 0 ssid "enter-your-previously-shown-BSSID-here"
     --> set_network 0 psk "enter-your-wpa2-key-here"
     --> enable_network 0
     --> save_config

Get a copy of /usr/local/sbin/

chmod 700 /usr/local/sbin/

32. Various Rpi management, LED and Bluetooth tricks on the Rpi v3

This section covers various little sub-projects including:

   - Hardware review
   - Changing the behavior of the Rpi LEDs
   - Setting up Bluetooth for serial port access to a Kenwood TH-D74 radio

32.a - Monitoring the Raspberry Pi hardware and other scripts

I've posed various scripts to manage the hardware of your Raspberry Pi:

   - Monitor the CPU clocking, hardware temps, and serial number of your Raspberry Pi

     Get the script and required tools by running:

        #Install the classic calculator to support doing numeric conversions
        sudo apt install bc

        cd /tmp
        chmod 755
        sudo mv /usr/local/bin

     Now try running it:

     The output should look something similar to the following:
        Current CPU speed governor: (valid is 'powersave', 'ondemand'):

        Current CPU frequency:

        Max allowed frequency

        SOC Temp (in Celsius) - DD.ddd
        GPU temp

        Rpi Serial number, model firmware and Warranty bit (MSB):
        Serial          : 000000005851234b
        Revision        : a22082
           value of a22082 is Pi 3 Model B - 1GB - made at Embest, China
        Broadcom firmware version:
        Aug 22 2017 14:20:40
        Copyright (c) 2012 Broadcom
        version eb51b8b84ec11d98562dfbb7be53cdd216c0ea4c (clean) (release)
        Confirm system will clock up to max CPU speed (turbo mode) by loading the CPUs and report new CPU frequency when at load


   Here are more scripts are available for doing specific tasks (some already mentioned in previous
   sections of this doc):

      - Ensure the new IPTABLES firewall takes place and doesn't lock you out (covered in the firewall 
        section of this document):

      - Clean up the file system a bit and remove old kernels

      - Blank empty space for smaller system backups and take an image copy of your removed Rpi 
        micro-SD card for backup reasons

      - Mounting and Unmounting external USB hard drive with a Linux LVM/EXT3 file system

Look in to see other potentially interesting 
scripts and tools as I post them!

32.b - LED tricks with the onboard Raspberry Pi LEDs

With the Rpi v3, the purpose of the red led (power) and green led (sd card)
is now programmable.  Specifically, with the green LED, you can can indicate any
of the following functions.  In this specific case, you can use the green
LED to show Wifi activity:

   #show the possible LED options with your RPI hardware and current firmware 
   #  Options may change over time
   cat /sys/class/leds/led0/trigger
   cat /sys/class/leds/led1/trigger

   * Any items wrapped with "[ ]" means it's active

     none - does nothing
     kbd-scrollock  - status from the controlling keyboard
     kbd-numlock    - status from the controlling keyboard
     kbd-capslock   - status from the controlling keyboard
     kbd-kanalock   - status from the controlling keyboard
     kbd-shiftlock  - status from the controlling keyboard
     kbd-altgrlock  - status from the controlling keyboard
     kbd-ctrllock   - status from the controlling keyboard
     kbd-altlock    - status from the controlling keyboard
     kbd-shiftllock - status from the controlling keyboard
     kbd-shiftrlock - status from the controlling keyboard
     kbd-ctrlllock  - status from the controlling keyboard
     kbd-ctrlrlock  - status from the controlling keyboard
     [mmc0]         - activity on the microSD card slot
     mmc1           - activity on the Wifi interface
     timer          - monitor the timer 
     oneshot        - not sure on this one
     heartbeat      - monitor the broadcom watchdog timer
     backlight      - status of the DSI backlight
     gpio           - monitor a specific GPIO pin
     cpu0           - status of cpu0
     cpu1           - status of cpu1
     cpu2           - status of cpu2
     cpu3           - status of cpu3
     default-on     - on 100%
     input          - not sure what this is
     rfkill0        - show if the BT signal is admin disabled via rfkill
     rfkill1        - show if the wifi signal is admin disabled via rfkill

  To change the green LED to show Wifi activity instead of microSD activity, 
  issue the command:

    echo mmc1 > /sys/class/leds/led0/trigger

  This will be a temporary setting and the Rpi will revert to it's stock behavior
  after a reboot.  If you want to make this change permanent, add this command
  to the /etc/rc.local script.

  You can learn more about controlling the two primary LEDs here:

  You can learn about controlling the wired Ethernet jack LEDs here:

32.c - Setting up Bluetooth on the Rpi for using Bluetooth keyboards


This section covers how to associate to Bluetooth keyboard to interact with the Rpi 
while viewing the display via the HDMI port.  This is all assuming you DIDN'T disable 
the bluetooth support on your Raspberry Pi (Rpi0W, 3, 3+, 4) via the raspi-config 
program in a previous chapter of this doc.

   NOTE:   If you want a BT keyboard to be used with your smartphone to control
           SSH sessions to your Raspberry Pi, you need to pair the keyboard to your 
           *smartphone* instead (not the Rpi itself).

   | IMPORTANT DETAIL: 09/04/17                                                   |
   |                                                                              |
   | I have read in multiple places that the combo Wifi+Bluetooth support on the  |
   | RPi running simultaneously is not very reliable when either the wifi link or |
   | the bluetooth links are behing heavily used.  You might see many wifi        |
   | disassociations and re-associations on the Wifi and/or Bluetooth side        |
   | because of this.  It sounds like this could be limitations on the Raspberry  |
   | Pi hardware but I personally haven't encountered this.  Maybe this issue can |
   | be fixed through newer firmware for the Raspberry Pi but I haven't seen much |
   | movement here.  Beware!                                                      |

   #Status of the BT interface
   sudo hciconfig -a
   hci0:   Type: BR/EDR  Bus: UART
           BD Address: B8:27:EB:xx:xx:xx  ACL MTU: 1021:8  SCO MTU: 64:1
           UP RUNNING
           RX bytes:717 acl:0 sco:0 events:42 errors:0
           TX bytes:1532 acl:0 sco:0 commands:42 errors:0
           Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87
           Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
           Link policy: RSWITCH SNIFF
           Link mode: SLAVE ACCEPT
           Name: 'rpi3'
           Class: 0x000000
           Service Classes: Unspecified
           Device Class: Miscellaneous,
           HCI Version: 4.1 (0x7)  Revision: 0xb6
           LMP Version: 4.1 (0x7)  Subversion: 0x2209
           Manufacturer: Broadcom Corporation (15)

   #You can also display the local MAC address with this interactive program
   sudo bluetoothctl
   #See any pairable bluetooth devices around you (try setting one of your nearby
   # bluetooth devices into discovery mode and give this command a try:
   hcitool scan
   Scanning ...
        00:1F:22:44:17:18       Ultrathin Keyboard Mini

   From this point there are TWO ways to use Bluetooth:

      - The Raspberry Pi reaches out to the remote BT device to connect

      - The remote BT device reaches out to the Rpi to connect

   Here is an example Have the Rpi reach out and attach to a remote BT device (a keyboard):
   # To pair to this BT wireless keyboard, use the following command which is more of an 
   # interactive command prompt:
   sudo /usr/bin/bluetoothctl

      #Issue the following commands

      #Show available BT controllers

      #Give more details on the local controller (change this example MAC address to match yours)
      show B8:27:EB:AA:AA:91

      #Show what might already be paired

      #Enable BT pairing

      agent on

      #Scan for available BT devices
      scan on

      # Initiate the pairing to the keyboard found above (change the BT mac address with
      # the device found in your area
      #   NOTE: If you cannot read the displayed "Passkey" text, you need to 
      #         change your terminal's background font color to something other than white.
      #         Alternatively, try copying that line and pasting it into a different terminal
      #         window to see if you can read it
      pair 00:1F:22:35:17:18

      #  If challenged for a "PIN code", enter that "PIN code" on your BT keyboard 
      #  and press ENTER on the bluetooth keyboard

      #Remember the device
      trust 00:1F:22:35:17:18

      #reconnect to the device on reboot
      connect 00:1F:22:35:17:18

      #to permanently remove a pairing
      disconnect 00:1F:22:35:17:18
      remove 00:1F:22:35:17:18

      #to exit bluetoothctl but leave BT fully working 

32.d - Setting up a serial console using a Bluetooth connection

WIP: This section is still being worked on : this all works but the automatic startup after 
     a reboot is not completed

Serial consoles are a way to login and troubleshoot your system when the usual network type access via
say local HDMI console, eth0, Wifi, etc. is not working or not available.  With Linux serial console, 
there are TWO general types of consoles:

   - consoles with the kernel booting details - this is ONLY available via the GPIO-pin based
     serial port

   - console without the kernel booting details - this can be on any serial port including bluetooth
     connections, USB to serial adapters, etc

NOTE:  This section CONFLICTS with the TNC-Pi section mentioned later in this document as the TNC-Pi
       uses the GPIO serial pins for it's default configuration.  You CAN configure the TNC-Pi to 
       alternatively use the I2C-bus for communications but that's not detailed in this document.

NOTE#2: This section does NOT check nor test any other uses of Bluetooth such as Bluetooth audio, etc.
        If you do run into issues, I can try to give you a hand to address your issue but it's possible
        that both Bluetooth serial and Bluetooth audio running at the same time might not be possible.

Some details from this section came from the following URL:

   This documentation expanded upon it to make the connections more secure as well as provide
   troubleshooting steps along the way to make sure things are working as expected

To get a Bluetooth serial console session (without kernel booting text) working, follow these steps:

   1. Enable the serial console option on the Rpi via the raspi-config tool

           sudo raspi-config --> Interface Options --> Serial Port --> YES --> Ok --> Finish

       NOTE:  On older Raspbian releases, you would find this setting in:
              sudo raspi-config --> Advanced Options --> Serial --> YES --> Ok --> Finish

   2. IMPORTANT:  reboot your Raspberry Pi to make sure everything gets enabled

   3. Install some security tools for Bluetooth

      sudo apt install bluez bluez-test-scripts
      cd /usr/share/doc/bluez-test-scripts/examples
      sudo gunzip simple-agent.gz
      sudo cp simple-agent

   4. Confirm you're seeing both the hardware UART and the software UART:

      NOTE:  the number of serial ports on your Rpi depends on which Rpi model you're using.
             For example, below is valid for a Raspberry Pi 3B+ or a Raspberry Pi 0-W:

         ls -la /dev/serial?
         lrwxrwxrwx 1 root root 5 Apr 16 10:43 /dev/serial0 -> ttyS0
         lrwxrwxrwx 1 root root 7 Apr 16 10:43 /dev/serial1 -> ttyAMA0

      In modern versions of the Raspberry Pi OS "Buster", the /dev/serial/ttyAMA0 device is the on-board 
      *hardware* UART mapped to be used with Bluetooth services.  

         NOTE: Some of the newer Raspberry Pi models like the Rpi4 and CM4 have additional hardware UARTs 
               but they aren't available unless you enable alternative DevTree configuration and thus you 
               swap out the use of valuable GPIO, I2C, etc. options for these UART connections.  

      The /dev/ttyS0 is what's call the "mini-uart" or *software* emulated serial port.  This is the serial
      port connected to the GPIO pins.  For serial console needs, this software emulation is usually ok but
      it CAN experience issues.  If the AMA0 device is NOT seen, you need to try using the "sudo raspi-config" 
      step shown above again, check your settings, and then reboot.

   5. Confirm the kernel messages sent to the GPIO-pin based serial console is enabled AND enabled on the 
      correct port.  Look at the /boot/cmdline.txt file and confirm the following text is there:


      If you don't see it, I recommend you try step #1 above again.  If that still doesn't work, you can manually 
      add the text in.  As an example, this is what I have in my system running Raspberry Pi OS "Buster" version:

         dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=4351cdc6-02 rootfstype=ext4 elevator=deadline rootwait

      5.a If you're using the serial console via the UART connected to the GPIO pins and you want to also see the 
          kernel boot up output (won't work via Bluetooth serial consoles), you also need to do the following to 
          the /boot/cmdline.txt file:

             #1. Add the following string to the line

             #2. Make sure the word "quiet" is NOT in that kernel boot line

   5. Make sure there is a getty daemon configured to use /dev/ttyAMA0

      ps aux | grep getty
      If you see something like the following with the "ttyAMA0" device in the output, you're good:
         root       543  0.0  0.3   6600  1828 ttyS0    Ss+  07:17   0:00 /sbin/agetty -o -p -- \u --keep-baud 115200,38400,9600 ttyS0 vt220
         root       546  0.0  0.3   4292  1752 tty1     Ss+  07:17   0:00 /sbin/agetty -o -p -- \u --noclear tty1 linux

      If you don't see the ttyS0 text, re-check the enabling of the serial console above and reboot your Rpi and try again.  

   6. Confirm the Bluetooth system is now working:

      - Either use the command "hcitool dev" to get brief details 

            hci0	B8:27:EB:xx:xx:xx

         or use "hciconfig" to get deeper details:
            sudo hciconfig -a

            hci0:   Type: BR/EDR  Bus: UART
                    BD Address: B8:27:EB:xx:xx:xx  ACL MTU: 1021:8  SCO MTU: 64:1
                    UP RUNNING
                    RX bytes:717 acl:0 sco:0 events:42 errors:0
                    TX bytes:1532 acl:0 sco:0 commands:42 errors:0
                    Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87
                    Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
                    Link policy: RSWITCH SNIFF
                    Link mode: SLAVE ACCEPT
                    Name: 'rpi3'
                    Class: 0x000000
                    Service Classes: Unspecified
                    Device Class: Miscellaneous,
                    HCI Version: 4.1 (0x7)  Revision: 0xb6
                    LMP Version: 4.1 (0x7)  Subversion: 0x2209
                    Manufacturer: Broadcom Corporation (15)

      If you DON'T see any controller information from either command, try running the following 
      commands to see if there might be some conflicting daemons running.  If these processes 
      are running, you won't be able to even see the Bluetooth controller (lame):

        sudo systemctl | grep ttyAMA0

          Do you see anything like the following below?
               loaded active plugged   /sys/devices/platform/soc/20201000.serial/tty/ttyAMA0

               loaded active running   Serial Getty on ttyAMA0 

             If you do see those ttyAMA0 lines, run the following commands:

                sudo systemctl stop serial-getty@ttyAMA0.service
                sudo systemctl disable serial-getty@ttyAMA0.service

   7. Modify the SystemD Bluetooth startup scripts to enable LEGACY compatibility needed for 
      serial support

      I can confirm this "legacy" bluetooth mode is STILL required in Raspberry Pi OS Buster with 
      the 5.10.17 kernel and bluez_5.50-1.2~deb10u1+rpt2 package

      7.a. To enable legacy bluetooth support, you need to modify the Systemd unit file and add 
           the "-c" option:

         sudo vim /lib/systemd/system/bluetooth.service
         ExecStart=/usr/lib/bluetooth/bluetoothd -C
         ExecStartPost=/usr/bin/sdptool add SP
         ExecStartPost=/bin/hciconfig hci0 auth
         ExecStartPost=/bin/hciconfig hci0 encrypt
         ExecStartPost=/bin/hciconfig hci0 piscan

      7.b.  Create a new systemd unit

          To associate the Bluetooth connection to a serial service, we need to enable the rfcomm
          program.   I am using the "-A" Authentication, "-E" Encrypted", and "-S" Secure options
          for the best security possible.  

             NOTE: The "-S" option will ONLY work if you used the tool.  If you didn't, 
                   the use of -S here will BREAK the pairing entry on the linux side and you'll have to 
                   DELETE that pairing and start over.  It will NEVER work unless you do that

             NOTE #2: While I don't recommend it, you can add "-a pi" and change the "pi" username
                      to whatever username you want to automatically login without any password

          sudo vim /etc/systemd/system/rfcomm.service
          Description=RFCOMM service

          ExecStart=/usr/bin/rfcomm -A -E -S watch hci0 1 getty rfcomm0 115200 vt100



      7.c. Restart the Bluez bluetooth control plane

           sudo systemctl daemon-reload
           sudo systemctl restart bluetooth.service
           sudo systemctl enable rfcomm
           sudo systemctl start rfcomm

      7.d. Confirm Bluez is now running with the "-C" option as well as the other options are running

           ps aux | grep -e bluetoothd -e rfcomm
           root      1187  0.0  0.0      0     0 ?        S<   Apr22   0:00 [krfcommd]
           root      3579  0.1  0.9   9876  4776 ?        Ss   14:37   0:00 /usr/lib/bluetooth/bluetoothd -C
           root      3608  0.0  0.2   2088  1240 ?        Ss   14:37   0:00 /usr/bin/rfcomm -A -E -S watch hci0 1 getty rfcomm0 115200 vt100

   8. Review currently enabled BT features

            #view all basic settings
            sudo /bin/hciconfig hci0
            hci0:	Type: Primary  Bus: UART
            BD Address: B8:27:EB:xx:xx:xx  ACL MTU: 1021:8  SCO MTU: 64:1
            UP RUNNING 
            RX bytes:3272 acl:0 sco:0 events:187 errors:0
            TX bytes:7056 acl:0 sco:0 commands:187 errors:0


            #view all extended BT profile settings
            sudo /usr/bin/bluetoothctl show
            Controller B8:27:EB:xx:xx:xx (public)
            Name: rpi0w-2
            Alias: rpi0w-2
            Class: 0x00000000
            Powered: yes
            Discoverable: no
            Pairable: yes
            UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)
            UUID: A/V Remote Control        (0000110e-0000-1000-8000-00805f9b34fb)
            UUID: PnP Information           (00001200-0000-1000-8000-00805f9b34fb)
            UUID: A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb)
            UUID: Generic Access Profile    (00001800-0000-1000-8000-00805f9b34fb)
            Modalias: usb:v1D6Bp0246d0532
            Discovering: no

         Notice that the controller is "powered", NOT discoverable, it IS pairable, and it's
         NOT discovering (looking to pair to other devices like keyboards, etc)

   9. Confirm all new settings are operational:

         #Notice there is now "PSCAN ISCAN AUTH ENCRYPT" attributes enabled
         sudo /bin/hciconfig hci0
         hci0:	Type: Primary  Bus: UART
                   BD Address: B8:27:EB:xx:xx:xx  ACL MTU: 1021:8  SCO MTU: 64:1
                   RX bytes:3300 acl:0 sco:0 events:191 errors:0
                   TX bytes:7107 acl:0 sco:0 commands:191 errors:0


         #Notice the BT is now showing "pairable" 
         sudo /usr/bin/bluetoothctl show
         Controller B8:27:EB:xx:xx:xx (public)
         Name: rpi0w-2
         Alias: rpi0w-2
         Class: 0x00000000
         Powered: yes
         Discoverable: yes
         Pairable: yes
         UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)
         UUID: A/V Remote Control        (0000110e-0000-1000-8000-00805f9b34fb)
         UUID: PnP Information           (00001200-0000-1000-8000-00805f9b34fb)
         UUID: A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb)
         UUID: Generic Access Profile    (00001800-0000-1000-8000-00805f9b34fb)
         Modalias: usb:v1D6Bp0246d0532
         Discovering: no

  10.  Create a Bluetooth secure authentication script

          sudo vim /usr/local/sbin/

          # 04/24/21

          echo -e "\nBegin secure pairing with remote device.  Hit control-c to exit once complete\n"
          /usr/bin/bluetoothctl pairable on
          /usr/bin/bluetoothctl discoverable on

          echo " "
          sudo python3 /usr/share/doc/bluez-test-scripts/examples/

          echo -e "\nOnce Pairing completed.  Disabling pairing and discoverable mode:"
          /usr/bin/bluetoothctl pairable off
          /usr/bin/bluetoothctl discoverable off
          echo -e "\nScript is exiting\n"

          #Make it executable
          sudo chmod 700 /usr/local/sbin/

  11.  Run bluetooth secure authentication script

          sudo /usr/local/sbin/

             # You will see some warnings but it should run fine
             /usr/share/doc/bluez-test-scripts/examples/ PyGIDeprecationWarning: GObject.MainLoop is deprecated; use GLib.MainLoop instead
  mainloop = GObject.MainLoop()
             Agent registered

       NOTE #1: Be ready to come back to this window to accept the pairing coming in the next few steps

       NOTE #2:  You CANNOT run this script in the background as you will have to approve the bluetooth paring.
              More on this below

  12.  Let's get your BT device paired:
       a. On your Android phone under System settings --> Connections --> Bluetooth --> Network
          and find your Rpi in the list.  Select your Raspberry Pi entry to start the pairing

       b. You should see something like the following:
          Bluetooth pairing request:

             Pair with rpi0w-2?
                Cancel or OK?
          Select OK

       c. Back on the main terminal on your Raspberry Pi where you started the "" program, 
          you should see the following prompt:
          RequestConfirmation (/org/bluez/hci0/dev_58_B1_0F_XX_XX_XX, 553510)
          Confirm passkey (yes/no):

          Type in "yes" and hit enter to ACCEPT the pairing request

       d. At this point, a few seconds will pass and the Raspberry Pi should now be listed
          as paired.  If this doesn't happen, you need to recheck your steps from above
          but this MUST happen or you cannot move forward

  13.  Now that pairing is complete, exit the script

       a. On the Raspberry Pi where you are running the "", now hit control-c
          to exit that process as well as disable future pairing and remove your Raspberry Pi from being
          discoverable.  You will see the following error but don't worry about it
          ^CTraceback (most recent call last):
            File "/usr/share/doc/bluez-test-scripts/examples/", line 180, in
            File "/usr/lib/python3/dist-packages/gi/overrides/", line 498, in run super(MainLoop, self).run()
            File "/usr/lib/python3.7/", line 119, in __exit__ next(self.gen)
            File "/usr/lib/python3/dist-packages/gi/", line 251, in register_sigint_fallback signal.default_int_handler(signal.SIGINT, None)

          Pairing completed.  Disabling pairing and discoverable mode:
          Changing pairable off succeeded
          Changing discoverable off succeeded

          Script is exiting

  14.  Curious what your pairing info looks like, try this:

       Run this command to see details about your pairing record.  You will need to put
       in the correct MAC address corresponding to the device you want to look at.  In
       this example, I'm going to look at BOTH devices.  

          sudo /usr/bin/bluetoothctl devices
          Device 9C:FC:E8:XX:XX:XX LAPTOP-F63LDUTG
          Device 58:B1:0F:XX:XX:XX David's Galaxy device

       Here is the Galaxy phone first:

          sudo /usr/bin/bluetoothctl info 58:B1:0F:XX:XX:XX
          Device 58:B1:0F:XX:XX:XX (public)
          Name: David's Galaxy Device
          Alias: David's Galaxy Device
          Class: 0x005a020c
          Icon: phone
          Paired: yes
          Trusted: yes
          Blocked: no
          Connected: no
          LegacyPairing: no

          NOTE:  Notice that the pairing is listed as "trusted".  That's important for
                 secure bluetooth sessions

       Here is a Windows 10 laptop just for comparison sake (notice there is a LOT more
       available information captured here via UUID items):

          sudo /usr/bin/bluetoothctl info 9C:FC:E8:XX:XX:XX
          Device 9C:FC:E8:XX:XX:XX (public)
          Name: LAPTOP-F63LXXXX
          Alias: LAPTOP-F63LXXXX
          Class: 0x002a010c
          Icon: computer
          Paired: yes
          Trusted: yes
          Blocked: no
          Connected: no
          LegacyPairing: no
          UUID: Service Discovery Serve.. (00001000-0000-1000-8000-00805fxxxxxx)
          UUID: Audio Source              (0000110a-0000-1000-8000-00805fxxxxxx)
          UUID: Audio Sink                (0000110b-0000-1000-8000-00805fxxxxxx)
          UUID: A/V Remote Control Target (0000110c-0000-1000-8000-00805fxxxxxx)
          UUID: A/V Remote Control        (0000110e-0000-1000-8000-00805fxxxxxx)
          UUID: PANU                      (00001115-0000-1000-8000-00805fxxxxxx)
          UUID: Handsfree                 (0000111e-0000-1000-8000-00805fxxxxxx)
          UUID: Handsfree Audio Gateway   (0000111f-0000-1000-8000-00805fxxxxxx)
          UUID: PnP Information           (00001200-0000-1000-8000-00805fxxxxxx)
          UUID: Vendor specific           (c7f94713-891e-496a-a0e7-983a09xxxxxx)
          Modalias: bluetooth:v0006p0001d0A00

  15.  Next up, install a Bluetooth Serial terminal and connect to your Rpi

       a. On your Android phone, you now need to install a Bluetooth serial terminal application

          I can recommend the "Serial Bluetooth Terminal" app by Kai Moriach on the Google Play store 
          as it's simple, intuitive and seems to do what you would expect.  There are *MANY* other 
          programs out there but most of them are not suitable for being a "console terminal"

          This recommended app has a graphic of a yellow DB9 RS232 plug with a bluetooth icon on it 
          pointing to the right.

             - I don't have recommendations for Apple iPhones - email me if you find a good app)

             - I currently don't have any instructions for other OSes but here are some links I found:
                      none yet
                  1. Understanding the weird behavior of Windows and dual com ports

                  2. How to configure the COM ports to match against BT pairings
                        - Highlights additional steps to mate the BT pairing to a COM port
                        - recommends one terminal program on the Microsoft store
                      none yet

       b. Start up the newly installed "Serial Bluetooth Terminal" app

       c. In the upper left corner, click on the four horizontal bar icon (settings) and select:

          c.1. Settings
                  Terminal tab
                     Display mode: Terminal
                     Show timestamps: off
                     Local Echo: off

          c.2. Devices - In the shown paired devices list, find your newly paired Raspberry Pi entry 
               and select it

               If everything works, you should see in the app:
               Connecting to <your raspberry pi's name>

               Raspbian GNU/Linux 10 hostname rfcomm0

               hostname login: 

               On the Raspberry Pi's "rfcomm" process side, you should see:
               Connection from 58:B1:0F:XX:XX:XX to /dev/rfcomm0
               Press CTRL-C for hangup

          d. Try logging in with your Raspberry Pi credentials and you should be able to get down
             to a shell prompt!

          e. If that works, that's great!  Now I recommend to log out from the shell session using
             "exit" and then touch the "plug" icon to the left of the trashcan icon on the Bluetooth 
             serial console app to disconnect the low level bluetooth session

  - Consider Enable discoverable / pairable via a GPIO connected button

# Bluetooth Appendix information
# ------------------------------

The state of bluetooth security is quirky and sometimes kludgy at times.  Here are some of my
misc notes on some behaviors I've seen:

   - If you don't care about bluetooth security authentication and encryption, you can SKIP 
     the above step running "" security agent.  To do so, you could consider the 

        /bin/hciconfig hci0 sspmode 1

       NOTE: "sspmode 0" will present a PIN challenge to the BT client but it never complete the pairing
             WITHOUT the to acknowledge the request and them marking the pairing as

   - I don't know what "secmgr" option is and it's mentioned in the man page but isn't supported in the
     actual hciconfig tool:

        /bin/hciconfig hci0 secmgr

   - Other thoughts on Bluetooth transport security:

     weakest: this doesn't use authentication or encryption or require trusted pairings but it works
              /usr/bin/rfcomm watch hci0 1 getty rfcomm0 115200 vt100

     stronger: enables authentication and encryption but doesn't require the tool
             /usr/bin/rfcomm -A -E watch hci0 1 getty rfcomm0 115200 vt100

     strongest: requires the tool to not only create interactive pairing prompts on both
                the BT client and server, but does other things to the pairing.  If you try this "-S" option
                with a pairing that NOT done with the "", that pairing will become corrupted
                and be no longer usable for ANY sessions.  You will have to delete that pairing on the Linux 
                side and start over:
                /usr/bin/rfcomm -A -E -S watch hci0 1 getty rfcomm0 115200 vt100

   - Details on the and some of it's advanced modes:
            ./                    - the default mode here is to acknowledge the pairing on the Linux 
                                                   side with only an interactive accept-only prompt on the client
            ./ -c NoInputNoOutput - this is the same "sspmode 1"; instantly pairs the client to server
                                                   without any prompting, any PIN, etc
            ./ -c DisplayOnly     - Requires acknowledgement of the pairing PIN code on the client side 
                                                   as well as requiring a Yes/No PIN acceptance prompt on the server side
            More secure but very more cumbersome
            ./ -c KeyboardOnly    - this requires you type in the paring PIN on the Linux side that is 
                                                   then displayed on the client side
            ./ -c DisplayYesNo    - this requires you acknowledge the pairing on the server side only
            ./ -c KeyboardDisplay - acknowledge the pairing PIN code on the client side with a Yes/No 
                                                   interactively confirmation of the PIN on the serverside

   - If you ever delete the BT pairing from your phone (client) or you enable "secure connections" on the Linux side, 
     you'll need to delete the stored pairing from the server / Linux side with:

     #Show all current stored BT pairings
     /usr/bin/bluetoothctl devices

     #Delete a specific pairing
     /usr/bin/bluetoothctl remove <BT MAC ADDRESS of your phone>
     bluetoothctl remove xx:xx:xx:xx:xx:xx

32.e - Setting up Bluetooth on the Rpi for pairing to a Kenwood D74 KISS TNC

    All of the steps in this section are required to be followed before
    pairing and operation of the D74's KISS TNC is possible

   To get started, you need to get the D74 setup:

      1. On the D74, turn on the radio and use the A/B button to select the BOTTOM 
         VFO or VFO-B as this is the only VFO that the built-in TNC works on.

      2. Tap the function + 5 key until the D74's display says "KISS 12"

      3. For now, put the radio into high power mode by pressing F + Menu
         until the display shows "H" for HIGH power

      4. Enable the D74 Bluetooth engine by pushing:
         Menu -> Configuration -> Bluetooth -> Bluetooth: ON

   Ok, the radio is now ready to go so on to the Raspberry Pi!  Now you
   need to make sure the Raspberry 0w, 3, or 3B+ has it's bluetooth setup
   right (and bluetooth is enabled if you previously disabled it):

   sudo /usr/bin/bluetoothctl

      #Issue the following commands

      #Show available BT controllers

      #Give more details on the local controller (change this example MAC address to match yours)
      show B8:27:EB:AA:AA:91

      #Show what might already be paired

      #Enable Bluetooth pairing
      agent on

      #Scan for available BT devices
      scan on

      # At this point, you're going to want to WAIT until you see the D74's BT MAC show up in
      # the scan output.  After 10-20 seconds, the D74's BT mac address should show up on the 
      # command line tool looking like:
      #    [NEW] Device 24:71:89:96:de:AB TH-D74
      # This output MUST show up before you move on and actually do a pairing or # the program 
      # will give the error:
      #   Device 24:71:89:96:de:AB  not available

      # Now initiate the pairing mode on the D74 with going into:
      #   Menu --> Configuration -> Bluetooth -> Pairing Mode

      # Now issue the command to start the pairing:
      pair 24:71:89:96:DE:AB

      # You should now see on the D74's display, the BT pairing code.  The bluetoothctl program
      #  should prompt you with offering AUTO-ENTER in the BT passcode such as:
      #    Request confirmation
      #    [agent] Confirm passkey 285481 (yes/no): yes

      # Accept the pairing by typing in in "yes" (without the quotes and don't just use "y") and hit enter


      # *CRITICAL*: On the TH-D74, quickly hit the upper right button for the Bluetooth Pair's "OK".  If
      # you do this in time, the D74 should say:
      #    Information:   Pairing is completed.  
      # Select "OK" on the D74 to dismiss this script

      # On the Rpi, you should see:
      #   [agent] Confirm passkey 285481 (yes/no): yes
      #   [CHG] Device 24:71:89:96:de:AB UUIDs: 00001101-0000-1000-8000-00805f9b34fb
      #   [CHG] Device 24:71:89:96:de:AB UUIDs: 00001112-0000-1000-8000-00805f9b34fb
      #   [CHG] Device 24:71:89:96:de:AB ServicesResolved: yes
      #   [CHG] Device 24:71:89:96:de:AB Paired: yes
      #   Pairing successful
      #   [CHG] Device 24:71:89:96:de:AB ServicesResolved: no
      #   [CHG] Device 24:71:89:96:de:AB Connected: no

      # Don't worry about it showing "Connected: no", this is normal

      # Now Save this pairing permanently with 
      trust 24:71:89:96:DE:AB

      # You should see the trust acknowledgment with:
      #   Changing 24:71:89:96:DE:AB trust succeeded 

      # For whatever reason, if you wanted to remove the D74 pairing such as if you upgraded the 
      # D74's firmware and though you made a backup with the Kenwood MCP program, it didn't save
      # any BT pairings and now you have to re-pair the radio, you can do:
      #  remove 24:71:89:96:DE:AB

      # Ok, you should be good now!  For those who are curious, you can learn a little more about 
      # these Bluetooth UUIDs with:
         info 24:71:89:96:de:AB
         Device 24:71:89:96:de:AB
                 Name: TH-D74
                 Alias: TH-D74
                 Class: 0x620204
                 Icon: phone
                 Paired: yes
                 Trusted: yes
                 Blocked: no
                 Connected: no
                 LegacyPairing: no
                 UUID: Serial Port               (00001101-0000-1000-8000-00805f9b34fb)
                 UUID: Headset AG                (00001112-0000-1000-8000-00805f9b34fb)
                 RSSI: -71
                 TxPower: 4

      # Notice a few things the above bluetooth output:
      #   1. The two UUIDs shown above
      #   2. It went from ServicesResolved: Yes" to "ServicesResolved: no"
      #   For Item #1 above, that's showing the found bluetooth "services" from the remote 
      #   BT device.  Let's learn more about those services by issuing the next command 
      #   to see what detailed BT services the D74 offers.  The important information you 
      #   get from this output is:
      #      The top entry is for the Audio side using Bluetooth profiles: 
      #           0x1112 (input) and 0x1203 (output) on Bluetooth channel #1
      #      The second entry is for the serial port using Bluetooth profile:
      #           "Serial Port" (0x1101) on channel #2
      # In different Unix terminal window than where you are currently running the 
      # program "bluetoothctl", issue the command:

         sdptool browse 24:71:89:96:DE:AB

      # Here, you'll see all kinds of details:
         Browsing 24:71:89:96:DE:AB ...
         Service RecHandle: 0x10000
         Service Class ID List:
           "Headset Audio Gateway" (0x1112)
           "Generic Audio" (0x1203)
         Protocol Descriptor List:
           "L2CAP" (0x0100)
           "RFCOMM" (0x0003)
             Channel: 1
         Language Base Attr List:
           code_ISO639: 0x656e
           encoding:    0x6a
           base_offset: 0x100
         Profile Descriptor List:
           "Headset" (0x1108)
             Version: 0x0102

         Service Name: Serial Port
         Service RecHandle: 0x10001
         Service Class ID List:
           "Serial Port" (0x1101)
         Protocol Descriptor List:
           "L2CAP" (0x0100)
           "RFCOMM" (0x0003)
             Channel: 2
         Language Base Attr List:
           code_ISO639: 0x656e
           encoding:    0x6a
           base_offset: 0x100
         Profile Descriptor List:
           "Serial Port" (0x1101)
             Version: 0x0100

      # As you can see above, the D74 is offering both audio in/out, and a serial port.  That's good!
      # You'll also notice in the bluetoothctl window, it showed that it connected and disconnected:
        [CHG] Device 24:71:89:96:DE:AB Connected: yes
        [CHG] Device 24:71:89:96:DE:AB Connected: no

      # Assuming that all worked, type in "exit" in the terminal window running the bluetoothctl tool 

      # Now for the bad part for item #2.  Let's confirm some things ARE or AREN'T properly working 
      # on your Raspberry Pi.  Try running the following command:

         sudo sdptool browse local
         Failed to connect to SDP server on FF:FF:FF:00:00:00: No such file or directory
         Failed to connect to SDP server on FF:FF:FF:00:00:00: Permission denied
         Failed to connect to SDP server on FF:FF:FF:00:00:00: Connection refused

      # Did the command fail?  If so, you probably have have version 5.x of the "bluez" Linux Bluetooth stack.  
      # It's known to be broken for the sdptool but a work around is available.  You can read more about 
      # this here:
      # The work around is to edit the following file:
         vim /etc/systemd/system/dbus-org.bluez.service

         # Find the "ExecStart" line and append "-C" to the end of that line to enable Compatibility mode

     # Now tell Systemd to recognize the modified configuration files and to restart
     # the Bluetooth service

        sudo systemctl daemon-reload
        sudo systemctl restart bluetooth

     # With the Bluetooth service restarted, it now created a new system device.  Confirm the SDP device
     # was created with running:

       ls -la /var/run/sdp
       srw-rw---- 1 root root 0 Dec 24 10:53 /var/run/sdp

     # Again, try the sdptool command and hopefully it now works:
        sudo sdptool browse local
        Browsing FF:FF:FF:00:00:00 ...
        Service RecHandle: 0x10000
        Service Class ID List:
          "PnP Information" (0x1200)
        Profile Descriptor List:
          "PnP Information" (0x1200)
            Version: 0x0103

        Browsing FF:FF:FF:00:00:00 ...
        Service Search failed: Invalid argument
        Service Name: Generic Access Profile
        Service Provider: BlueZ
        Service RecHandle: 0x10001
        Service Class ID List:
          "Generic Access" (0x1800)
        Protocol Descriptor List:
          "L2CAP" (0x0100)
            PSM: 31
          "ATT" (0x0007)
            uint16: 0x0001
            uint16: 0x0005

        Service Name: Generic Attribute Profile
        Service Provider: BlueZ
        Service RecHandle: 0x10002
        Service Class ID List:
          "Generic Attribute" (0x1801)
        Protocol Descriptor List:
          "L2CAP" (0x0100)
            PSM: 31
          "ATT" (0x0007)
            uint16: 0x0006
            uint16: 0x0009

        Service Name: AVRCP CT
        Service RecHandle: 0x10003
        Service Class ID List:
          "AV Remote" (0x110e)
          "AV Remote Controller" (0x110f)
        Protocol Descriptor List:
          "L2CAP" (0x0100)
            PSM: 23
          "AVCTP" (0x0017)
            uint16: 0x0103
        Profile Descriptor List:
          "AV Remote" (0x110e)
            Version: 0x0106

        Service Name: AVRCP TG
        Service RecHandle: 0x10004
        Service Class ID List:
          "AV Remote Target" (0x110c)
        Protocol Descriptor List:
          "L2CAP" (0x0100)
            PSM: 23
          "AVCTP" (0x0017)
            uint16: 0x0103
        Profile Descriptor List:
          "AV Remote" (0x110e)
            Version: 0x0105

        # TO BE CONFIRMED if this is NEEDED (I don't think it is)
        #   It's mentioned that the permissions of this /var/run/sdp need to be "other" read and
        #   writable.  To do that, issue the command:
        chmod 666 /var/run/sdp

     # At this point, let's try connecting to the D74 with the following MANUAL test.  This test
     #  will read the output of the GPS and send it to the Bluetooth interface
     #  1. On the D74, go into Menu --> GPS --> Basic Settings --> 
     #        Built-in GPS: On
     #        PC Output: On
     #  2. On the D74, go into Menu --> Configuration --> Interface --> 
     #        PC Output  (GPS): Bluetooth
     #        PC OUtput (APRS): Bluetooth
     #        KISS            : Bluetooth
     #        DV/DR           : Bluetooth
     #  3. On the D74, don't have it in any "mode" where either VFO shows "APRS12" or "KISS12"

     # Let's have the Rpi connect to the D74's serial port (channel 2):

        sudo rfcomm connect hci0 24:71:89:96:DE:AB 2

     # At this point, you should see the LCD on the TH-D74 light up with a notification saying 
     # "Connected Bluetooth Device".  You won't see anything else in this terminal window as 
     # this program doesn't display anything.  If you don't get the connected message and you
     # try using control-c and try the command again yet now get:

       Can't connect RFCOMM socket: Device or resource busy

     # You probably typed in the wrong MAC address.  You'll have to wait for the command to
     # time out or just reboot the Rpi.  
     #   Btw, sometimes I've never been able to get the command to work again without rebooting
     #   the Pi.  It's frustrating and I haven't found any other ways to clear out that old
     #   state.  If you find a reliable way, please let me know!

     # Assuming the above commands worked ok, open a new terminal windows and run the command:

        sudo cat /dev/rfcomm0

     # In this window, you should now see NEMA GPS Sentence output like:
       . . .
     # If you see that, awesome, you've confirmed Bluetooth to the D74 is working!  
     # Type in control-C in the "rfcomm connect" window to disconnect the 
     # bluetooth system as well as in the "sudo cat /dev/rfcomm" window 

       |NOTE:  I can reliably reproduce a bug in the D74 firmware v1.06 that if you    |
       |       have the GPS output enabled and you simply leave the "rfcomm connect"   |
       |       command running, the GPS icon on the D74 will eventually stop blinking  |
       |       and the front interface on the D74 will eventually stop responding.     |
       |       Everything will be fine if you don't create the Bluetooth connection.   |
       |       In about 60 seconds, the D74 will reboot.  Beyond the automatic reboot, |
       |       The only other way to regain control of the HT is to pull the battery!  |
       |                                                                               |
       |       D74 firmware v1.07 was released today, 12/27/17 and it sounds like      |
       |       Kenwood have fixed this specific issue but I haven't confirmed this yet |

     #  Next up, try dynamic Bluetooth binding.  To do this, issue the following command
     #  in one window:

        sudo rfcomm bind hci0 24:71:89:96:DE:AB 2

     # Notice the command ran and it instantly put you back that the Unix prompt.  Also notice 
     # the D74 didn't light up the LCD and state "Connected Bluetooth Device".  This is GOOD!
     # The system is now in standby.  Now open another window and run:

        sudo cat /dev/rfcomm0 

     # NOW you should have seen the Bluetooth message on the D74 and you're getting NEMA GPS 
     # sentence details in this window.  Now type in control-c in this window and you'll 
     # instantly see the bluetooth icon on the D74 go out.  If you run the command again,
     # it will instantly re-associate to the D74.  Awesome!

     # To shutdown this dynamic Bluetooth association, run the command:

        rfcomm release hci0

     # It's worth mentioning that you can also put the D74 either into the "APRS12" or "KISS12"
     # mode and put bottom VFO (VFO-B) on a packet frequency say like 144.390 for APRS or 145.050
     # for keyboard-2-keyboard chat here in Northern California, the Bluetooth interface will send
     # this traffic too!  That assumes you configured the other D74 menus items as mentioned above

     That's it.. you've proved all the basics are working!  The next step is to get the Linux
     AX.25 stack working with it.  The plan is to integrate this functionality into the 
     /etc/ax25/ script but, for now, I've created a basic script called available below that does the basic bring up steps:
     Put the D74 into KISS12 mode by toggling the Function-APRS button (that's the 5 key) 
     twice and you'll see the "KISS 12" icon in the upper middle right of the D74's display.
     Then edit this script to match your specific D74's bluetooth MAC 
     address and run it.  Things should come automatically!
     Cool!  Btw, one more point:
     | IMPORTANT |
     DISABLE the GPS sentence output we enabled before as you probably won't need it
     and it will either run down your battery or crash older D74 firmwares:

        D74 Menu --> GPS --> Basic Settings --> PC Output: OFF

  Other Linux Bluetooth notes:
  Tips on supporting bluetooth audio devices (output only speakers, input/output 
  headsets, et) on your RPI v3:

   NOTE:  This URL recommends to install PulseAudio for full featured Bluetooth support.
          Since this document focuses on being a minimalist GUI-less environment, this
          isn't the direction I recommend for packet uses:


   NOTE #2: As of 12/4/20, the Raspberry Pi OS now includes PulseAudio by default in it's
            GUI-enabled versions of the distro.  This hopefully now means any previously 
            seen issues with PulseAudio on the Raspberry Pi have been resolved.

   Older details from the same author for older versions of Raspbian that uses ALSA.
   This URL might be a better fit for our simple needs:

  Problems devices not reconnecting on reboot, see the proposed SystemD script at:

33. Enable NTP for accurate date/time

Accurate time and Location - Using Adding GPS location and GPS-based NTP time support

Basic time keeping: Modern versions of Raspbian that use SystemD have moved away from the 
classic "ntpd" service and now use timesyncd (used to be chrony).  timesyncd actually 
uses the simpler sntp protocol and is good enough for most usecases.  For now, let's keep 
things simple and ensure that timesyncd is working if that's all you need.

Assuming you have a working network connection, test your setup:

   Bullseye, Buster or Stretch:
                     Local time: Fri 2020-11-13 17:10:03 PST
                 Universal time: Sat 2020-11-14 01:10:03 UTC
                       RTC time: Sat 2020-11-14 01:10:03
                      Time zone: America/Los_Angeles (PST, -0800)
      System clock synchronized: yes <----------------------------------------
                    NTP service: active
                RTC in local TZ: no

      - In the output above, look for "NTP synchronized: yes".  If that says NO, 
        try running:

           #Make sure it's running
           systemctl status systemd-timesyncd.service

           #Also try manually enabling it
           systemctl restart systemd-timesyncd.service
           sudo timedatectl set-ntp false
           sudo timedatectl set-ntp true

        If there are issues, please review the config at /etc/systemd/timesyncd.conf .  If you
        make any changes, be sure to reload things:

          sudo systemctl daemon-reload
          sudo systemctl restart systemd-timesyncd.service
          sudo timedatectl set-ntp false
          sudo timedatectl set-ntp true

   Additional NTP details can be found by running these other commands:

      timedatectl show-timesync
      PollIntervalMaxUSec=34min 8s
      PollIntervalUSec=34min 8s
      NTPMessage={ Leap=0, Version=4, Mode=4, Stratum=2, Precision=-24, RootDelay=1.022ms, RootDispersion=18.783ms, 
      Reference=11FD227B, OriginateTimestamp=Tue 2021-06-01 10:24:12 PDT, ReceiveTimestamp=Tue 2021-06-01 10:24:12 PDT, 
      TransmitTimestamp=Tue 2021-06-01 10:24:12 PDT, DestinationTimestamp=Tue 2021-06-01 10:24:12 PDT, 
      Ignored=no PacketCount=1912, Jitter=3.409ms }

         - Does the above command FAIL with a "Failed to query server: Connection timed out" or
           "Failed to parse bus message: Connection timed out"

             - Does the "ntptime" command also fail?

             - Check the output of "sudo journalctl | tail --lines=100" and look for errors

      #Even more technical details can be found here:
      timedatectl timesync-status
       Server: (   
       Poll interval: 34min 8s (min: 32s; max 34min 8s)
                Leap: normal                           
             Version: 4                                
             Stratum: 2                                
           Reference: 11FD227B                         
           Precision: 1us (-24)                        
       Root distance: 19.294ms (max: 5s)               
              Offset: -966us                           
               Delay: 142.745ms                        
              Jitter: 3.409ms                          
        Packet count: 1912                             
           Frequency: +11.288ppm                       


33.b. Configure a USB-based GPS receiver with GPSD for position and optional time

Instead of getting accurate date/time from the Internet, you can connect a GPS receiver 
to your Raspberry Pi to get highly accurate date/time without buying a real time clock
(RTC).  In addition, you can use the location for say being a roaming APRS client.

  | A note on picking a good GPS receiver:                                          |
  |                                                                                 |
  |     You get what you pay for!  I bought an inexpensive USB GPS unit but         |
  |     it would never lock on more than one or two satellites when inside my home  |
  |     and that would take like ten minutes to do!  Compare that to a quality      |
  |     smartphone  which could get full lock within 60 seconds.  I'm currently     |
  |     having decent luck with the following $26 USB-attached device:              |
  |                                                                                 |
  | |
  |                                                                                 |
  |     This SiRF-IV based receiver unit gets a good lock within my home, seems     |
  |     to be reliable and offers quick Sat lock BUT.. it also seems to spew out    |
  |     all kinds of RF noise on 144.000Mhz.  Beware!                               |
  |                                                                                 |
  |     If you have a recommended, not too expensive GPS receiver unit that's more  |
  |     RF quiet, please email me on your recommendation!                           |

Assuming you have a USB-based GPS receiver (or a serial-port based GPS receiver with a 
serial to USB adapter), follow these steps:

To get started, plug in your the USB based GPS device to determine what device name it 
gets by running either:

   sudo journalctl

   I see:
   [262398.233128] usb 1-1.3.3: new full-speed USB device number 8 using dwc_otg
   [262398.335505] usb 1-1.3.3: New USB device found, idVendor=067b, idProduct=2303
   [262398.335528] usb 1-1.3.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
   [262398.335541] usb 1-1.3.3: Product: USB-Serial Controller D
   [262398.335554] usb 1-1.3.3: Manufacturer: Prolific Technology Inc.
   [262398.372576] usbcore: registered new interface driver usbserial
   [262398.372686] usbcore: registered new interface driver usbserial_generic
   [262398.372769] usbserial: USB Serial support registered for generic
   [262398.377356] usbcore: registered new interface driver pl2303
   [262398.377549] usbserial: USB Serial support registered for pl2303
   [262398.377696] pl2303 1-1.3.3:1.0: pl2303 converter detected
   [262398.383001] usb 1-1.3.3: pl2303 converter now attached to ttyUSB0

Now find it's alternative serial device name:

   ls -la /dev/serial/by-id

For me, I see the following LONG string (the whole thing is needed):

   lrwxrwxrwx 1 root root 13 Sep  4 17:28 usb-Prolific_Technology_Inc._USB-Serial_Controller_D-if00-port0 -> ../../ttyUSB0

So, the serial/by-id name is "usb-Prolific_Technology_Inc._USB-Serial_Controller_D-if00-port0".  
That's a pretty long string but using that will make things easy on the long run.  Let's keep going.

Now install the required GPS software:

   sudo apt update

   #Unfortunately, you must install all the additional package dependencies here 
   # (something like +60 new packages [108MB space used] is required)
   sudo apt install gpsd gpsd-clients libgps-dev

We now need to configure gpsd to use the new device in the future.  The easiest way to do that is just start
the service manually to start:

   sudo systemctl enable gpsd

Now lets test the new daemon it for a single run in the foreground.  To do so, we first need to shutdown
any running gpsd processes:

   sudo systemctl stop gpsd
   sudo systemctl stop gpsd.socket

Next, we have to work around SystemD doing the wrong thing here.  By default, SystemD creates a network
socket on port 2947 but ironically, when gpsd wants to start, it sees the port as busy and refuses to

    #Confirm that gpsd isn't running but the GPS socket is still listening (thanks to Stretch's version 
    # of SystemD.. NOT) - I don't see this on Buster though:
    ps aux | grep gpsd
    sudo lsof -nPi | grep 2947

       #If you see that the socket is still listening, you can shutdown the listening socket here
       sudo systemctl stop gpsd.socket
       sudo lsof -nPi | grep 2947

   NOTE:  One more permanent solution to avoid this Systemd listening socket situation, is to edit the 
          /lib/systemd/system/gpsd.socket file and change the following line.  This change can also 
          help EXTERNAL applications (specifically programs running on a different computer that's not
          on your Raspberry Pi) that are trying to connect to this GPS software server:

          sudo vim /lib/systemd/system/gpsd.socket
          #Find the line

           change it to


Ok, let's do a manual test of your GPS.  Run gpsd from the command line with the device-by-id string
found from above.  For my setup, I would run the following:

   # Understanding the options I'm using here:

   #    -N       : don't become a daemon, stay running in the foreground which is good for troubleshooting
   #    -D3      : increases the debugging output
   #    -n       : disables power savings on your GPS device (if it supports it)
   #    <device> : manually specify the serial device name

   sudo gpsd -N -D3 -n /dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller_D-if00-port0

   You should see something like the following:
   gpsd:INFO: launching (Version 3.11)
   gpsd:INFO: listening on port gpsd
   gpsd:INFO: stashing device /dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller_D-if00-port0 at slot 0
   gpsd:INFO: opening GPS data source type 3 at '/dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller_D-if00-port0'
   gpsd:INFO: gpsd_activate(2): activated GPS (fd 6)
   gpsd:INFO: KPPS checking /sys/devices/virtual/pps/pps0/path, /dev/ttyUSB0
   gpsd:INFO: KPPS device not found.
   gpsd:INFO: NTPD ntpshm_link_activate: 1
   gpsd:INFO: device /dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller_D-if00-port0 activated
   gpsd:INFO: running with effective group ID 20
   gpsd:INFO: running with effective user ID 114
   gpsd:INFO: startup at 2016-10-11T22:59:01.000Z (1476226741)
   gpsd:INFO: speed 4800, 8N1
   gpsd:INFO: /dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller_D-if00-port0 identified as type NMEA0183, 2.654767 sec @ 4800bps
   gpsd:WARN: can't use GGA time until after ZDA or RMC has supplied a year.
   gpsd:INFO: /dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller_D-if00-port0 identified as type SiRF, 4.151043 sec @ 4800bps
   gpsd:INFO: Sats used (8):                                                                                                                         
   gpsd:INFO: PRN=  8 az=289 el=36 (-0.764941, 0.263390, 0.587785)                                                                                   
   gpsd:INFO: PRN= 10 az= 16 el=65 (0.116489, 0.406247, 0.906308)                                                                                    
   gpsd:INFO: PRN= 18 az= 60 el=44 (0.622967, 0.359670, 0.694658)                                                                                    
   gpsd:INFO: PRN= 27 az=241 el=46 (-0.607562, -0.336777, 0.719340)                                                                                  
   gpsd:INFO: PRN= 32 az=195 el=65 (-0.109382, -0.408218, 0.906308)                                                                                  
   gpsd:INFO: PRN= 14 az=199 el=47 (-0.222037, -0.644842, 0.731354)                                                                                  
   gpsd:INFO: PRN= 24 az= 60 el=18 (0.823639, 0.475528, 0.309017)                                                                                    
   gpsd:INFO: PRN= 21 az=126 el=32 (0.686085, -0.498470, 0.529919)                                                                                   
   gpsd:WARN: SiRF: warning, write of control type 80 while awaiting ACK for a6.                                                                     
   gpsd:WARN: SiRF: warning, write of control type a6 while awaiting ACK for 80.                                                                     
   gpsd:INFO: Sats used (4):                                                                                                                         
   gpsd:INFO: PRN= 10 az= 18 el=64 (0.135464, 0.416916, 0.898794)                                                                                    
   gpsd:INFO: PRN= 18 az= 61 el=43 (0.639656, 0.354567, 0.681998)                                                                                    
   gpsd:INFO: PRN= 21 az=127 el=32 (0.677281, -0.510368, 0.529919)                                                                                   
   gpsd:INFO: PRN= 32 az=196 el=66 (-0.112112, -0.390980, 0.913545)                                                                                  
   gpsd:INFO: Sats used (9):

The important lines to see there is the "Sats used" lines.  You need a minimum of "3" and if you have that or more, 
you should be good!  Other information lines will display and continue to come but but gpsd is successfully running.  

   It's important to understand that the above command will NOT start spewing out NMEA sentences.  It will
   show key start-up details and then go quiet.

The key items to see in that output is:

   1. device <serial-by-id> activated

   2. startup at <timestamp>

   3. My GPS was identified as type SiRF

Go ahead and hit control-c to stop this manual gpsd process.  Btw, when you exit the command, notice the output:

   ^Cgpsd:WARN: received terminating signal 2.
   gpsd:WARN: SiRF: warning, write of control type 88 while awaiting ACK for a6.
   gpsd:WARN: SiRF: warning, write of control type 81 while awaiting ACK for 88.
   gpsd:INFO: closing GPS=/dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller_D-if00-port0 (6)
   gpsd:WARN: exiting.
   gpsd:WARN: shmctl for IPC_RMID failed, errno = 1 (Operation not permitted

That last line will be important if you want to set time by the GPS.  More on that later.

   OPTIONAL:  You can choose to put the GPS into NEMA mode to be able to read the raw output heard:

      gpsctl -f -n /dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller_D-if00-port0
      You should see the following output and the command should complete and go back to the Unix prompt
      gpsctl:SHOUT: switching to mode NMEA.

Now try running this ncurses-based GPS display program (works well over an SSH terminal):

   gpsmon -n /dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller_D-if00-port0
      | NOTE:  I've seen a few times that when I run this command, I just get a blank screen even   |
      |        after leaving the program just sitting there for like 10 seconds.  Even if I rerun   |
      |        the command a few times, it stays blank but if I again yet restart it, it then comes |
      |        up ok.  I think the issue is due to the program trying to negotiate GPS vs binary    |
      |        mode as things coming up with "-n" seems to make it more reliable.                   |

   You should see a TUI (textual user interface) screen printing both top level details from your 
   GPS on the top with the incoming streaming NMEA data on the bottom.  Some of the key fields to 
   look for:

      Top box:   
         Pos (position) : your GPS's position and altitude : this should NOT be changing much if
                          at all

         Time           : Date and time is accurate for the UTC timezone

         Fix            : Which satellites your GPS has locked onto; You must have at least 3 more 
                          satellites to get a mostly accurate location

      Lower Right box:   
         Firmware version: When your GPS was last updated from the manufacturer
         Visible List    : A list of the satellites your GPS sees

      The longer you run the program, the more accurate the details will become

      Example bottom NMEA streaming data
      (40) $GPGSV,3,3,10,15,03,041,,16,00,236,*7A\x0d\x0a
      (72) $GPRMC,224315.000,A,3720.6148,N,12159.9942,W,0.00,167.23,141016,,,A*78\x0d\x0a
      (77) $GPGGA,224316.000,3720.6148,N,12159.9942,W,1,05,1.9,26.2,M,-25.7,M,,0000*5D\x0d\x0a
      (49) $GPGSA,A,3,10,32,27,21,18,,,,,,,,6.6,1.9,6.3*30\x0d\x0a
      (72) $GPRMC,224316.000,A,3720.6148,N,12159.9942,W,0.00,167.23,141016,,,A*7B\x0d\x0a
      (77) $GPGGA,224317.000,3720.6148,N,12159.9942,W,1,05,1.9,26.2,M,-25.7,M,,0000*5C\x0d\x0a
      (49) $GPGSA,A,3,10,32,27,21,18,,,,,,,,6.6,1.9,6.3*30\x0d\x0a
      (72) $GPRMC,224317.000,A,3720.6148,N,12159.9942,W,0.00,167.23,141016,,,A*7A\x0d\x0a
      (77) $GPGGA,224318.000,3720.6148,N,12159.9942,W,1,05,1.9,26.2,M,-25.7,M,,0000*53\x0d\x0a
      (49) $GPGSA,A,3,10,32,27,21,18,,,,,,,,6.6,1.9,6.3*30\x0d\x0a

It's worth mentioning that there are a LOT of other GPS-like satellites flying above us these days.
According to , there are at least (12) other systems!

NOTE on poor GPS receivers:

       In the above display, make sure the DATE is correct.  As mentioned at the top of this section,
       a different USB-based GPS receiver I had was showing the following bogus date (in the future!):

       This was very strange and per the man page for "gpsd" under the Accuracy section, it states 
       this is a known issue with older GPS chips.  If I took the GPS receiver outside with a WIDE, 
       clear view of the sky, it would fix itself and report the details.  This essentially proved 
       that this cheap USB receiver wasn't very sensitive (or very good) at all!

       A potential work around to this busted time/date issue, you can do the following (or better yet, 
       just get a better GPS receiver):

          sudo fake-hwclock save
          systemctl enable fake-hwclock

       This hack resolve this for the Rpi's next reboot.  See the following URL for more details:
       Ultimately, this workaround DIDN'T work for me all the time.  What did work for me is to move 
       my GPS setup from inside my home to outside with a clear view of the sky.  

If all the above test steps work, good job.  You're almost done!  Now you need to edit the GPSD configuration 
file to make a few more changes: 

   sudo vim /etc/default/gpsd

   1. Find the line that says USBAUTO (it might not event exist).  This setting allows gpsd to interrogate any 
      new USB serial device to see if they are GPS receivers or not.  I generally *never* recommend "auto" 
      anything as it can interfere with other programs and I've seen it can make errors as well.  I recommend 
      to change the line or if not there, ADD the line to read:


   2. Find the line that says "DEVICES=" and change it to reflect your actual device-by-id serial port.  
      In this example, I'm using my GPS with:

   3. OPTIONAL: You might need to specify "-n" as an optional parameter for your specific GPS but it has
      power draw implications (if you run your Rpi from battery).  From the man page:
          -n : Don't wait for a client to connect before polling whatever GPS is associated 
               with it. Some RS232 GPSes wait in a standby mode (drawing less power) when the 
               host machine is not asserting DTR, and some cellphone and handheld embedded GPSes 
               have similar behaviors. Accordingly, waiting for a watch request to open the device 
               may save battery power. (This capability is rare in consumer-grade devices).


Ok, go ahead and save your changes and exit the editor.  Now try to start the GPS service with:

   sudo systemctl start gpsd

If all goes well, you'll just be dropped back to the command prompt without any specific output.  To 
confirm things started ok, run the commands:

   systemctl status gpsd
    gpsd.service - GPS (Global Positioning System) Daemon
     Loaded: loaded (/lib/systemd/system/gpsd.service; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2021-06-11 14:15:29 PDT; 16s ago
    Process: 14175 ExecStart=/usr/sbin/gpsd $GPSD_OPTIONS $DEVICES (code=exited, status=0/SUCCESS)
   Main PID: 14176 (gpsd)
      Tasks: 1 (limit: 2062)
     CGroup: /system.slice/gpsd.service
             └─14176 /usr/sbin/gpsd /dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller_D-if00-port0

      - The above output shows that the service is running

   # Confirm udev isn't showing any stray "gps0" devices or things like that with your USB device (change
   # the device name to match your setup.  Your output will be different depending on the USB to serial
   # chip being used in your GPS

      sudo udevadm info /dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller_D-if00-port0
      sudo udevadm info /dev/ttyUSB0

      P: /devices/platform/soc/3f980000.usb/usb1/1-1/1-1.1/1-1.1.3/1-1.1.3:1.0/ttyUSB0/tty/ttyUSB0
      N: ttyUSB0
      L: 0
      S: serial/by-path/platform-3f980000.usb-usb-0:1.1.3:1.0-port0
      S: serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller_D-if00-port0
      E: DEVPATH=/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.1/1-1.1.3/1-1.1.3:1.0/ttyUSB0/tty/ttyUSB0
      E: DEVNAME=/dev/ttyUSB0
      E: MAJOR=188
      E: MINOR=0
      E: SUBSYSTEM=tty
      E: USEC_INITIALIZED=11280236
      E: ID_VENDOR=Prolific_Technology_Inc.
      E: ID_VENDOR_ENC=Prolific\x20Technology\x20Inc.\x20
      E: ID_VENDOR_ID=067b
      E: ID_MODEL=USB-Serial_Controller_D
      E: ID_MODEL_ENC=USB-Serial\x20Controller\x20D
      E: ID_MODEL_ID=2303
      E: ID_REVISION=0400
      E: ID_SERIAL=Prolific_Technology_Inc._USB-Serial_Controller_D
      E: ID_TYPE=generic
      E: ID_BUS=usb
      E: ID_USB_INTERFACES=:ff0000:
      E: ID_USB_DRIVER=pl2303
      E: ID_VENDOR_FROM_DATABASE=Prolific Technology, Inc.
      E: ID_MODEL_FROM_DATABASE=PL2303 Serial Port
      E: ID_PATH=platform-3f980000.usb-usb-0:1.1.3:1.0
      E: ID_PATH_TAG=platform-3f980000_usb-usb-0_1_1_3_1_0
      E: DEVLINKS=/dev/serial/by-path/platform-3f980000.usb-usb-0:1.1.3:1.0-port0 /dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller_D-if00-port0
      E: TAGS=:systemd:

   Run the command "ps aux | grep gps":
   gpsd     11074  0.6  0.8  13928  7224 ?        S<s  16:47   0:00 /usr/sbin/gpsd -N /dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller_D-if00-port0

      - This output shows that the gpsd process is running as well as how it was started.  If you see both 
        of these, thats GOOD!  

   Now try out a gpsd client to talk to the gpsd server.  Try running the program:


         or alternatively for NEMA only mode:
      gpsmon -n

   Either of these commands should look and work just like the manual run we did above.  For an even nicer display, try

      - This cgps program offers a slightly simpler, cleaner view to the number of satellites being used 
        in the left-side box under the "Used" column


      If you're running the GUI version of Raspbian with the full Xwindows GUI on the HDMI console *or* are 
      SSHing into the Rpi from an Xwindows GUI computer with SSH X-forwarding enabled, this program
      will show a nice graphical representation of the received satellites with color coding 
      based upon their signal strength.  
      system running through SSH

If you want gpsd to automatically start upon boot, use the command:

   sudo systemctl enable gpsd


   - If you want to disable gpsd from auto-starting when the GPS is connected 
     to the USB bus, see: 

33.c. Adding time support via GPS and/or Internet access

Stock Raspberry Pi SBCs don't include a real time clock as it would add too much
to the cost of a base model Raspberry Pi SBC.  It's easy enough to add an inexpensive 
RTC and that's fully covered in a previous chapter in this doc.  If you don't want to install
an RTC, this simply means that when the Rpi boots, the date and time will always be WRONG
until it's updated by something.  

It's ideal to get that new time set as early as possible so the system creates properly dated
logs, etc.  One method to get a reliable date/time is via NTP (network time protocol) 
be it from the Internet (shown above) or more interestingly from a GPS data feed!

  NOTE:  If you intend to run a Raspberry Pi as an iGate and you have:
            - The rpi doesn't have accurate date/time (was rebooted and didn't have it's 
              date/time corrected)
            - Initially had working Internet connection and it later broke
            - Has been up and running for weeks

         At that point and the Internet connection is later restored, Direwolf will 
         evidently digipeat all the queued up APRS traffic heard from RF into APRS-IS land!  
         Not a great situation to be igating weeks old packets!   The fix here is to have an 
         accurate clock on your Rpi.  The easiest way to do this is to install an inexpensive

  NOTE #2: There are SEVERAL ways to solve "time" on Linux but not all soluiotns have the functionality
           that we require.  Let me chime in on some of the primary solutions:

    - ntpd:        This is the classic Linux time service and while more complex than the others,
                   it's also the most advanced.  It allows to be connected to multiple concurrent 
                   Internet based ntp servers for redundancy.  In addition, ntpd also allows to get 
                   the date and time from other sources such as a GPS receiver and merge all of
                   these time sources into one pool and automatically pick which source has the most
                   accurate time.  

    - timedatectl: systemd enabled Linux distros have moved away from classic solutions like ntpd, 
                   newer alternatives like crony and now this control program to configure it.  
                   At the time I wrote this chapter, systemd's timedatectl DID NOT support setting 
                   and synchronizing time from a GPS as well as support a GPS's 1-PPS signal.  THIS 
                   is why I did NOT opt for setting things up in this section via the systemd way. 

    - chrony:      At the time I wrote this chapter, the chrony solution DID NOT support setting 
                   and synchronizing time from a GPS as well as support a GPS's 1-PPS signal.

34.a - Add the NTP binaries and initially set the time/date

   # install the ntpdate program which allows immediate time/date setting vs using
   #   ntpd approach with slews in the new time/date over a period of days or week
   sudo apt install ntp ntpdate

   # On Raspbian Stretch system, the default 

   #Stop the newly installed and started ntpd from running for a moment
   sudo systemctl stop ntp

   #Set the date/time assuming so you have a sane starting point for ntpd
   #   - You currently have a working internet connection 
   #   - The NTP servers specified in the stock ntp.conf file are reachable
   # This command can take up to 20 seconds to print anything.. be patient
   sudo ntpdate -b `grep -e ^server -e ^pool /etc/ntp.conf | head --lines=1 | awk '{print $2}'`

   From the above command, after say 20 seconds, you should see a response like:
     21 Jul 16:41:41 ntpdate[2656]: step time server offset -0.009051 sec

34.b. - Enable ntpd to get time from gpsd

   #Ok, let's make a backup of your ntp.conf and enable ntp to support it
   sudo mkdir /etc/Old
   sudo cp /etc/ntp.conf /etc/Old/ntp.conf-bak

   #Next, make a drift directory which helps the system more quickly remember the behavior
   #of your specific GPS
   sudo mkdir -p /var/lib/ntp

   #Now edit the ntp.conf file to enable GPS PPS mode
   #  The SHM keyword or "SHard Memory" keyword is an alias to the "type 28" reference clock created by gpsd
   #  1. Put the following lines ABOVE the stock Debian NTP server definitions
   #  2. Append the "prefer" keyword to the pre-populated Debian NTP servers
   sudo vim /etc/ntp.conf
   server minpoll 4 maxpoll 4
   fudge time1 0.000 refid SHM stratum 15

   # Drift file.  Put this in a directory which the daemon can write to.
   # No symbolic links allowed, either, since the daemon updates the file
   # by creating a temporary in the same directory and then rename()'ing
   # it to the file.
   driftfile /var/lib/ntp/drift

34.c - Start up ntpd and let things sit. 

          #For Raspbian Stretch
          sudo systemctl start ntp

          #For Raspbian Jessie
          sudo systemctl start ntpd

       When I say sit, I mean have it running for at LEAST 10 minutes (assuming your GPS was getting
       a strong lock on it's various satellites.  The weaker it's reception, the longer this can take
       (if it ever works).  You can run the commands "gpsmod" or "cgps" to monitor the lock of the GPS.   
       Once your GPS has lock with at lease THREE satellites, you can move to the next step:

34.d - While gpsmon or cgps is still running, run the following command in another window
       (yes, gpsmon or cgps MUST be running in another window for this to work):

          sudo systemctl start ntp

34.e - Run the following command to print the output of the ntp system:

          ntpq -p
          root@rpi3:/etc# ntpq -p
          remote           refid      st t when poll reach   delay   offset  jitter
           SHM(0)          .SHM.           15 l    -   16    0    0.000    0.000   0.000
          +      2 u   50   64    1   84.325   13.006   0.928
          *time-a.timefreq .ACTS.           1 u   49   64    1   49.129   -2.399   0.746
          +cpe-70-114-179-      3 u   48   64    1   77.391    0.880   3.212
          +ha3.smatwebdesi    2 u   47   64    1   53.979   -2.988   0.646

    In the above output, the host with the "*" is the selected network time server.  If you 
    only see SHM to SHM, somethings isn't working right.  In troubleshooting, there might 
    be an issue with the GPS being accessed by gpsd.  To fix this, run:

       sudo usermod -aG dialout nobody

    You ultimately want to see something like the below output that shows
        SHM to GPS

   Additional troubleshooting:

      - There could be problems where it's not polling very often (notice the 71m delay)
        Sometimes if another program is running like cgps, then ntpd works.  Hmmm..
        I've seen this play both ways
        $ ntpq -p
             remote           refid      st t when poll reach   delay   offset  jitter
        +carbon.neersigh   2 u  172  256  373   85.801    0.216  22.702  2 u   46  256  377   48.269    1.420  21.650
        -time01.muskegon     2 u  100  256  377   74.713    6.046  53.822
        *     2 u  182  256  377   20.031   -0.125   0.134
         SHM(0)          .GPS.            0 l  71m   64    0    0.000  399.598   0.000
         SHM(1)          .GPS1.           0 l    -   64    0    0.000    0.000   0.000

Other Great NTP + GPS urls:

[Chapter Gap]

48. Review the boot up logs to make sure things are working as expected

Before you claim success on your new Raspberry Pi setup, I recommend you review the system bootlogs to make
sure you're not having some hidden errors.   

   | NOTE:                                                                            |
   |       This is probably going to be needed to be redone from time to time as you  |
   |       apply OS patches to your system.  I've already seen several OS patches     |
   |       BREAK things on my working Stretch install in the areas of dnsmasq and     |
   |       iptables.  Not cool but it's happening regardless and this is the only     |
   |       real way to make sure that things are remaining OK.                        |

To do this, simply do:

   sudo /sbin/shutdown -r now

Let the Raspberry Pi reboot and once it's back up, log into it and then run:

   sudo journalctl

Spend some time and review at LEAST the items that are bolded or color coded.  I'll openly mention that there
are errors in there on my system that seem to be bugs in Raspbian Stretch and/or the Linux kernel today.  
Hopefully those will be addressed over time but none of them seem to be fatal.   It will also be a good idea
to review the /var/log/messages and /var/log/syslog files though most of those log entries should be duplicates
of what's now captured in the SystemD log journal.

49. Backup your Raspberry Pi

There are a LOTS of ways to backup your Raspberry Pi be it via copies of important files to the entier SD card.
Each method has it's pros/cons and I recommend BOTH methods on a different cadence:

   - File backups:  Do this every time you make system level changes that you would hate to loose

   - SD card backup:   Do this once you've fully setup the Pi the way you want it and after each major upgrade

49.a. Backup the files on your Raspberry Pi to a remote SSH server

Backing up your Rpi's critical files is quite easy if you have a script to automate this.  The critical 
issue here is to know what files you need.  Then you need to consider when you add functionality to your 
Rpi, you need to update the script and run it.  A lot of people don't like doing things this way as
it can be tedious, error prone, etc. and they rather just do full backups.  I *personally* find this
wasteful and unnessisary but the choice is yours.  

If you'd like to try my route, download my example backup script:

   cd /tmp
   chmod 744
   sudo mv /usr/local/sbin/

from there, you need to determine a few things:

   1. Identify a server that can reach your Rpi that has the scp SSH-based file transfer 
      tool installed which you trust to keep your backup

   2. Create a directory on that server for your backups:

      mkdir -p /usr/src/archive/Rpi-backups/

   3. Edit this script to see what it does and how it's to be used

   4. Once you've made any nessisary edits, and you're ready to try running it:

      4.a.  Log into the remote server where you will keep the backups and go into the 
            /usr/src/archive/Rpi-backups/ directory

      4.b.  Run the backup script on the Rpi with:

            sudo /usr/local/sbin/

      4.c.  Once the Rpi backup is complete, run the lines outputted from the bottom of 
            the backup script to copy over the backup file

That's it.  Again.. there is no one right way to do backups but do them often!
49.b. Backup your MicroSD card

This section will let you make a complete image backup of you Raspberry Pi SD card into 
a heavily compressed file using another Linux computer.  With this backup, if you ever 
accidentally delete a file, a directory, or have your SD card ever gets corrupted, 
you can restore from this image!  This approach is very comprehensive but it:

   - Requires you to shutdown your Rpi and physically remove the SD card
   - Is slower than some other methods to run the strongest compression to minimize size

Still interested?  Ok, let's get started:

  a. Let's clean a few things up first:

         #Remove any unneeded / left over packages
         sudo apt autoremove

         #Delete all the temporary packages downloaded for patching
         sudo apt-get clean

  b. Let's remind ourselves of the SD card's size and how much it's used.  Run the 
     the "df" command which you'll see some key details.  This is for a minimal
     install of Raspberry Pi OS Lite (Bullseye):
        Filesystem     1K-blocks    Used Available Use% Mounted on
        /dev/root       15026928 1854216  12530700  13% /
        devtmpfs          113048       0    113048   0% /dev
        tmpfs             244332       0    244332   0% /dev/shm
        tmpfs              97736    3084     94652   4% /run
        tmpfs               5120       4      5116   1% /run/lock
        tmpfs              20480       0     20480   0% /tmp
        tmpfs              51200     248     50952   1% /var/log
        /dev/mmcblk0p1    258095   49440    208655  20% /boot
        tmpfs              48864       0     48864   0% /run/user/1001

        - The "/dev/root" entry says it's on a "15026928" Kbyte device.. that's 15GB aka.. 
          aka a 16GB SD card

           - Of that 16GB card, we are using "1854216" Kbyte or 1.86GByte.  This means
             that an SD card backup will be about 1.86GB with minimal compression.
             The reality is that this backup will be MUCH smaller with XZ compression

  c. Shutdown the Rpi with:

       /sbin/shutdown -h now

  d. Unplug the power cord from the Rpi

  e. Eject the MicroSD card from the Rpi and install it into a different Linux machine's 
     SD card reader while that machine is already running

  f. On the other Linux machine, run the "dmesg" command to confirm SD card device as 
     being seen and to also identify what SD card reader's device name is.  On different
     machines, I sometimes see the SD card show up as:

        /dev/sda    (For machine's that boot from an NVME SSD)
        /dev/sdd    (when using a USB3 attached multi-format card reader)

  g. The following steps will make a backup image and make as small as possible.  If you're
     only looking to copy on SD card to another, you can skip this step.

     g.1. Install the xz compression utility (if not already installed)

          #These commands assume the other Linux computer is running a Debian-like OS
          sudo apt install xz pxz

     g.2  Identify the REAL size of the SD card (in this example, I'm using /dev/mmcblk0):

              Here, you can see that m card is 15931539456 bytes large 

              sudo fdisk -lu /dev/mmcblk0
              Disk /dev/mmcblk0: 15.9 GB, 15931539456 bytes
              4 heads, 16 sectors/track, 486192 cylinders, total 31116288 sectors
              Units = sectors of 1 * 512 = 512 bytes
              Sector size (logical/physical): 512 bytes / 512 bytes
              I/O size (minimum/optimal): 512 bytes / 512 bytes
              Disk identifier: 0x92f034a6

              Device Boot               Start      End         Blocks   Id  System
              -----------               -----      ---         ------   --  -------
              /dev/mmcblk0p1            8192       93813       42811    c  W95 FAT32 (LBA)
              Partition 1 does not end on cylinder boundary.
              /dev/mmcblk0p2           94208    31116287    15511040   83  Linux
              Partition 2 does not end on cylinder boundary

     g.3. Mount the SD card with the following (in this example, I'm using /dev/mmcblk0):

          sudo mkdir -p /media/$USERNAME/boot
          sudo mkdir -p /media/$USERNAME/rootfs
          sudo mount /dev/mmcblk0p1 /media/$USERNAME/boot
          sudo mount /dev/mmcblk0p2 /media/$USERNAME/rootfs

     g.4. Clear out all unallocated space in the file system for max compression

          #Use my pre-written script as a baseline and tune to meet your needs
          cd /tmp
          chmod 700
          sudo ./

          or manually run the commands:

             #Fill up and clear out the "boot" partition - this will be fast (7 seconds)
             sudo time dd if=/dev/zero of=/media/$USERNAME/boot/bigfile.dd bs=1M
             sudo rm -f /media/$USERNAME/boot/bigfile.dd

             #Fill up and clear out the "root" partition - this will be considerably slower
             # To fill 14.1GB of free space, it took my system 29minutes.
             sudo time dd if=/dev/zero of=/media/$USERNAME/rootfs/bigfile.dd bs=1M
             sudo rm -f /media/$USERNAME/rootfs/bigfile.dd

     g.5. Unmount the card partitions

          sudo umount /media/$USERNAME/boot
          sudo umount /media/$USERNAME/rootfs

  At this point, there are two options to do the actual backup:

    - Use my script (RECOMMENDED) to create a compressed backup image which 
      is documented below


    - Consider using tools like PiShrink ( ) which can create a 
      DOWNSIZED image which can let you restore this backup on SMALLER SD card if desired

         NOTE: This tool can only work with uncompressed DD images of the SD card which requires
               substantially more disk space on the management Linux host than what my
      script requires

  h. Assuming you want to use my script, let's download it

        #This tool uses XZ compression by default which maximizes compression but is very slow
        cd /tmp
        chmod 700

  i. Update the script to reflect your system's setup

       # Edit the script and update the "SRCDEV" variable to reflect your SD card's device name.
       # In this example, I set it to:
       #   SRCDEV="/dev/sdd"

  j. Back things up!

        # Go ahead and change the filename from "ki6zhd-jessie-w-linpac.dd.gz" to 
        #   reflect your callsign, SD card size, the hostname of the Rpi, the Raspbian version, 
        #   and maybe when you created the backup (and anything else you want).  
        sudo ./ ki6zhd-16gb-hostname-bullseye-031722.dd.xz

        #if you want to do it manually:
           cd <a directory you place your backup stuff in>
           sudo time dd if=/dev/mmcblk0 bs=1M | xz -9 > ki6zhd-16gb-hostname-bullseye-031722.dd.xz

        NOTE: This command will give you a summary of what it's about to do and once started, not 
              give any output until the process is complete.  This can take quite a while to do 
              depending on the size of your SD card, the speed of I/O to your SD card reader, and
              the speed of your system.  

        Example Speed: A 16GB card took 51 minutes to copy and compress.

        Example compression:  A 16GB MicroSD card with 3.08GB worth of files on it dd's to a raw
                              file size of 15560867840 bytes  (15.56GB).  After xz compression, it was 
                              only 395MB.  That's an impressive reduction!

  k. Ok, you have your backup!  Now remove the original SD card from this secondary Linux machine 
     and put it back into the original Raspberry Pi

  l. Power back up your Raspberry Pi and everything is as it was but now you have a backup

  m. If you'd like to put a copy of this newly created SD image onto another SD card

     m.1. Make sure this new SD card is the same size OR bigger (use the fdisk command shown above to
          see it's size in blocks)

     m.2. Put the new, empty SD card into this other Linux computer and use the command:

        # Use the file name from what you entered above
        unxz -9c ki6zhd-16gb-hostname-bullseye-031722.dd.xz | dd of=/dev/sdd bs=1M

           NOTE: This command will not give any output until the process is complete
                 and it can take in upwards of 10 minutes or more depending on the size
                 of your SD card and the speed of your card reader

49.a. Restore individual files or completely from your MicroSD backup

Once you've fully backed up your Raspberry Pi's SD card, you have some insurance from file 
system corruption (power glitches) SD card failures (too many writes over it's lifetime), and
human error (you deleted the wrong file, etc).

Full microSD image backup restore:

   If you want to restore the entire image you made, the whole process is just like when you first
   imaged the SD card for your Raspberry Pi.  Multiple approaches is covered in Section 1 of this 
   document but I personally recommend to use my script since it
   supports the might better XZ compression format.   Getting this script and using it is fully
   addressed in that chapter

Individual file restore:

   Restoring individual files from a "dd" image is a little more complex but isn't too hard.
   In this example, I'm going to assume assume you want to restore the /etc/passwd file from the 
   following compressed backup file but substitute in your specific backup filename:


   1. If not already installed from following Chapter 1, install the multi-threaded XZ program 
      as it will make the decompression process go MUCH faster:

         sudo apt install pixz

   2. You need to first decompress the backup image file as there is current no way to follow these 
      steps with inline compression.  I assume you're going to want to keep the compressed file
      so you don't have to re-compress it afterwards.  You need to make sure you have enough storage
      space to BOTH support the duplicated compressed backup file AND it's decompressed copy

      a.  Create a copy of the compressed backup file

             cp ki6zhd-16gb-stretch-w-linpac-090417.dd.xz ki6zhd-16gb-stretch-w-linpac-090417-2.dd.xz

      b. uncompress the file : this will be SLOW (on a Intel i7-7600U CPU @ 2.80GHz, this took 1.5 
         minutes to decompress the 877MB file) 

            time pixz -d ki6zhd-16gb-stretch-w-linpac-090417-2.dd.xz

   3. Once decompressed, we need to look at the image's partition table to get some key details:

      NOTE:  There are lots of ways to mount "loop" file systems such as with losetup, kpartx, etc but all 
             of these options require more programs to be installed and you also don't learn how this all
             works.  So, for now, I'm just going to use the basic and included "fdisk" and "mount" commands:

      /sbin/fdisk -lu ki6zhd-16gb-stretch-w-linpac-090417-2.dd
         Disk ki6zhd-16gb-stretch-w-linpac-090417-2.dd: 14.86 GiB, 15931539456 bytes, 31116288 sectors
         Units: sectors of 1 * 512 = 512 bytes
         Sector size (logical/physical): 512 bytes / 512 bytes
         I/O size (minimum/optimal): 512 bytes / 512 bytes
         Disklabel type: dos
         Disk identifier: 0x92f034a6
         Device                                    Boot Start      End  Sectors  Size Id Type
         ki6zhd-16gb-stretch-w-linpac-123017-2.dd1       8192    93813    85622 41.8M  c W95 FAT32 (LBA)
         ki6zhd-16gb-stretch-w-linpac-123017-2.dd2      94208 31116287 31022080 14.8G 83 Linux

      The important information here is:
         - the "sector size" is 512
         - the first partition for booting starts at offset "8192"
         - the second partition for the Linux file system starts at offset "94208"

   4. Ok, time to do a little basic math to calculate where the real partition starts.  You will need to 
      substitute your backup image's values and do your own math to get the correct values:

         a. partition #1:  512 * 8192  = 4194304
         b. partition #2:  512 * 94208 = 48234496

   5. Let's mount the needed partition:

      NOTE:  if you're using Ubuntu 20.04 or similar with it's built in "snap" support, your system is 
             already using a LOT of /dev/loop devices.  For example, here is the output of "df" from my 
             $ df
             Filesystem     1K-blocks      Used Available Use% Mounted on
             udev             8040392         4   8040388   1% /dev
             tmpfs            1613988      2636   1611352   1% /run
             /dev/nvme0n1p2 479152840 121894624 332848824  27% /
             tmpfs            8069936         0   8069936   0% /dev/shm
             tmpfs               5120        24      5096   1% /run/lock
             tmpfs            8069936         0   8069936   0% /sys/fs/cgroup
             /dev/loop0          9344      9344         0 100% /snap/canonical-livepatch/98
             /dev/loop3        101632    101632         0 100% /snap/core/10958
             /dev/loop5        223232    223232         0 100% /snap/gnome-3-34-1804/60
             /dev/loop7        224256    224256         0 100% /snap/gnome-3-34-1804/66
             /dev/loop8        166784    166784         0 100% /snap/gnome-3-28-1804/145
             /dev/loop9         52352     52352         0 100% /snap/snap-store/498
             /dev/loop10       145920    145920         0 100% /snap/arduino/50
             /dev/loop12        56832     56832         0 100% /snap/core18/1997
             /dev/loop13        66432     66432         0 100% /snap/gtk-common-themes/1514
             /dev/loop15        33152     33152         0 100% /snap/snapd/11588
             /dev/loop14       267008    267008         0 100% /snap/kde-frameworks-5-core18/32
             /dev/loop16        52352     52352         0 100% /snap/snap-store/518
             /dev/nvme0n1p1    523248      8020    515228   2% /boot/efi
             tmpfs            1613984       172   1613812   1% /run/user/1000
             /dev/loop18       190976    190976         0 100% /snap/arduino/56
             /dev/loop19        66688     66688         0 100% /snap/gtk-common-themes/1515
             /dev/loop20        63232     63232         0 100% /snap/core20/975
             /dev/loop21       275200    275200         0 100% /snap/gimp/367
             /dev/loop22       249856    249856         0 100% /snap/gnome-3-38-2004/39
             /dev/loop6         32896     32896         0 100% /snap/snapd/11841
             /dev/loop23       101376    101376         0 100% /snap/core/11081
             /dev/loop1        283392    283392         0 100% /snap/gimp/372
             /dev/loop11         9344      9344         0 100% /snap/canonical-livepatch/99
             /dev/loop2         63232     63232         0 100% /snap/core20/1026
             /dev/loop17        56832     56832         0 100% /snap/core18/2066

             As such, I've found my system only wants to mount one file system at at a time.  If
             I try to mount the second partition on say , I get the error:
             mount: /mnt/dd1/: overlapping loop device exists for /usr/src/archive/RPi/Images/ki6zhd-16gb-stretch-w-linpac-123017-2.dd

         Anyway, go ahead and mount the second partition which has the /etc/passwd file:

            sudo mkdir /mnt/dd1
            sudo mount -t ext4 -o loop,offset=48234496 ki6zhd-16gb-stretch-w-linpac-090417-2.dd /mnt/dd1/

         For completeness, let's say you wanted to copy a file out of the backup image's /boot file system.
         Here, you'd use a different file system type (vfat) and use the correct partition offset:

            sudo mkdir /mnt/dd2
            sudo mount -t vfat -o loop,offset=4194304 ki6zhd-16gb-stretch-w-linpac-090417-2.dd /mnt/dd2/

            NOTE:  If you get an error here similar to the one above, you need to UNMOUNT the first file system
                   with a "sudo umount /mnt/dd1" first

   6. Copy over the file needed for recovery

         Ok, if the above command didn't give you an error, you can copy out your needed file.  In this example,
         I'm copying out the /etc/passwd file into /tmp

            cp /mnt/dd2/etc/passwd /tmp/

   7. Ok.. done.. you've recovered your file!   Let's clean up:

      a. Unmount the mounted recovery file system
            sudo umount /mnt/dd1

      b. delete the uncompressed copy of the original backup
           sudo rm ki6zhd-16gb-stretch-w-linpac-090417-2.dd 

[Chapter Gap]

60. Optional projects to add to your Raspberry Pi

This section covers various little sub-projects including:

   - Setting up a 20x4 LCD screen

60.a. Setup a 20x4 LCD via I2C to display various system details

The goal of this project was to add and LCD display to my Raspberry Pi to know what's
going on in it at a glance.  There are many options here be it 16 character by 2 line 
(16x2) LCDs, 20x4 LCDs, little LCD or OLED displays, etc.  I wanted to display more 
information at one time so I opted for one of these

   $8.75 - Blue Serial IIC/I2C/TWI 2004 204 20X4 Character LCD Module Display For Arduino

This is an inexpensive 20x4 Blue LCD that's about the same size as a Raspberry Pi.  
This LCD is driven off a four wire I2C connection instead of running it off many GPIO
pins.  This is a 5volt display but even though the Raspberry Pi is a 3.3v device, the Rpi
offers +5v pins as well so it can drive it just fine.

   NOTE:  It's important to connect LCD to 5.0v pin on the Rpi and not 3.3v pin. If you
          use the 3.3v supply, you won't be able to read the text on the display

To get started, you first need to run the setup tool and enable the I2C bus:

  sudo raspi-config

     Goto :

         - Interfacing options
              - I2C        : If you have any I2C low speed devices and plan to use them, enable this

Exit the program to save the new settings and shutdown your Rpi with:

   sudo /sbin/shutdown -h now

Now unplug the power from your Rpi and wire up the display.  For me, I used:
   Rpi pin                      LCD pin
      2    :    +5V display   :   VCC
      3    :    I2C DATA      :   SDA
      5    :    I2C Clock     :   SCL
      6    :      ground      :   GND


Now power back up the Rpi with the connected display.  The display's backlight 
should light up but nothing be on the display.  If you see a bunch of rectangle 
blocks, that's OK for now.   Once the Rpi is back up and you SSHed back into it, 
install some key I2C packages:

   sudo apt install i2c-tools python-smbus

Once those tools are installed, try running the following command to see if the
I2C display is detected:

   # detect all I2C IDs on the second I2C bus:
   sudo i2cdetect -y 1

        0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
   00:          -- -- -- -- -- -- -- -- -- -- -- -- --
   10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 3f
   40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

As you can see here, my LCD display has an I2C address of 0x3f.  If you see a "UU" in 
the address spot where you expect your RTC address, this means that the I2C address in 
use.   Maybe your Raspberry Pi distro already recognized it and has configured it for 
something else.

Now we need to get an example program going to confirm the LCD
works ok.  I would start with this project that worked for me.
There are lots of them out there though.

   I've seen that many programs just barely show any text on the LCD display
   If you look very closely, at an angle, you'll be able to tell the text is 
   but it's way too faint.  As I was troubleshooting this, I randomly stumbled 
   into another program that would show all the text in a clear, bright fashion!
   Seems this LCDs have seemingly TWO brightness levels but this one program
   is mistakenly showing the text in ultra-bright mode.  Good to know things work
   but it's the wrong function.  It ultimately turned out that my issue was that
   the LCD's VCC line was connected to the Raspberry Pi's 3.3v pin and not the +5.0v 
   pin.  Once I made that switch, I could read all the original text.  

So go get a test program:

   #This fork of another user's program works well
   #   It 100% initializes well and shows text and graphics the first time, every time

Now edit the "" and change I2C address to match your display's I2C address 
(mine is 0x3f) and LCD dimensions to 20,4:

   < ADDRESS = 0x27
   > ADDRESS = 0x3f
   < DIMENSIONS = (16, 2)
   > DIMENSIONS = (20, 4)

Ok, give the program a try:

   sudo python

This program should:

   - light up the backlight
   - Show some text
   - Show a smiley face icon
   - Show a filling bar from the left to the right
   - Show a smiley face icon
   - turn the backlight off

If that worked, you're in business!  We'll need to use in later so let's move it to somewhere

   sudo mv /usr/local/sbin/

Now I imagine you want to do something more useful with the LCD.  In the discussion thread at

There was an example program posted at
which runs a basic clock.  Unfortunately, this code doesn't seemingly initialize the LCD 
properly 100% of the time so I load each of the two above programs to get things working.  

I then enhanced the program to include the above mentioned display items with showing:

   - The Month-Day datestamp    Local time AM/PM
   - The status of the Internet connection (pinging and
     the status of the NTP session (do we have Internet time)
   - The current running callsign and the number of received AX25 packets
   - The system load with 1min / 5min / 15min details

You can grab a copy of my modified script here:

   sudo mv /usr/local/sbin/

If you downloaded my modified file, give it a trial run with:

   sudo python

You can find other examples of programs here:

  #C and Python examples : Missing URL for libraries

If that runs well, have it start at boot up with adding the following to the /etc/rc.local file:

   echo -e "\nStarting up LCD on I2C address: 0x37"
   #this test script seems to initialize the LCD properly every time
   python /usr/local/sbin/
   #This is the running program but doesn't aways init properly
   python /usr/local/sbin/ &

60.b. Setup a DS3231 battery backed up real time clock (RTC) with temperature sensor

This section covers how to add a DS3231 realtime clock (RTC) to your Raspberry Pi to allow it
to automatically set the system's date/time upon initial power up.  There are a lot of different
RTC kits, HATs, and other solutions out there which might use a PCF8523 chip, a better DS1307 chip, 
the much better DS3231 chip, or possibly some other chip.  Your RTC might also use a different I2C 
addresses, etc. so you might need to adapt these steps below to your specific RTC hardware.

It's also important to understand this section builds upon the steps previously mentioned in the 
"connecting an LCD to your Rpi" section.  As such, you must least install the key I2C programs 
in that previous section FIRTST before following this section.

Background: You might be thinking to yourself, "Why do I need an DS3231 RTC device if I already 
            have a GPS running which can set the clock?".  That's a good question but consider 

          1. An DS3231 RTC consumes almost no power and its always running even when your Rpi is
             not powered.  It will give the Raspberry Pi system the correct date/time upon 
             initial boot for accurate logging.  Using a GPS to set your system's dated/time takes 
             much longer to get the date/time and then reflect in your system's logs, etc.

          2. If your setup is in a static location or have poor GPS satellite reception, 
             why waste the power on a GPS receiver worse, suffer GPS position jitter (your 
             position keeps moving around).  Instead, just statically set your location in 
             the APRS application

          3. Why not have both?  :-)

The specific DS3231 RTC unit I bought is this one:

   # NOTE: this URL buys THREE units for $7 including the batteries ($2.30 US/ea)!  That's a
   # great deal though these are evidently Chinese boards with a questionable sourcing of these 
   # Dallas chips (possibly counterfeit?)

   # In comparison, Adafruit sells a board with what should be a true Dallas part for $13.95 US 
   # which doesn't # include a battery (yet another $0.95).  That's 6.5x more expensive but it's 
   # probably both the better quality part and ethical purchase (not ripping off Dallas Semiconductor)

   # If you're curious about these knockoff boards, you can read more say here:

Anyway, assuming you have your little RTC and also you enabled the I2C bus per the previous section 
for the LCD display (if not, read up on that now and come back here), shutdown your Rpi with:

   sudo /sbin/shutdown -h now

Now unplug the power from your Rpi and wire up the RTC.  This wiring is very similar to the
the LCD setup above but this RTC chip uses the +3.3v voltage instead.  I've read conflicting 
information where some sites say you can power it with +5.0v as well.  I've personally tested 
and have things working with the +3.3v line only.  You also might consider wiring things up
through a little Raspberry Pi breadboard like this:

   IMPORTANT:  This specific fe-pi proto board connects the three pins together just like a 
               breadboard on BOTH sides of the PCB.  These are NOT just individual holes with 
               solder grommets as I had expected.  I missed that and I completely screwed up 
               one board and had to use an Exacto knife to cut the traces on both sides of 
               the board to un-short my board!

I2C bus wiring:

   I2C buses can be wired either in a serial or parallel fashion.  In this setup, I connected 
   the Raspberry Pi to a breadboard.  On the breadboard, I connected up both the RTC as well 
   as connected jumper cables to the LCD display in PARALLEL.  Works well.

Here is a nice website for showing the standard and alternative Rpi header pinouts:
   Rpi physical 
     pin                         RTC pin
      1    :   +3.3v power    :   VCC
      3    :    I2C DATA      :   SDA
      5    :    I2C Clock     :   SCL
      6    :      ground      :   GND

Once everything is wired up, power back up the Rpi with the RTC board connected.  If you 
bought the same DS3231 RTC as I did, the LED on the unit should light up.  Once the Rpi 
booted back up, log in and install some key I2C packages (if not already installed):

   #Bullseye and newer distro versions
   sudo apt install i2c-tools python3-smbus


   #Buster and older distro versions
   sudo apt install i2c-tools python-smbus

Once those tools are installed, try running the following command to see if the
I2C-based RTC is detected:

   sudo i2cdetect -y 1
        0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
   00:          -- -- -- -- -- -- -- -- -- -- -- -- --
   10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 3f
   40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- --
   60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
   70: -- -- -- -- -- -- -- --

In the above output, you can see:

   0x37 : LCD display on I2C Bus 1 - described in the previous chapter
   0x57 : DS3231 RTC's internal 32K EEPROM 
   0x68 : DS3231 RTC 

If you see a "UU" in the address spot where you expect the RTC 0x68 address, this means that 
the RTC and it's I2C address is already in use!   That most likely means your Raspberry 
Pi distro already recognized the RTC and has configured it (that's what happened to me).  
That's a good thing but to confirm that in-use point, try running:

   ls -la /dev/rtc0

If that command comes back with something like the following, your system is already up
and running (aka.. you're done!):

   crw------- 1 root root 253, 0 Dec 31  1969 /dev/rtc0

  If this doesn't show up, you're going to need to configure a few things to get it
  recognized so keep reading and specifically read the "Setting up from scratch" section below.  

  If it DOES already show up,  I still recommend you also try running the following command:

     dmesg | grep rtc

  Confirm the output looks like this to confirm things are indeed setup properly:

  [    9.133480] rtc-ds1307 1-0068: SET TIME!
  [    9.137606] rtc-ds1307 1-0068: rtc core: registered ds3231 as rtc0

  Now, things might work but if you look closely, does your output show the "ds3231" 
  above or does it show "ds1307" instead like this output below:
    [    9.049339] rtc-ds1307 1-0068: rtc core: registered ds1307 as rtc0
    [    9.049408] rtc-ds1307 1-0068: 56 bytes nvram

  If it has the INCORRECT string "registered ds1307" text, maybe your RTC is really a ds1307 
  chip or it was incorrectly recognized.  The behavior for this output seems to be inconsistent but 
  it's actually the ds1307 kernel module that supports BOTH the ds1307 and ds3231 devices but the 
  ds3231 invocation can give you more features.  If you believe it should be a "ds3231", you'll need 
  to update your /boot/config.txt file as instructed below to gain access to some of this chip's 
  advanced features like temperature sensors, flash ROM, etc.

Configuring your I2C RTC if not already recognized
If things didn't get auto-setup for you as mentioned above, that probably just means your specific 
RTC board might be at different I2C address.  No big deal.  All you'll need to do is research what 
I2C addresses your specific RTC board will show up as from the seller.  If you don't see ANYTHING 
in the above "i2cdetect" command output, you need to make sure:

   -  the I2C bus is turned on in the raspi-config tool (see Section #4 of this doc)

   -  check your wiring from the Rpi to the RTC module, etc.  You might also try running the i2cdetect
      command on the other I2C bus (try I2C bus 0)

Assuming your RTC wasn't already recognized (not showing a UU), let's give it a temporary test by 
running the following commands to get the kernel module to load and connect to the device on 
I2C bus 1 (Raspberry Pi v1 owners will need to use bus 0 instead):

   # You must use su command here and NOT sudo to run the entire command as it's passing multiple 
   # parameters
   #  Change the "0x68" to match the I2C ID of your specific RTC
   sudo su
   echo ds3231 0x68 > /sys/class/i2c-adapter/i2c-1/new_device

If you get an error like "bash: echo: write error: Invalid argument", your RTC chip
is probably already being used.  Now check the output of the I2C command again:

   sudo i2cdetect -y 1

Is the 0x68 address now showing "UU" in it's place!  Hopefully it is and that means
the RTC is now (temporarily) in use!  That also means Linux loaded the DS1307 / DS3231 kernel 
module.  Confirm the kernel module is loaded by running:

   lsmod | grep ds
   rtc_ds1307             13908  0
   hwmon                  10552  1 rtc_ds1

Also make sure the RTC device was created as well:

   ls -la /dev/rtc*
   lrwxrwxrwx 1 root root      4 Nov 20 17:05 /dev/rtc -> rtc0
   crw------- 1 root root 253, 0 Nov 20 17:05 /dev/rtc

Assuming you see the "UU", let's now see if you can read the time from it:

   #Simply READ from the chip
   sudo hwclock -r -f /dev/rtc0
   1999-12-31 23:44:08.906751-0800

If you see all that... Awesome!  Now if your output was like mine, it seems to work but 
it might have the WRONG date and time. That's ok as it's brand new and it might not have 
even been programmed.  Assuming you Raspberry Pi has been configured to get it's time 
by being an NTP client per the previous chapter (highly recommend and also see WHY I'
m using ntpdate vs say other tools as well), setting the RTC time perfectly will be easy.

You should confirm you DO have good NTP lock via some remote time servers.  Here is what 
I see for my system.  The remote host with a "*" is the current system used for time:

   # If you're NOT using ntpd per the previous section (needed for use with getting the
   # date/time from a GPS receiver, let's look at it via Systemd's solution:
   timedatectl show-timesync
   PollIntervalMaxUSec=34min 8s
   PollIntervalUSec=17min 4s
   NTPMessage={ Leap=0, Version=4, Mode=4, Stratum=2, Precision=-26, RootDelay=15.228ms, RootDispersion=1.113ms, Reference=4559CFC7, 
     OriginateTimestamp=Sat 2021-11-13 08:14:51 PST, ReceiveTimestamp=Sat 2021-11-13 08:14:51 PST, TransmitTimestamp=Sat 2021-11-13 08:14:51 PST, 
     DestinationTimestamp=Sat 2021-11-13 08:14:51 PST, Ignored=no PacketCount=6, Jitter=4.089ms } Frequency=-1815765

   If you see something like that above, that means you have a valid NTP connection and accurate time.

   # As a simpler output, You can use the timedatectl without any options:
                  Local time: Sat 2021-04-17 17:01:01 PDT
              Universal time: Sun 2021-04-18 00:01:01 UTC
                    RTC time: Sun 2021-04-18 00:01:02
                   Time zone: America/Los_Angeles (PDT, -0700)
   System clock synchronized: yes
                 NTP service: active
             RTC in local TZ: no

   # Alternatively, If you DID enable ntpd per the previous section (needed for use with getting the
   # date/time from a GPS receiver, let's look at it via ntpq:
   ntpq -c peers
        remote           refid      st t when poll reach   delay   offset  jitter
    SHM(0)          .GPS.           15 l    -   16    0    0.000    0.000   0.000
    0.debian.pool.n .POOL.          16 p    -   64    0    0.000    0.000   0.001
    1.debian.pool.n .POOL.          16 p    -   64    0    0.000    0.000   0.001
    2.debian.pool.n .POOL.          16 p    -   64    0    0.000    0.000   0.001
    3.debian.pool.n .POOL.          16 p    -   64    0    0.000    0.000   0.001
   +eterna.binary.n     2 u  707 1024  377   52.846    2.335 143.338     2 u  149 1024  377   26.745    0.763   6.440
   +christensenplac   2 u  147 1024  373   87.077    2.070   9.090
   -    3 u   62 1024  377   16.602    2.725  22.823
   *rolex.netservic .kPPS.           1 u  825 1024  177   82.314   -3.493  11.500

Ok, assuming you have a good date/time, let's update the DS3231 RTC's clock.  It's as 
easy as running the previous command but now we're going to WRITE to it.  Running this 
command won't give any output as it completes.  The second command here will then read 
from the chip and confirm the correct date/time:

   sudo hwclock -w -f /dev/rtc0
   #no output given

Now re-read from the RTC and make sure it has the right time and date:

   sudo hwclock -r -f /dev/rtc0
   Mon 18 Feb 2019 03:23:22 PM PST  -0.247576 seconds

Great!  Now you've set the time on it and confirmed it's correct!  Now all you have to do 
is enable the RTC kernel module to load up at boot time.  To do this, edit the /boot/config.txt 
file, find the line that has the "dtoverlay" line  and make the change.

  NOTE: create a new line that reads the following (btw, you can have multiple active "dtoverlay"
        lines in this file

   sudo vi /boot/config.txt
   #  or

   #Add this line below it

Next, it's recommended to remove the stock Raspberry Pi "fake" hardware clock package if
you intend to always keep this RTC module connected to your Rpi.  You can do that with:

   sudo apt remove fake-hwclock

Next up, for most Raspberry Pi OS (Bullseye, Buster and older) users that use SystemD, you 
need to edit one more file and COMMENT out a few lines

   sudo vim /lib/udev/hwclock-set

      Find the following lines (usually starting at line 7):
      if [ -e /run/systemd/system ] ; then
          exit 0

      and comment all three lines out so they look like

      #if [ -e /run/systemd/system ] ; then
      #    exit 0

That should be it!  To test everything, go ahead and reboot your Raspberry Pi with:

   sudo /sbin/shutdown -r now

Now log back into your Rpi and try running:

   ls -la /dev/rtc*
      Confirm the /dev/rtc device is listed:
      lrwxrwxrwx 1 root root      4 Nov 20 17:05 /dev/rtc -> rtc0
      crw------- 1 root root 253, 0 Nov 20 17:05 /dev/rtc

   dmesg -T

      You should see all the kernel boot lines with the correct time/date from the very 
      beginning of the file.  

      In the dmesg output, you should also see the rtc kernel driver loaded up:
      [Sat Mar 19 17:39:25 2022] rtc-ds1307 1-0068: registered as rtc0

BONUS:  Temperature sensor on DS3231 RTCs!
A DS3231 RTC chip (not the DS1307 chip) also includes a highly accurate temperature sensor 
which is included for it to keep far more accurate time compared to NON-temperature compensated 
RTCs.  Assuming you configured and rebooted your Rpi to use the DS3231 chip vs the basic ds1307 
non-temperature compensated module, you can read the temperature from the DS3231 RTC.

Use this command to determine which device will report the temperature sensor:

   sudo find /sys/devices/ | grep 0068 | grep temp1_input

Assuming you got a response similar to above, try cat'ing that file to get a temperature 
reading in Celsius:

   cat /sys/devices/platform/soc/20804000.i2c/i2c-1/1-0068/hwmon/hwmon2/temp1_input

If the above commands didn't work, read below.  For a working example, I used the following command 
but you might need to "cat" the output of what was found above:

   cat /sys/devices/platform/soc/3f804000.i2c/i2c-1/1-0068/hwmon/hwmon0/temp1_input

   Rpi Zero-W
   cat /sys/devices/platform/soc/20804000.i2c/i2c-1/1-0068/hwmon/hwmon1/temp1_input


That output is showing it's 23.250 degrees Celsius (73.850 degrees Fahrenheit).  If you have the 
"bc" package installed, you can convert to Fahrenheit with this one line command:

   #Update this variable to reflect your specific valid device as described above

   echo "scale=2; (`cat $RTCTEMP` / 1000.0) * (9/5) + 32" | bc -l

   The output of those two lines should look like something like:

If you get a response but the temp seems too high, check the placement of the RTC board.  
Is it close to a heat generator like the RPI's CPU?  If so, try moving it to a different 
place away from any heat generators.  Maybe you are using a case with your Raspberry Pi
but it doesn't have any ventalation holes, doesn't have a fan, etc?

If you get an error polling for the temperature, it's possible that one of a few things happened:

  1. You didn't enter in the right I2C address in the "cat" command.  Try finding the right address 
     with the following command:

          sudo find /sys/devices/ | grep 0068 | grep temp1_input

     On some systems, I got the response:


     that means I need to give the command:

         cat /sys/devices/platform/soc/20804000.i2c/i2c-1/1-0068/hwmon/hwmon0/temp1_input

  2. You forgot to reboot your system to use the ds3231 personality of the kernel module

  3. Your DS3231 is a counterfeit board (very common when buying cheap Ebay / AliExpress / etc RTC 
     devices.  Please read the URLs in the beginning of this section to learn more on what you get
     when you pay very little

  4.  Raspbian has auto-configured your RTC setup yet is loading the WRONG RTC driver.  Check your 
      /boot/config.txt file and on the "dtoverlay" line, make sure it reads:


      Not "dtoverlay=i2c-rtc,ds1307"

      If you had to change this, reboot your Raspberry Pi for the changes to go into effect.

60.c. Raspberry Pi cases and cooling

Most Raspberry Pi boards don't need any special cooling and/or heatsinks except when running 
with very high CPU load or operating in very high ambient temperatures.  The Raspberry Pi 4 is 
different as it's higher performance CPU creates a lot more heat and really needs a fan to operate 
without slowing down the CPU.

Cases:  Any Raspberry Pi really need a case to protect it from any potential physical damage as 
        well as possible ESD (electro-static discharge) damage.  There are 100s of case options out 
        there but MANY aren't very good.  Please consider the following:

        - 100% enclosed cases:  
          BAD: Some vendors offer fully enclosed cases made from plastic over even metal without ANY 
          ventilation holes, any fans, etc.  If it's a plastic case such as the official Raspberry 
          Pi Foundation's case, I find this is a terrible option as your Raspberry Pi will just 
          bake inside it.  Metal cases might better dissipate some of the heat but not as much
          as you might think.  For very low CPU loaded Raspberry Pi uses, maybe this is ok for 
          your needs but your Raspberry Pi might be throttling it's CPU speed from time to time.  
          Some people argue that the case gaps around the USB, RJ45 Ethernet jack, HDMI jack, and 
          USB power ports will provide enough airflow but I would argue you can easily drill in a 
          bunch of ventilation holes on the top cover to improve it's cooling as well.  Here is 
          on good video showing this terrible design choice with showing various measurements and
          how thermal throttling can dramatically slow the performance of your Rpi (4x slower!):


        - Cases with heatsinks but no fan: 
          Heatsinks can help keep the chips cooler but many cheap cases use such cheap thermal tape 
          that it actually HURT the chip's temperature.  Please also note that even if you have a 
          heatsink installed but the case is still fully enclosed, it essentially will NOT HELP AT ALL.
          You need to have a case that has some level of ventalation to get rid of the heat.

          Buy your case + heatsink from a quality vendor to hopefully avoid this situation.  

             Rpi Zero W 2 - This case comes with two tops.  One without a heatsink hole, another
                            with a cutout for a heatsink (but it doesn't include a heatsink)

        - Metal cases with no fan: 
          There are some nice metal cases out there that will be far better than a plastic case for
          dissipating heat.  There are also some versions that extrude some of the top metal all the way down 
          to make contact with the main CPU and other chips to act as a massive heat sink.  

          IMPORTANT Wifi   ANY metal case can have a SIGNIFICANT impact on your Wifi range as it's
               note:       going to shield the RF signals.  Many amateur radio users WANT this shielding
                           to avoid stray RF noise coming out of the Rpi but they might also depend on Wifi
                           for connectivity.  if so, you will need to use the wired ethernet jack, an external 
                           USB-based Wifi dongle, or possibly hack your Rpi to add an external wifi antenna.  
                           Here is a URL with more scientific testing but it's not 100% conclusive:


          Some examples of this full-metal-heatsink type of case are the FLIRC (No GPIO pin access - leave 
          the top plastic cover OFF for better cooling), the Cooler Master Pi Case 40 (has GPIO pin access), 
          etc.  These type of cases can offer VERY good cooling with no noise *if* they make good thermal 
          contact with the RPI's chips.  

             NOTE: I recommend to use some good thermal grease on these extruded points, assemble, then 
                   disassemble, and inspect the grease dispersion on the chip to see how well it actually 
                   makes contact.  A good review of some of these cases and their thermal performance can be 
                   found here:


             Rpi Zero W FLIRC case (works on the Zero W 2 too):

        - Cases with or without heatsinks with a permanently-on fan
          These plastic or metal cases can really help keep a Rpi cooler but all of the above
          ventilation points above apply as the fan needs airflow to really work.  A downside of many
          cheaper offerings is that many come with cheap "sleeve" bearing design fans which will fail 
          to keep spinning after say a year of operation.  Better fans will come with either ball bearing, 
          MagLev, or alternative designs and these fans can last a LOT longer.  Next, the speed and resulting 
          fan noise from these always-on fan / fans can sometimes be managed by connecting the fan's power 
          leeds to either the +5.0v or +3.3v power pin.

          Fan maintenance note:  
          Any device with a fan WILL accumulate dust and dirt inside it as air flows over the board.  
          It's highly recommended to periodically clean out the inside of your Raspberry Pi's case
          and option heatsinks.  I also recommend to carefully clean the individual fan blades with
          a q-tip if it's really dirty.

        - Cases with or without heatsinks with a temperature controlled fan (full speed or variable speed)
          There are newer fan options for the Raspberry Pi that are temperature controlled where
          the fan is OFF until it exceeds a specific temperature.  These are special THREE pin fans 
          (power, ground, and PWM pin [not a TACH pin]) to control the fan speed and this control 
          CANNOT be directly done with the classic two-pin fans with just a GPIO pin.  These new
          kinds of PWM fans are not expensive and you can even make your own.  For example:

             - Official Raspberry Pi 4 Fan
                 25mm x 25mm x 8mm +5v fan with one low profile heatsink:
                 $5 US -

                NOTE:  This solution is intended to be used with the official Raspberry Pi Foundation's
                       Rpi4 case but by itself, it doesn't work very well.  If you plan on getting this
                       fan, plan on modifying your official Raspberry Pi case to create a large ventalation
                       hole.  Ultimately, can just buy this kit get the PWM fan.  I encourage you to watch 
                       the ETA Prime's YouTube video on why the unmodified Offical Rpi4 case with a fan
                       is a poor solution:


             - Another alternative ffering
                  30mm x 30mm x 8mm +5v fan shim
                  $12 US -
             - DIY temperature controlled fan with variable speed support (quieter)
               If you would like add this kind of control with your existing two-pin fans, you ideally
               need a small transistor, diode, and resistor for a solution.  See the next section in this
               doc on how to do that!

Fans with TACH signals:
The Raspberry Pi doesn't support any fans monitoring with a TACH signal wire (usually a YELLOW wire).   This 
signal can show the fan's current spinning RPM rate which is useful to find out if a fan is slowing down 
(failing) or has outright has failed (no longer spinning).  Knowing this kind of information is hugely important 
with industrial servers but can be important for your Rpi too!  There are ways to add TACH support:

   - EMC2101 fan controller chip:

   - TBD: DIY fan controller - add an Arduino, other required passive components, and an Arduino sketch 
          to communicate to the Raspberry Pi

60.d. Setting up a DIY temperature controlled variable speed fan

The newer generations of Raspberry Pi SBCs like the Rpi4 really active cooling when under load.
Many RPI cases now include cooling and even the Raspberry Pi OS offers fan control so why
this section?

I personally don't like the simple fans that run 100% of the time as that wears them out and
can be noisy.  I also don't like the Raspberry Pi OS solution because the fan either runs at
0% or 100%.  It's not variable speed and thus is noisy when they are running.  This solution 
below offers a *variable speed* support though it requires a little circuit to support this.  
All you'll need is a soldering iron and a few common electroinc parts.   

  To start, review this page that much of this project comes from:

  From there, the below details should give you some more details on what to order, how to 
  assemble, debug, etc:

  The Build of Materials (BoM) for this project are:

      Qty   Description
       1  | Install your little circuit within your Rpi case on this:
          | small square of perf board (cut to size) - My design uses 4x5 grid of holes
       1  | Connect a wire from the Rpi's GPIO pin to the circuit board to control the fan
          | Recommend a 4" (or longer) Dupont female to female jumper - maybe white or yellow color
       1  | Power the fan with the a higher power transistor
          | 2N2222 NPN transistor (1A @ 40v) - axial lead type
       1  | Prevent any backpowering when the fan turns off with a protection diode
          | 1N4001 diode (1A @ 50v) - axial lead type
       1  | Limit the current going between the GPIO pin and the transitor with a resistor
          | 1KOhm resistor (5% tolerance or better @ 0.25 watt) - axial lead type
       1  | small piece of double sided tape to hold small perf board to inside of Rpi case

  Project Steps:
   1.  Cut out a 4x5 hole rectangle section from your perf board.  This makes this little project
       very small and compact so it can fit INSIDE your Rpi's case

   2.  Before you power off your Raspberry Pi, take note of how "loud" the fan is, if it's connected
       to the +5v or maybe the +3.3v pin on the Raspberry Pi, etc.

   3.  Power off your Rpi, disconnect all cables and open up it's case

   4.  Figure out where you can put this small perf board INSIDE your Rpi case in relation to the 
       Rpi's header pins and the case fan.  Once you figure out this placement, you will need to 
       CUT the fan wires so you can reuse the bare wires from the fan to connect to the perf board.
       The other side of those cut wires will go from the perf board to to the female Dupont connectors 
       and hopefully reach the GPIO header

   5. After the fan wires are cut to the right length, I recommend to REMOVE the fan from the case to
      make the job of soldering easier
   6.  Solder the components and wires on the small perf board cutout as so:

       | E  B  C--d |  : The horizontal "EBC" here are the transistor connections :: the verical "dD" is the diode
       | |  r  o  D |  : the rRr is the resistor
       | |  R  o  _ |  : the "_" means the direction of the diode polarity
       | |  r  o  d |
       | x  x  x--x |  : the horizontal "--" means to create a solder bridge between the two connections
         |  |  |  |
         |  |  |  reuse red fan wire you cut off - to Rpi physical pin 2 (+5v)
         |  |  |
         |  |  to Fan + (red wire)
         |  |
         |  to Rpi GPIO 21 (physical pin 40)
         to Rpi physical pin 2 (ground)

   7.  Connect up everything between the small perf board and the Raspberry Pi.  Please note that using 
       GPIO pin 21 is MANDATORY as it's a special pin that supports outputting PCM signals.  Use double 
       sided tape to mount the little PCB within the case to hold it semi-permanently

   8. Re-connect up all cables on the Rpi and power it up 

   9. Follow the URL above to download the , and fanctrl.service files as well as a 
      slightly modified script from:

         cd /tmp
         wget -O 
         wget -O
         wget -O fanctrl.service
         sudo chmod 700
         sudo mv /usr/local/sbin/

      I recommend to place these files in /usr/local/sbin/

  10. Please review that script and if you are using a different Raspberry Pi GPIO pin (default is GPIO 21 /
      physical pin 40), you need to update the variable in this script to use that new pin

         NOTE:  Using this pin CONFLICTS with the use of any I2S-based sound HATT devices like a Fe-Pi Audio Z v2

Ok, lets' now get the software going:

  11. With the Raspberry Pi near you, run the /usr/local/sbin/ script and type in "100" (without
      the double quotes and hit enter.  At this point, the Rpi should be giving a 100% duty cycle voltage to the 
      fan which means it should spin at 100% speed.  If the fan doesn't run at full speed, you need to troubleshoot 
      all your connections, wiring, etc. until it works as expected

  12. Assuming the above "full speed" step worked, now enter in a lower duty cycle number like "50" and make sure 
      the fan slows down but doesn't stop.  Ok, now enter in "0" and enter to stop the fan.  Now enter back in "50"
      then enter and confirm the fan starts back up and runs at the lower speed.  At this point, keep trying lower 
      and duty cycle numbers until the fan no longer starts up and spins after being stopped.  For example, I have 
      one fan where the fan wouldn't start until it had a duty cycle of "32" and a different fan at "38".  
      Understanding that minimum start number, I then would use a number of "35" for the first example and "40" for
      the other fan to give me a little bit of margin and relibility

  13. Edit the and scripts and make sure that you make sure that the "FAN_PIN" and 
      "FAN_MIN" variables have the correct GPIO pin and your "reliable low" fan duty cycle value found in the step 

  14. Now run "python2" and you should see an updating list of Rpi temperatures and when
      the temperature exceeds a different thresholds, you will see a different PWM fan speed kick in and
      either speed up or slow down the fan.  If you see that, great!  It's working

  15. To make the script run at startup, do the following:

         sudo mv /tmp/fanctrl.service /etc/systemd/system 

  16. Edit this script, update the following lines to read:


         ExecStart= /usr/bin/python2 /usr/local/sbin/

  17. Now active and start the new systemd service with:

         sudo systemctl enable fanctrl
         sudo systemctl start fanctrl

  18. Confirm the python monitor is running with:

         ps aux | grep fan_ctrl

  19. Let's now test it!

        a. Depending on how well you can visually see the fan blades, consider getting a flashlight so you 
           can clearly see them spinning or not spinning

        b. Use the "uptime" CLI command to confirm the first listed "load average" is very low such as "0.15"
           which means only ONE core is loaded to 15%

        c. Visually confirm the fan blades are not spinning

        d. Run the following stress command (this comes from power supply validation section 14 from above) 
           to load up the Rpi's CPU.  Visually confirm that the CPU fan starts to slowly speed up, get to 
           full speed (probably best noticed by the increasing fan noise) and then eventually slow back
           down and STOP once the stress test is over:

              #For 4core Rpis like Rpi2, 3, 3+, 4
              stress --cpu 20 --io 20 --vm 6 --vm-bytes 25M --timeout 120s
              #For 1core Rpis like Rpi0, 0w, 1
              stress --cpu 5 --io 20 --vm 6 --vm-bytes 25M --timeout 120s

Other options:
   - Using a MOSFET transistor instead of an NPN type:  

        This alternative design can use a MOSFET transitor which can probably better manage
        coolers that have multiple fans.  This design also has a pull-up resistor to keep the fan 
        ON when the management script isn't working right:


   - Don't want to build your own little circuit board?  You can buy little pre-made boards:

60.e. Infrared (IR) transmitter and 8 channel light sensor

TBD: Setting up an InfraRed IR TX/RX Raspberry HATT board with a secondary DIY light meter sensor

  I have a complete setup working using the following HAT board:

        - This board DOES require custom LIRC packages to be compiled to be compatible due to known
          kernel issues

  I also have developed my own DIY hat design which includes a SPI-connected MCP3008 ADC with a light
  sensor to confirm that the remote device (a Finnex fishtank light) has actually turned on/off.  If
  it didn't change, there are scripts that do automatic retries, etc.

I will slowly work on adding these IR/ADC HAT and package creation instructions to this document.  
Until then, if you would like to get a copy of my notes to get started, email me.

[Chapter Gap]

70. Stuff that still needs to be added or updated

N7NIX Dan tracker
Need to consider the integration of the DanTracker document at:


into this doc.  The challenge here is that this valuable program's source code 
has long been abandoned.

   DanTracker currently does NOT support gpsd and
   - only supports GPSes on /dev/ttyUSB*
   - only supports NEMA GPSes
   - does not initialize SiRF GPSes to send NEMA
   - does support for setting the time via GPS once a day

  - even if I disable DanTracker GPS and gpsd and just run:
    cat /dev/ttyUSB0 > /dev/null
    the impact hits direwolf where it under-samples and then fails to do decodes:

          Past 100 seconds, 4275495 audio samples, 0 errors.

  #Update the config - Dantracker currently ONLY supports devices like ttyUSB0 
  # (not /dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller_D-if00-port0 )
  vi /etc/tracker/aprs_tracker.ini
  port = /dev/ttyUSB0

  #You have to get the GPS running in NEMA mode first
  sudo gpsd -N -D3 -n /dev/ttyUSB0 


  To view the current system, use:

  # Is this needed for N7NIX DanTracker?

  # Provides:          prepare-dirs
  # Default-Start:     2 3 4 5
  # Default-Stop:      0 1 6
  # Required-Start:
  # Required-Stop:
  # Short-Description: Create /var/log/nginx directory on tmpfs at startup
  # Description:       Create /var/log/nginx directory on tmpfs at startup


  # main()
  case "${1:-''}" in
      # create the /var/log/nginx needed by webserver
      if [ ! -d ${DIR} ]; then
        mkdir ${DIR}
        chmod 755 ${DIR}
     echo "Usage: $SELF start"
     exit 1

  chmod 755 /etc/init.d/prepare-dirs
  update-rc.d prepare-dirs defaults 01 99

  # ------------------------------------------------------------------------
  Check out for more RPi optimizations, etc
  # ------------------------------------------------------------------------

# This note is only relevant for F6BVP's based Rpi image (obsolete)

   You can update the various F6BVP code, AX25 stack, etc. from the included scripts:

   cd /usr/local/src/  

#Other ideas.. make the whole SD card read only

# Maybe install Xastir - old though - currently at 2.0.4
  apt install Xastir

# ---------------------------------------------------------------
# Possibly Deprecated
# ---------------------------------------------------------------

# ---------------------------------------------------------------
?Still needed for Jessie?

# /var/log items go into the tmpfs ram drive anyway

Suppress 1000s of cron lines like the following in /var/log/auth.log
#   Jan 30 18:49:01 ota3 CRON[14054]: pam_unix(cron:session): session opened for user zzz by (uid=0)
#   Jan 30 18:49:03 ota3 CRON[13055]: pam_unix(cron:session): session closed for user root

edit /etc/pam.d/common-session-noninteractive

At the end of the file, find the line:

   session required

and now add the following line ABOVE it

   session [success=1 default=ignore] service in cron quiet use_uid

80. Todo

03/17/22 - Move logrotation to an eariler section - ideally at the same time as enabling
           LOG ram drive

90. Special Topics

90.a - Use a Coastal Chipworks TNC-Pi on your Raspberry Pi

The above mentioned /etc/ax25/ script DOES have support for the TNC-Pi.  All you need
to do is edit the script to use the TNC-Pi routines vs. the Direwolf ones.  It should just work.

   1. - On the TNC-Pi board, does it have Jumpers JP2 and JP3 right next to the Rpi GPIO pin header?  
        If so, they both MUST be in-place to communicate to the TNC-Pi to change it's settings (for 
        either serial OR I2C mode).  They must remain there if the TNC-Pi is to use the serial port
        interface or REMOVED if you're going to use the TNC-Pi via the I2C bus

   2. - If you have a Raspberry Pi v3, you MUST make two changes to the setup to swap the serial
        port for use with the Bluetooth interface (required for using the TNC-PI in serial or I2C

           Edit the /boot/config.txt file and add these two lines:


           You can read more about these changes here: 

   3. - You need to enable the serial port on the Rpi with the following steps but unfortunately, 
        this approach both enables the serial port AND the serial console support at the same time.  We
        don't want the serial console support so that part has to be undone:

           sudo raspi-config --> Interface Options --> Serial Port --> YES --> Ok --> Finish

           On older Raspbian releases, you would find this in :
              sudo raspi-config --> Advanced Options --> Serial --> YES --> Ok --> Finish

        Select YES to reboot your Raspberry pi

   4. - Make sure the serial console is not enabled

      Look at the /boot/cmdline.txt file and Look for the string: 


      If you see it, you'll need to edit the file with sudo rights, remove that portion of text, save 
      the file and get ready to reboot the Rpi

   5. - Now reboot your rpi with: 

      sudo /sbin/shutdown -r now

   6. - Make sure the /dev/ttyAMA0 serial port is recognized

      ls -la /dev | grep AMA
      lrwxrwxrwx  1 root root           7 Nov  6 09:44 serial0 -> ttyAMA0
      crw-rw----  1 root dialout 204,  64 Nov  6 09:44 ttyAMA0

      If it's NOT seen, you need to try using the "sudo raspi-config" step again

   7. - Make sure there aren't any console sessions configured to use /dev/ttyAMA0

      ps aux | grep getty
      If you see something like the following, you need to fix this
         root      1077  0.8  0.1   4112  1764 ttyAMA0  Ss+  08:24   0:18 /sbin/agetty --keep-baud 115200 38400 9600 ttyAMA0 vt102

      Disable the getty running on /dev/ttyAMA0 permanently the Jessie / SystemD way with:

         sudo systemctl stop serial-getty@ttyAMA0.service
         sudo systemctl disable serial-getty@ttyAMA0.service

   8. - Make sure there aren't any AX25 interfaces already loaded

      ifconfig | grep ax

          If there are, use the command "sudo ifconfig ax0 down" to shut them down

   9. - Make sure there aren't any KISS applications already running:

      ps aux | grep kiss

      Use the command "sudo killall kissattach" to kill any running kissattach commands (also removes any mkiss commands too)

   10. - Download the newest TNC-Pi get/set tools

      sudo mkdir /usr/src/pitncgetset
      cd /usr/src/pitncgetset

      # Get the newest John Wiseman G8BPQ code - current as of 08/30/18

        # If the above links don't work, try looking for a different version of 
        # the "PITNCParams" filename.  You can also try downloading it at the following 
        # URL but that link doesn't always seem have the newest available code:


               or another alternative:

   11. - Uncompress and make sure the pitncgetset binaries are executable

      #Uncompress the archive
      sudo unzip

      chmod 750 pitnc_setparams pitnc_getparams

   12. - Check the /dev/ttyAMA0 serial port to make sure it's ok.  Disconnect the DB9 connection going from the TNC-Pi 
         to your radio.  Now run the following command (you can use control-C to stop it) and you should see NOTHING.  
         If you see garbage on the screen (something like the following):

            sudo cat /dev/ttyAMA0

         That's bad.  I recommend to shut down your TNC-Pi with "sudo /sbin/shutdown -h now", wait to see the green 
         power LED blink 7 times.  Now REMOVE the power connection from the Raspberry Pi for 30 seconds and then 
         reconnect power.  Again try the above command and make sure NO garbage or any out text output is coming

   13. - Try running the pitnc_getparams program:

         - If running on a TNC-Pi v1 board:

            ./pitnc_getparams 0 0
         - if running on a TNC-Pi v2 board:

            ./pitnc_getparams 1 0

      You should see something like:

         Using Serial port /dev/ttyAMA0

            PIC Software Version           0
         01 TXDelay - Zero means use ADC  25
         02 Persistance                  250
         03 Slottime (in 10 mS)            6
         04 TXTail                         2
         05 Full Duplex - Not used         0
         06 Our Channel (Hex)             00
         07 I2C Address (0 = async) Hex   00
            ADC Value                     30
         8 0 19 fa 6 2 0 0 0 1e f1 c0 sum 0

   14. - Making changes to the TNC-Pi via I2C

      - After making any changes to the TNC-Pi's register, you need to reboot the unit.  To do so, run the 
        I2C command:

           ./pitnc_getparams 15 2

   If you want to try to use the TNC-Pi in I2C mode (frees up the onboard /dev/ttyAMA0 serial port), 
   here are some additional things to check:

     14.a - You will need to change the "I2C address" using the above commands to enable I2C mode, power down the 
            Rpi and take off the TNC-PI JP2 and JP3 jumpers (if you have an older TNC-Pi board)

     14.b - see if the I2C drivers are installed:

        lsmod | grep i2c
        i2c_bcm2708             4834  0
        i2c_dev                 5859  0

        Both entries MUST be there

     14.c - make sure the i2ctools are installed

          sudo apt install i2c-tools

     14.d - Make sure the I2C bus can be found

         make sure the you see bus #1 (should show something like: i2c-1   i2c   3f804000.i2c   I2C adapter)
            sudo i2cdetect -l

     14.e  - See if you can see the TNC-Pi in I2C mode on address 15:

        sudo i2cdetect 1

        WARNING! This program can confuse your I2C bus, cause data loss and worse!
        I will probe file /dev/i2c-1.
        I will probe address range 0x03-0x77.
        Continue? [Y/n]
             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
        00:          -- -- -- -- -- -- -- -- -- -- -- -- --
        10: -- -- -- -- -- 15 -- -- -- -- -- -- -- -- -- --
        20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
        30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
        40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
        50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
        60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
        70: -- -- -- -- -- -- -- --

        The output above shows NOTHING which means it's not correct.  

           Troubleshooting items to be added

     14.f - Enable I2Ckiss

          Assuming you want to use the TNC-Pi in I2C mode with the Linux AX.25 stack, you would 
          then run the command:

             i2ckiss 1 15 vhfdrop

     The rest of configuring the AX.25 stack is configured in the above mentioned /etc/ax25/
     script.  That script DOES support the TNC-Pi setup with some simple changes.  Read and edit the
     script to suit your needs.

     Ps.  Here is an older thread will take you through a way to get things working via the I2C bus 
          and not the serial port which might get you going:

90.b - Use a Kenwood D710 KISS TNC with your Raspberry Pi

Are you looking to use a Kenwood D710 packet TNC (or really any KISS TNC) with your Raspberry Pi and 
NOT say a soundcard based TNC?  If so, you're in luck!  Nearly everything is ready to go in this project 
to use your D710 as your packet TNC.  

   NOTE: If you're looking to use a different KISS TNC with your Raspberry Pi, it should be pretty easy
         to modify the setup to replace the D710 tool with a generic "KISS ON" script.  Email me if you
         need help

To enable D710 support, try the following steps.  I've tested this and it works with my D710:

   #0. Open a terminal window on your Rpi

   #1. Become root
   sudo su

   #2. Download and build a very good D710 configuration tool
   cd /tmp
   wget -O tmd710_tncsetup.c
   gcc -o /usr/local/bin/tmd710_tncsetup tmd710_tncsetup.c

   #3. Identify your USB to serial port - unplug it and re-plug it into your Raspberry Pi and run these commands
   dmesg | tail --lines 10 | awk -F"now attached to " '{print $2}' | grep ttyUSB

   #4. Edit the /etc/ax25/ script file and change the following to read as follows


   #5. Update this line to whatever is the serial port name connected to the D710 head's TNC port.  For example, 
       this is what I'm using 


     | CRITICAL: Using the long device names found by the predictable serial interface system via  |  
     | 11/22/20 /dev/serial/by-id gives segmentation faults when running the required kissattach   |
     |          program used for packet radio.  If you aren't going to use packet radio, don't     |
     |          worry about it.  If you ARE setting up packet radio, this issue has been reported  |
     |          and confirmed as an issue in the libax25 and ax25-tools packages from the VE7FET   |
     |          or official AX.25 repos                                                            |
     |                                                                                             |
     |         For now, DO *NOT* use the /dev/serial/by-id style name at this time with used with  |
     |         the Linux AX.25 kissattach program at this time                                     |

   #6. Edit the /etc/ax25/axports file and on the line starting with the name of your configured tnc such as "vhfdrop", 
       change the speed from "19200" to "9600"

   #7. Turn on your D710 with an antenna attached to the main radio body and the D710 head itself, go into the menus and 
       set AUX menu item 528 "COM Port Baudrate" to 9600.  Why?  the D710 configuration tool used here only works at 9600

   #8. On the D710 head itself, power off the entire radio and turn it back on.  This is to make the TNC take the new serial 
       speed setting
   #9. That's it and the rest of the packet instructions in this doc should just work

If things don't work right, I would recommend to start with a few troubleshooting steps:

   0. Make sure your Rpi has an internet connection

   1. Open a terminal window on the RPi

   2. Shutdown the ax25 system just in case with "sudo /etc/ax25/"

   3. Install minicom with:
      sudo apt update
      sudo apt install minicom

   4. Run minicom by typing in "sudo minicom" in the terminal window

   5. In Minicom, use the key sequence Control-a and then "o" (that's an Oh) to get into the Minicom menus.  In there, 
      go to the serial port setup and change the "Serial device" to your proper device such as "/dev/ttyUSB0", and change 
      the speed to 9600,8n1.  Once done there, hit enter to go back one menu, select "Save as DFL", hit enter, select "Exit"

   6. In Minicom, use the key sequence Control-A and then "x" to exit minicom.  This is usually done to avoid weird issues 
      with Minicom and changing serial port speeds

   7. On your D710 head, tap the lower right "tnc" soft-key until the very top left TNC status area goes blank

   8. Restart minicom

   9. On your D710 head, tap the lower right "tnc" soft-key (bottom of the very right vertical buttons) and keep taping that 
      soft-key until very top left LCD "TNC status" area goes from blank to "aprs12" to "packet12"

  10. At that point, you should see something similar the following in minicom:
      Kenwood Radio Modem
      AX.25 Level 2 Version 2.0
      Release 09/Mar/11 3Chip ver 1.02
      Checksum $1859

  11. If you hit enter, you should get a response back of "cmd:".  If you don't, you need to troubleshoot your setup until this works.

      Ps.  Notice the TNC firmware version shown above.  It's recommended to be running v1.02 which is the newest version 
           of the firmware available here:

91 - Custom Kernel Compiling the Raspberry Pi OS way

[ Work in progress ]

As part of a working effort with Bernard F6BVP, we are looking to install custom kernel modules 
for modern Raspbian kernels that REVERT known toxic changes to the following modules:



   This effort is NOT for Linux newbies and will take hours to complete due to the size of the 


   1. An external storage device - I recommend at least 32GB of space on either an SSD or spinning HD.
      Do NOT do these builds on the Raspberry Pi's SD card as you *will* permanently damage and crash 
      the SD card.  This is due to the punishing level of writes which SD cards are not designed to
      support.  You've been warned.

   2. You are either using the Stretch version of Raspbian-Lite or have disabled the GUI system from 
      startup via the raspi-config.  This is required to maximize the amount of available RAM for
      the build.

   3. You have minimized the amount of RAM allocated to the video system.  This is covered in the 
      beginning chapters of this doc using raspi-config.

   4. You have mounted an external /tmp partition to support overflowing of any build objects.  This
      is automatically done in my available at:

      I noticed when I was doing a kernel build, I was seeing the "overTemp" icon (a red thermometer) 
      blinking in the upper right corner of the HDMI console display!  The compile was seemingly running
      ok but obviously the Rpi was throttling it's performance.  I didn't place any heat sinks on my Rpi 3B+ 
      but to support these builds, I placed a small +5V fan to blow air on it and the icon went away.

   6. You have lots of time to let the builds do their thing as there is a LOT of code in the Linux
      kernel and *all* Raspberry Pi hardware (even the newest RPI v3B+) is generally SLOW for work
      like this.

Mount the storage:

   1. Mount the external storage manually or via my "" script

      Initializing mount directories if required: /tmp/root /tmp/home
      Debian 8 or 9.0 - Jessie / Stretch : SystemD style

      Drive sda is LVM partitioned

      Logical volumes not enabled, starting
        PARTIAL MODE. Incomplete logical volumes will be processed.
        3 logical volume(s) in volume group "vg_dranchlt3" now active
      mounting /tmp/ with LVM
      mounting /tmp/home

      /usr/src/archive is present
      /usr/src/archive/Rpi-scratch is present... ready to go!

   2. Move into the external drive

      cd /usr/src/archive/Rpi-scratch

Install any required build tools and other dependencies:

   NOTE:  Most of the required GCC tool chains, etc. are already pre-installed
          in Raspbian

   sudo apt install git bc

Get the Raspbian kernel code

   The command you run depends on the version of code you want to compile:

      mkdir kernel
      cd kernel

      #Mainline 4.14.x code
      git clone --depth=1

        #The above clone command with the "--depth 1" option downloads the newest 4.14 code and it
        # took 1min48sec and 1.1GB space on a Rpi 3B+ with a cablemodem connection

      NOTE#2:  If you wish a specific kernel branch w/o downloading everything (say the 4.1.x line
               which ended at 4.1.21), you would run:

                  git clone --depth=1 --branch rpi-4.1.y

              This took 1min 13sec and 833MB of space on a Rpi 3B+ with a cablemodem connection

     NOTE #3:  If you wish to build ANY of the older kernels, do NOT include the original URL's 
               "--depth=1" option.  This command took 46min and 3.92GB space on a Rpi 3B+ with a 
               cablemodem connection

   Once downloaded, you can see what kernel version you would build by running the following
   command (I would build the 4.14.95 version by default):

      #Look at the top of the file for the versions
      less linux/Makefile

Build a stock 4.14.x kernel to ensure everything works:

   #This assumes you are building for a Rpi 2 or newer (this will NOT work for an RPI v0 or v1)
   # This took 14 seconds to complete
   cd linux
   make bcm2709_defconfig

   #This step took 76 minutes on a RPI v3B+ to build 4.14.95
   time make -j4 zImage modules dtbs
   [all the build stuff removed]

   real    76m32.336s
   user    283m40.400s
   sys     16m41.059s

Confirm what kernel files you already have installed:

   #Show the current kernel you're running:
   uname -a
   Linux rpi3plus 4.14.93-v7+ #1191 SMP Wed Jan 16 11:53:33 GMT 2019 armv7l GNU/Linux
                  ^^^^^^^^^^^                                            ^^

   #List the current kernel modules for current and previous kernels
   ls -la /lib/modules/
   total 32
   drwxr-xr-x  8 root root 4096 Jan 19 10:14 .
   drwxr-xr-x 16 root root 4096 Jun 26  2018 ..
   drwxr-xr-x  3 root root 4096 Aug  4 14:21 4.14.59+
   drwxr-xr-x  3 root root 4096 Aug  4 14:21 4.14.59-v7+
   drwxr-xr-x  3 root root 4096 Dec  8 12:35 4.14.79+
   drwxr-xr-x  3 root root 4096 Dec  8 12:35 4.14.79-v7+
   drwxr-xr-x  3 root root 4096 Jan 19 10:14 4.14.93+
   drwxr-xr-x  3 root root 4096 Jan 19 10:14 4.14.93-v7+  <------------------------

   #List the current and previous kernels
   ls -la /boot
   total 17079
   drwxr-xr-x  3 root root    2560 Dec 31  1969 .
   drwxr-xr-x 23 root root    4096 Aug  4 14:17 ..
   -rwxr-xr-x  1 root root   23315 Jan 19 10:14 bcm2708-rpi-0-w.dtb
   -rwxr-xr-x  1 root root   22812 Jan 19 10:14 bcm2708-rpi-b.dtb
   -rwxr-xr-x  1 root root   23071 Jan 19 10:14 bcm2708-rpi-b-plus.dtb
   -rwxr-xr-x  1 root root   22589 Jan 19 10:14 bcm2708-rpi-cm.dtb
   -rwxr-xr-x  1 root root   24115 Jan 19 10:14 bcm2709-rpi-2-b.dtb
   -rwxr-xr-x  1 root root   25311 Jan 19 10:14 bcm2710-rpi-3-b.dtb
   -rwxr-xr-x  1 root root   25914 Jan 19 10:14 bcm2710-rpi-3-b-plus.dtb
   -rwxr-xr-x  1 root root   24087 Jan 19 10:14 bcm2710-rpi-cm3.dtb
   -rwxr-xr-x  1 root root   52296 Jan 19 10:14 bootcode.bin
   -rwxr-xr-x  1 root root     142 Jul 11  2018 cmdline.txt
   -rwxr-xr-x  1 root root    1601 Jun 26  2018 config.txt
   -rwxr-xr-x  1 root root   18693 Dec  8 12:36 COPYING.linux
   -rwxr-xr-x  1 root root      41 Jan 19 10:14 .firmware_revision
   -rwxr-xr-x  1 root root    2628 Jan 19 10:14 fixup_cd.dat
   -rwxr-xr-x  1 root root    6695 Jan 19 10:14 fixup.dat
   -rwxr-xr-x  1 root root    9895 Dec  8 12:35 fixup_db.dat
   -rwxr-xr-x  1 root root    9875 Jan 19 10:14 fixup_x.dat
   -rwxr-xr-x  1 root root     145 Jun 26  2018 issue.txt
   -rwxr-xr-x  1 root root 4943016 Jan 19 10:14 kernel7.img  <------------------------
   -rwxr-xr-x  1 root root 4695264 Jan 19 10:14 kernel.img
   -rwxr-xr-x  1 root root    1494 Dec  8 12:35 LICENCE.broadcom
   -rwxr-xr-x  1 root root   18974 Jun 26  2018
   drwxr-xr-x  2 root root   13312 Jan 19 10:14 overlays
   -rwxr-xr-x  1 root root  682532 Jan 19 10:14 start_cd.elf
   -rwxr-xr-x  1 root root 2869028 Jan 19 10:14 start.elf
   -rwxr-xr-x  1 root root 3955716 Jan 19 10:14 start_x.elf

   #Confirm you have enough space in /boot
   Filesystem                       1K-blocks     Used Available Use% Mounted on
   /dev/root                         15240048  1859012  12729236  13% /
   devtmpfs                            495480        0    495480   0% /dev
   tmpfs                               500088        0    500088   0% /dev/shm
   tmpfs                               500088    19160    480928   4% /run
   tmpfs                                 5120        4      5116   1% /run/lock
   tmpfs                               500088        0    500088   0% /sys/fs/cgroup
   /dev/mmcblk0p1                       43539    17478     26061  41% /boot  <------------------------
   tmpfs                               100016        0    100016   0% /run/user/1001
   /dev/mapper/vg_dranchlt3-lv_root  51475068  8763180  40074064  18% /tmp
   /dev/mapper/vg_dranchlt3-lv_home 249515908 21266576 215551528   9% /tmp/home

Install the new kernel you just compiled:

   #This takes about 30 seconds for all of these steps
   sudo make modules_install
   sudo cp arch/arm/boot/dts/*.dtb /boot/
   sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
   sudo cp arch/arm/boot/dts/overlays/README /boot/overlays/
   sudo cp arch/arm/boot/zImage /boot/$KERNEL.img

Confirm what you now have installed:

   #List the current kernel modules for current and previous kernels
   ls -la /lib/modules/
   total 36
   drwxr-xr-x  9 root root 4096 Jan 27 13:26 .
   drwxr-xr-x 16 root root 4096 Jun 26  2018 ..
   drwxr-xr-x  3 root root 4096 Aug  4 14:21 4.14.59+
   drwxr-xr-x  3 root root 4096 Aug  4 14:21 4.14.59-v7+
   drwxr-xr-x  3 root root 4096 Dec  8 12:35 4.14.79+
   drwxr-xr-x  3 root root 4096 Dec  8 12:35 4.14.79-v7+
   drwxr-xr-x  3 root root 4096 Jan 19 10:14 4.14.93+
   drwxr-xr-x  3 root root 4096 Jan 19 10:14 4.14.93-v7+
   drwxr-xr-x  3 root root 4096 Jan 27 13:26 4.14.95-v7+  <-------------------

   #List the current and previous kernels
   ls -la /boot
   total 17226
   drwxr-xr-x  3 root root    3072 Dec 31  1969 .
   drwxr-xr-x 23 root root    4096 Aug  4 14:17 ..
   -rwxr-xr-x  1 root root   23315 Jan 27 13:26 bcm2708-rpi-0-w.dtb  <-------------------
   -rwxr-xr-x  1 root root   22812 Jan 27 13:26 bcm2708-rpi-b.dtb  <-------------------
   -rwxr-xr-x  1 root root   23071 Jan 27 13:26 bcm2708-rpi-b-plus.dtb  <-------------------
   -rwxr-xr-x  1 root root   22589 Jan 27 13:26 bcm2708-rpi-cm.dtb  <-------------------
   -rwxr-xr-x  1 root root   24115 Jan 27 13:26 bcm2709-rpi-2-b.dtb  <-------------------
   -rwxr-xr-x  1 root root   25311 Jan 27 13:26 bcm2710-rpi-3-b.dtb  <-------------------
   -rwxr-xr-x  1 root root   25914 Jan 27 13:26 bcm2710-rpi-3-b-plus.dtb  <-------------------
   -rwxr-xr-x  1 root root   24087 Jan 27 13:26 bcm2710-rpi-cm3.dtb  <-------------------
   -rwxr-xr-x  1 root root   17513 Jan 27 13:26 bcm2835-rpi-a.dtb  <-------------------
   -rwxr-xr-x  1 root root   17629 Jan 27 13:26 bcm2835-rpi-a-plus.dtb  <-------------------
   -rwxr-xr-x  1 root root   17659 Jan 27 13:26 bcm2835-rpi-b.dtb  <-------------------
   -rwxr-xr-x  1 root root   17916 Jan 27 13:26 bcm2835-rpi-b-plus.dtb  <-------------------
   -rwxr-xr-x  1 root root   17792 Jan 27 13:26 bcm2835-rpi-b-rev2.dtb  <-------------------
   -rwxr-xr-x  1 root root   17617 Jan 27 13:26 bcm2835-rpi-zero.dtb  <-------------------
   -rwxr-xr-x  1 root root   17822 Jan 27 13:26 bcm2835-rpi-zero-w.dtb  <-------------------
   -rwxr-xr-x  1 root root   18448 Jan 27 13:26 bcm2836-rpi-2-b.dtb  <-------------------
   -rwxr-xr-x  1 root root   18266 Jan 27 13:26 bcm2837-rpi-3-b.dtb  <-------------------
   -rwxr-xr-x  1 root root   52296 Jan 19 10:14 bootcode.bin
   -rwxr-xr-x  1 root root     142 Jul 11  2018 cmdline.txt
   -rwxr-xr-x  1 root root    1601 Jun 26  2018 config.txt
   -rwxr-xr-x  1 root root   18693 Dec  8 12:36 COPYING.linux
   -rwxr-xr-x  1 root root      41 Jan 19 10:14 .firmware_revision
   -rwxr-xr-x  1 root root    2628 Jan 19 10:14 fixup_cd.dat
   -rwxr-xr-x  1 root root    6695 Jan 19 10:14 fixup.dat
   -rwxr-xr-x  1 root root    9895 Dec  8 12:35 fixup_db.dat
   -rwxr-xr-x  1 root root    9875 Jan 19 10:14 fixup_x.dat
   -rwxr-xr-x  1 root root     145 Jun 26  2018 issue.txt
   -rwxr-xr-x  1 root root 4930840 Jan 27 13:26 kernel7.img  <-------------------
   -rwxr-xr-x  1 root root 4695264 Jan 19 10:14 kernel.img
   -rwxr-xr-x  1 root root    1494 Dec  8 12:35 LICENCE.broadcom
   -rwxr-xr-x  1 root root   18974 Jun 26  2018
   drwxr-xr-x  2 root root   13312 Jan 27 13:26 overlays  <-------------------
   -rwxr-xr-x  1 root root  682532 Jan 19 10:14 start_cd.elf
   -rwxr-xr-x  1 root root 2869028 Jan 19 10:14 start.elf
   -rwxr-xr-x  1 root root 3955716 Jan 19 10:14 start_x.elf

   #Confirm you have enough space in /boot
   Filesystem     1K-blocks    Used Available Use% Mounted on
   /dev/root       15240048 1915832  12672416  14% /
   devtmpfs          495480       0    495480   0% /dev
   tmpfs             500088       0    500088   0% /dev/shm
   tmpfs             500088   12908    487180   3% /run
   tmpfs               5120       4      5116   1% /run/lock
   tmpfs             500088       0    500088   0% /sys/fs/cgroup
   /dev/mmcblk0p1     43539   17632     25908  41% /boot
   tmpfs             100016       0    100016   0% /run/user/1001

Ok, reboot the Raspberry Pi, log back into it and see what kernel version you're 
now running:
   /sbin/shutdown -r now

   #Log back in after it's rebooted 

   #Check to see which version you're now running

   uname -a
   Linux rpi3plus 4.14.95-v7+ #1 SMP Sun Jan 27 12:58:59 PST 2019 armv7l GNU/Linux
                  ^^^^^^^^^^^                                         ^^

   Success!  We're now running 4.14.95 for the ARM v7 CPU

Ok, so why did I write all this up?  Let's assume you want to build a SPECIFIC kernel
version like 4.1.21 kernel, you would want to issue:

   git clone --depth=1 --branch rpi-4.1.y

   #Then you have to create two workarounds for this specific older build on the newer Stretch OS
   cp include/linux/compiler-gcc5.h include/linux/compiler-gcc6.h

   and in the Makefile
KBUILD_CFLAGS   := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
                   -fno-strict-aliasing -fno-common \
                   -Werror-implicit-function-declaration \
                   -Wno-format-security -Wno-error=unused-but-set-variable \

   #It also seems the build has to be done in separate steps
   time make -j4 zImage modules dtbs
   time make -j4 modules 
   time make -j4 dtbs

   Then do the rest of the build as usual which took 18min 37sec on a Rpi 3B+


100. Errata

Page Views since 05/11/21:

Flag Counter

# 04/09/22 - Updated detail around the Raspberry Pi Foundation removing the "pi" user
#          - Added some significant details to headless (aka pre-configuration) of the
#            Pi before it's first boot
#          - Other minor cleanups
#          - Added mention of the DietPi distribution

# 03/22/22 - Improved mailx commands

# 03/19/22 - Improvements to the SD card backup section
#          - Updated the RTC section to be Bullseye compatible

# 03/17/22 - Updated the NFLOG section to include ip6table log redirection
#          - Updated the shutdown button section to reflect that the wiringpi library
#            has been deprecated in Bullseye and to now use raspi-gpio instead

# 03/16/22 - Added more details about voltage sags when connecting HDMI monitors
#          - Updated tmpfs (RAM drive) sizing recommendations for /tmp and /var/log

# 03/05/22 - Updated the doc to mention that Raspberry Pi OS 64bit version is now fully released
#          - Minor improvements around stopping Avahi from running by default
#          - Mention of possibly POORER wifi performance on the new Zero 2 W model
#          - Removal of the openssl-blacklist package since it seems it was dropped in Bullseye
#          - Made a global switch from using apt-get to using apt as it has better dependency
#            checking
#          - Added explicit download commands for the fan control script and other minor improvements
#          - Added additional test steps to verify the fan control script is working with
#            heat generated from CPU load

# 12/29/21 - Added a new Rpi file backup section that is good for intermediate backups between
#            doing full SD card backups

# 12/20/21 - Clarifying note on build dependencies for ax25-apps
#          - Added comments about the seemingly reversed behavior from the Raspberry Pi Foundation
#            of disabling Predictable Ethernet Interface names, installation of CUPS, etc
#          - other minor spelling fixes

# 12/01/21 - Added a new script for checking if you need to reboot after a new kernel install
#          - Added a note about any failures when running the usermod 

# 11/29/21 - Added a download link for the rules.v6 file

# 11/21/21 - minor updates about the OS differences with Bullseye 

# 11/17/21 - more recommendation on cases including ones for the new RPI0W2

# 11/16/21 - Updated the temp controlled fan section title to reflect it's a variable speed fan too

# 11/14/21 - Added a packet log timestamping section with a fun learning on the run-parts tool

# 11/13/21 - Updated the Intro section quite a bit to talk about the new Bullseye OS release 
#            including more details on support lifetimes, details on the 64bit OS section clarifying
#            that the 64bit Bullseye is still considered BETA
#          - Some minor improvemetns in the RTC section
#          - Enable printing kernel boot lines on the GPIO serial console 

# 11/12/21 - Updated the Direwolf section for Bullseye support

# 10/31/21 - Started updating the foc to add support for the upcoming Bullseye version of 
#            Raspberry Pi OS
#          - Updated the script to fully support IPv6
#          - Other clean-ups made 

# 10/29/21 - Added the new Rpi Zero 2 W SBC and did various cleanups to the hardware
#            spec area
#          - Added a brief section on overclocking

# 09/28/21 - Added a mention of PiShrink for users wanting more complex backups
#          - Updated the language that the Fe-Pi is actually the Fe-Pi Audio Z v2
#          - Added a note that the temperature controlled FAN chapter and it's chosen
#            GPIO pin CONFLICTS with I2S-based sound devices like the Fe-Pi Audio Z
# 09/27/21 - Mentioned newest Rpi4 models are using the newer SOC found in the 400 and CM4

# 09/23/21 - Updated the temperature controlled fan section a bit more
#          - Completed the optional SSH key section

# 09/15/21 - Updated the temperature controlled fan section to add complete full details
#            and enabling systemd to start the monitor

# 09/11/21 - Updated the Nexus DR-X Fe-Pi clone sound device information 

# 09/10/21 - Fixed a broken index link

# 08/14/21 - Improvements and minor fixes for the NFS section

# 08/05/21 - Updated the postfix section for better details and improved security

# 07/24/21 - Minor improvements in the descriptions in the bluetooth section

# 07/23/21 - Added more details for supporting IPv6 firewalls
#          - Updated the risks about deleting the pi user account
#          - Added a missing step of locking out the "pi" user
#          - Updated the direwolf.conf file to default to plughw:2,0 now for PulseAudio
#            enabled Raspberry Pi Buster OSes
#          - Added a direwolf troubleshooting hint for users running GUIs that have
#            PulseAudio enabled
#          - Minor formatting improvements

# 07/18/21 - Specifically mention the use of a 470 Ohm resistor for the LED
#            indicator for DCD
#          - Fixed a misspelled index link

# 07/10/21 - Updated the setting of direwolf's audio level section a bit

# 07/07/21 - Updated the Direwolf section a bit
#          - updated the version of ax25mail-utils

# 06/19/21 - Added some additional troubleshooting steps in the GPSD section for
#            setups that don't have USBAUTO disabled

# 06/16/21 - Added a new section on Rpi LEDs, changing what they do, etc
#          - Added the beginnings of a new appendix item for a DIY IR transmitter,
#            light sensor, and other small project integration

# 06/14/21 - Added section 60.d to set up PWM fan control
#          - Minor gpsd section updates
#          - Updated the file system location of vcgencmd

# 06/03/21 - Updated the text in the firewall section a bit
#          - Added an important missing step to update the rules.v4.checked ruleset
#          - Re-arranged the raspbi-config section to reflect newer versions of the tool; 
#            removed the memory-split item as that's been removed from the tool as well
#          - updated the patching section to now use apt instead of apt-get

# 06/02/21 - Addition of OS selection with FULL vs. Lite, 64bit vs. 32bit, etc.
#          - Merger and Clean up of 64bit vs. 32bit OS details

# 06/01/21 - Added URLs for wifi testing with metal cases as well as thermal performance
#          - Added mention about known older firmware issues with 5Ghz wifi
#          - Added mentions about 2.4Ghz wifi interference with USB 3.0 devices

# 05/31/21 - Added a new section on cases, fans, and temperature control
#          - updated the ntp and time with gpsd sections a bit
#          - Added a section of how to full or partial restores from your SD backup
#          - Added another GPIO pinout url
#          - Updated the index a little bit
#          - Did another spellcheck run

# 05/29/21 - indexed the hardware section for better linking 

# 05/12/21 - Fixed some minor HTTPS issues

# 05/11/21 - Revamped the legacy OSS Direwolf Dead Airtime TX support section 
           - Added mention of Signalink units and isolation transformers
           - Disabled the caching of this page so people will always get the newest
           - Added a webhits tracker just to see how much the doc is really used by people

# 04/26/21 - Added some more bluetooth checks and examples; added notes for Windows 
#            clients

# 04/24/21 - Made the bluetooth serial console operational across reboots

# 04/22/21 - Added a new serial console over bluetooth section 

# 04/18/21 - Updated the shutdown button section to include some GPIO pin 
#            status and monitoring tools, improved the shutdown button testing, etc

# 04/16/21 - Updated the RTC section to be a little more clear on some steps as well
             as fixes for some high temperature scenarios

# 04/14/21 - Minor tweaks to the sudo vim /etc/watchdog.conf

# 04/12/21 - Make recommendation for users to be more selective on OS updates using
#            apt-get dist-upgrade --no-install-recommends

# 03/28/21 - Some improvements to the RTC section regarding I2C setup and troubleshooting
           - Added a mention in the Fe-Pi section about it's presence on the I2C bus

# 02/22/21 - Fixed the APRS LCD screen rotation

# 02/07/21 - Minor comment changes to the IPv6 workaround for GPSd

# 02/02/21 - Fixed the Direwolf DCD LED wiring hook up.  Thanks to Fred N7FMH for this one

# 01/18/21 - Some improvements made to the script
#          - Added mention of the RIM-Lite sound devices

# 01/01/21 - Noted that the USB-C power issue on Rpi4 boards was fixed in the Rpi4
#            v1.2 hardware revision

# 12/31/20 - Updated the warning about long /dev/serial/by-id names when editing
#            the /etc/ax25/ script

# 12/30/20 - Updated the Linpac section to push the "NOT RECOMMENDED" install using the Deb repo 
#            approach to the very bottom to minimize confusion

# 12/28/20 - Added some misc cleanups

# 12/24/20 - Added a mention that a similar I2S board like the FePi units are 
#            available from the Nexus DR-X people
#          - Added the inclusion the Masters Communications DRA-36 USB sound device

# 12/14/20 - Added a note about maximum PCM audio level output from the Fe-Pi
#            as well as how some radios have input gain settings

# 12/04/20 - Minor updates to the Direwolf section
#          - Added a note that Raspberry Pi OS now installs PulseAudio by default
#             which is a benefit for Bluetooth audio users

# 12/02/20 - Added details on how to interpret Direwolf level output and 
#            what it means in terms of "twist", etc.

# 11/29/20 - Cleared up some steps for building Direwolf between v1.6 and v1.5
#          - Updated the direwolf section index numbering
#          - Updated the DWC2 USB kernel module details to be clearer

# 11/23/20 - Added a section on alternative OS distros

# 11/22/20 - Added a new CRITICAL issue around long predictable /dev/serial/by-id names 
#            and kissattach for say serial connected KISS TNCs, etc
#          - Clarified the "Work around for significant Predicable Interface naming bug with AX.25"
#            section

# 11/21/20 - Added Kenwood D710 KISS TNC support to the setup
           - Added notes that the Fe-Pi Audio Z v2 HAT board seems to be EOLed

# 11/13/20 - Tuned the Fe-Pi mixer settings; more hints around the Nexus DR-X and
             NW Digital boards

# 11/10/20 - Added more details for the CM3+

# 11/04/20 - Added the new Raspberry Pi 400 specs and other HW spec cleanups

# 10/31/20 - Added a direct link to the Direwolf dead TX workaround section

# 10/29/20 - Updated the Direwolf instructions to reflect the new final 1.6 release
              - removed unneeded patches for Direwolf 1.6 beta 
           - Substantial updates to the hardware section with more clarity around the 
             Compute Module 4 (CM4) and CM4IO
           - Added notes around rc.local deprecation on systemd-enabled OSes

# 10/27/20 - Added mention of other sound devices like the DINAH, DRAWS, Nexus DR-X, etc

# 10/20/20 - Added details on the new Raspberry pi 4 Compute module and I/O board
           - Added some gross HTML code at the top of this page for image rotation; 
             Please let me know if this doesn't look right on your browser

# 10/11/20 - Updated the Direwolf section to detail various options for users to
             avoid the dead TX airtime DWC / direwolf issue

# 10/07/20 - Updated the Direwolf TX dead-air issue and added updates on the OSS 
             workaround but also added fix details and NEW possible work arounds

# 10/06/20 - Fixed a incorrectly specified /etc/asoundrc filename

# 09/30/20 - Added CSD decoder URLs in the uSD hardware section

# 09/24/20 - Did a significant review, re-formatting, and improved steps for many sections
             across the entire doc
           - Added download links for the iptables rulesets
           - Added a section on assigning static IPs for eth0
           - Minor index formatting fixes

# 09/08/20 - Updated the 20d.soundcard-mixer section a bit to recommend users to ONLY
             turn up the output to the soundcard channel (LEFT or RIGHT) connected to the 
             radio and put the other level to 0.
           - Improved some of the working and formatting of this soundcard-mixer section 
# 09/07/20 - Minor updates

# 08/26/20 - Added "30.a Configure your Rpi to connect to an existing Wifi AP for network access"

# 08/08/20 - Added mentions of Debian Unstable aka Sid to building Direwolf

# 07/26/20 - Added a recommendation to only use Class-10 SD cards and a URL of how to learn
             more and benchmark your chosen card
           - Added a link to the sound chip for the Fe-Pi
           - Added more critical notes around the Fe-Pi's "headphone mux" setting

# 07/23/20 - Added some aoss-style Direwolf troubleshooting steps

# 07/13/20 - Added a small blurb on picking a radio for your setup and what to be aware of

# 06/17/20 - Minor improvements to the Direwolf OSS workaround section

# 06/05/20 - Minor index changes

# 06/01/20 - Added a possible alternative I2S soundcard to the Fe-Pi AudioZ

# 05/29/20 - Added mention of the new 8GB Raspberry Pi 4, newly renamed Raspberry Pi OS (was 
             Raspbian), and mention of the upcoming native 64bit Raspberry Pi OS version

# 05/25/20 - Updated the Rpi SD image section as the SD card backup section to move from
             the script to
             which supports multiple formats

# 05/08/20 - Fixed the Direwolf Cpack patch

# 04/15/20 - Added a Direwolf Cpack fix to address the incorrect 0.1.1 version issue
           - Fixed typo with applying Direwolf OSS patch

# 04/14/20 - Added spec URLs for what GPIO pins are initialized high/low in the PTT GPIO section

# 04/13/20 - Added a kissparms setting in the /etc/ax25/ script to disable the CRC 
#            which hurts the initial packet connection upon reboot

# 04/05/20 - Fixed the wrong command to make the listen program SUID root
#          - Added the disabling of Wifi
#          - made the disabling of Bluetooth more comprehensive
#          - Added links to a recommended installed package
#          - Added a section on how to only use SSH keys and disable passwords 

# 04/02/20 - Changed the aplay test example to be more generic to find more hardware possibilities

# 03/31/20 - Fixed the updating of tocalls for Direwolf

# 03/27/20 - Fix duplicate HTML section tags for the Linpac section

# 03/08/20 - Updated section 6 on SD card protection to mention two new options.  Once is to enable
#            the new OverLayFS option or make the SD card read-only
#          - Improvements to the watchdog section
#          - Other minor wording improvements

# 03/07/20 - Updated the full hostapd.conf file to deal with new incompatibilities with 
#            rts and fragmentation settings

# 03/02/20 - Added notes on which boards run which kernel file images

# 01/17/20 - Updated the Rpi stability testing section a little using "stress"

# 01/12/20 - Updated Direwolf DEV to 1.6D and updated the build section to better support the OSS
             sound card workaround as well as be more consistent

# 12/29/19 - Updated the Linpac develop release to 0.27

# 12/21/19 - Added libudev-dev to the Direwolf section as a preparation for Direwolf 1.6 when
             it releases

# 12/15/19 - Clarifications on the Rpi v3 wifi connection being direct and NOT thought the 
             USB bus

# 12/14/19 - Added a serial port section to the Rpi hardware differences section

# 12/08/19 - Updated the Direwolf section to support the new Direwolf 1.6 Cmake system
           - Updated the soundcard test section to test either the Fe-Pi or USB soundcard options
           - Started moving the documentation to use "apt" instead of "apt-get"

# 12/02/19 - Added mentions of new November firmware that lowers the Rpi4 power consumption
             as well as new reports of Wifi interference with different HDMI display resolutions

# 11/30/19 - Fixed an important missing "2" in the call in rc.local

# 11/10/19 - Added how to check out Direwolf's DEV branch via git

# 11/09/19 - Hardware section update to mention that the Rpi4 now has all Broadcom firmware
             on a dedicated eeprom chip vs. all previous Rpi firmwares were stored on the 
             SD card
           - Mention in the RTC and Direwolf section how an RTC clock can avoid very old 
             APRS packets from getting igated weeks later

# 10/10/19 - Typo cleanups

# 08/29/19 - Updated Rpi3 specs

# 08/27/19 - Added Rpi 1+ hardware specs

# 08/09/19 - Added the script into the archive for users 
             who like to learn more about what Direwolf is hearing.  Use the new 
    script to run nightly via cron

# 07/26/19 - Some cleanup in the firewall section and removed the unused 
             rules.v4-test step

# 07/24/19 - Some additional cleanups and improvements to the gpsd section say not
             to auto-detect new GPS units, etc.

# 07/22/19 - Added the "v" option to the firewall verification section to be more clear

# 07/21/19 - Updated various sections including RTC and GPS sections a bit
           - Made updates about the initial raspi-config setup working strange for
             Buster after changing the Locale encoding and doing a reboot might be wise
             before continuing on

# 07/21/19 - Updated the DS3231 RTC section on understanding more about counterfeit DS3231
             boards, where to get boards with real chips, and another check if your RTC
             is running on a different I2C bus
           - Updated the downloaded Raspbian Buster image which is now using the officially
             released Debian Buster URLs; as some specific fixes for dual monitors, etc.

# 07/20/19 - Added an extensive note on the fact that NFTABLES has become the default firewall 
             technology starting in Raspbian Buster over iptables.  This seems to be in a state
             of transition in Buster as key things are missing to be a complete nftables solution.
             I will add support for this in time but IPTABLES seems to still be the primary 
             interface in Buster to configure firewalls and it remains fully supported.

# 07/19/19 - Updated the script with the new reduced AMPR address range

# 07/18/19 - Rpi hardware USB updates

# 07/17/19 - Minor index fixes

# 07/16/19 - Added another URL on buying quality micro-SD cards
           - major aspell spell checking run done

# 07/14/19 - Extensive soundcard section update to add full setup on the Fe-Pi I2S 
             sound device and why
           - Added Direwolf OSS work around support for USB-based sound devices
           - updated the script to include checks and start the Direwolf OSS 
             workaround if required
           - Added a summary of differences in the hardware section

# 07/13/19 - Added a known USB hardware issue section
           - Added details on the used USB controllers with different Rpi hardware

# 07/10/19 - Added a note about a known problem with E-type USB-C power cables
             with the Rpi4
           - Added more modern terminology (Wifi-6) and USB 3.2 Gen 1

# 07/08/19 - Added more details in the external USB drive section

# 07/07/19 - Added a note around the missing libncursesw6-dev library
           - Added a sub-section on formatting your external storage device with a
             Linux file system
           - Updated the script to be cleaner
           - Renamed the scratch storage area to /usr/src/archive/Rpi-scratch 
             instead of the previous Rpi2-scratch

# 07/04/19 - Updated the tmpfs RAM drive section to be more clear
           - Added a missing point to put the ax25mail-utils package updates
             on-hold to avoid the Raspbian repos from overwriting it

# 07/03/19 - Minor update in the Rpi hardware comparison section

# 07/02/19 - Updated the HDD idle and mount/umount sections a bit
           - More formatting cleanups

# 06/30/19 - Updated the watchdog section
           - Updated and added the use of the and scripts
           - Upgraded Direwolf to version DEV 1.6C for Raspbian Buster

# 06/29/19 - Beginning support for the Raspberry Pi 4 and Buster
           - Major update to the Raspberry Pi HW differences section
           - Added support for initial IPv6 firewall rules
           - Make the formatting of this document a little less ugly

# 06/15/19 - Updated the /usr/local/bin/ to better show the
             Rpi health bitmap, included C to F temp conversion, etc

# 06/12/19 - Clarified the warning when installing the libax25 package using 

# 05/11/19 - Added a link discussing all the alternative GPS-like satellite 
             systems running
           - Added a link for a cheaper CM108 sound device

# 03/24/19 - Added automake to support other debian related OSes (Mint)
           - Updated the ve7fet section to use shorter checkconfig descriptions
           - Updated the ve7fet libax25, ax25apps, and ax25tools versions
           - added th suid root work around for Linpac users not running ax25spyd
           - added a ax25spyd URL

# 03/16/19 - Removed the legacy installconf steps as they were confusing users

# 03/08/19 - Cleaned up the intro section and some index links

# 02/25/19 - Updated the notes

# 02/18/19 - Updated the RTC section to reflect that newer Raspbian versions somewhat
             correctly auto-configure DS3231 RTCs but not to support the temperature 
             sensors, etc.  Made other cleanups here as well.

# 02/10/19 - Updated notes on the AX.25 packages with the VE7FET repo, the Official AX.25
             repo, and Debian repos
           - Updated the linpac section to build from the Git develop branch
           - Updates to the Linpac section to add more sub-sections to build ax25mail-utils

# 01/27/19 - Added a new special topic on building new kernels.  This section is a work 
             in progress to support installing custom-built kernel modules for the ax.25

# 12/29/18 - Added a link on USB soundcard enumeration

# 12/28/18 - Added a quick /tmp RAM drive expansion for packaging Direwolf
           - Cleaned up the index, aligned sub-topics, etc

# 12/07/18 - Basic reminder if autoreconf doesn't work, users didn't follow section 16 first

# 11/16/18 - Added the Raspberry Pi 3A+ to the specs area and cleaned up the section a little

# 11/10/18 - Updated to the script that includes tuning of the AX.25 window sizes
             and other parameters

# 11/04/18 - Updated the Direwolf section to use a shorter description during the checkinstall 
#            packaging
#          - Added workarounds for increasing the /tmp file system when packaging direwolf

# 11/03/18 - Updated the watchdog section 

# 10/25/18 - Updated to include low power and CPU throttling counts

# 10/23/18 - Minor updates to the audio card packet level section

# 10/21/18 - Updated the and ax25-up.new2 scripts to support new VE7FET changes to listen
#            and other improvements
#          - Updated the libax25 section to note that the use of the 
#            script is no longer needed if you're using the Aug 2018 version of the VE7FET repo
#          - Made several changes to the script
#          - Minor index formatting fixes

# 10/20/18 - Major updates to the AX25 package builds from VE7FET to adapt to the removed 
#            "installconf" section
#          - Added missing step before compiling the AX25 packages to enter the 
#            /usr/src/archive/Rpi2-scratch/ directory
#          - Updated the note in the libax25 compile section since it seems the VE7FET
#            repo has been repaired.
#          - Added more formatting for the ax25 packages and made more clarifying comments

# 10/19/18 - Minor updates talking about when needing the Glibc patch workaround script 

# 10/18/18 - Significantly updated the "Enable local storage for demanding builds" section for new
#            Linux users

# 10/17/18 - Updated the optional USB HDD mount script section

# 10/11/18 - Update to Direwolf 1.5 final release

# 09/21/18 - Added a link for a decent 12v to 5v UBEC power source

# 09/09/18 - Added IPv6 firewall examples in the directory structure at

# 09/06/18 - Added a note about IPv6 firewalls and how to do initial tests.  This document
#            does not fully cover IPv6 yet though I've added a minimal /etc/iptables/rules.v6
#            ruleset in the RPi directory snapshot

# 08/30/18 - Updated the TNC-Pi section to being up i2ckiss, etc.
#          - Improved the TNC-Pi section formatting a little 

# 08/28/18 - Remove avahi-daemon and expanded on the SSH section to include updating the
#            firewall to handle the change in port numbers

# 08/04/18 - Minor changes to the Rpi hardware section

# 07/20/18 - Added a comment in the TNC-Pi section to reboot the TNC after making any
#            register changes

# 07/19/18 - Added a note that a .deb force install is now needed for the ax25-tools
#            package due to three conflicting MAN page files
#          - Added a reminder in the picking a GPIO pin section about making sure the 
#            user has set the required GPIO Unix permissions

# 07/10/18 - Updated a URL for Raspbian and Bluetooth support

# 06/26/18 - Typo for section 70

# 05/24/18 - Some ax25 compile section cleanups

# 05/17/18 - Added a note about this doc is tested with Direwolf 1.4 but if newer versions of
#            Direwolf are available, I recommend to give them a try
#          - Fixed a broken index link

# 05/15/18 - Updated the download URL for the TNC-Pi utility

# 04/21/18 - Enhanced the iptables-ulog section to install any missing packages
#          - other typo fixes

# 04/05/18 - Added notes about enabling Wifi or SSH on a fresh install of Raspbian to enable remote
#             over-the-network only configuration

# 03/24/18 - Updated Direwolf

# 03/23/18 - More Hardware section formatting improvements

# 03/18/18 - Added a note in the AX.25 library section on how to use the
#            script when new glibc/libc updates come which cause upgrade failures

# 03/17/18 - Updated the Wifi AP+Client section a bit to include firewall updates, still kinda
#            broken but AP mode is working ok
#          - Updated the Differences in Raspberry Pi models to add the 3B+ and made the section 
#            a little clearer
#          - noted that the 3B+ doesn't support connecting a wifi u.fl connector for external 
#            antennas
#          - add a link to EOL dates for Raspbian (Jessie went EOL early)
#          - Updated the script a bit
#          - Updated the packet to Kenwood D74 section a bit
#          - Fixed some jump links

# 03/08/18 - Added dual/simultaneous wifi client AP access and AP mode 

# 02/03/18 - Enhanced the Bluetooth section a bit and updated the script

# 01/25/18 - Noted that the official SD formatter program is now available for Mac too

# 01/19/18 - Added a few URLs for an opto-isolated PTT circuits

# 01/12/18 - Updated in the index a bit

# 01/05/18 - Intentionally included the #ed out bind-interfaces line in the dnsmasq.conf file
#            so that Dnsmasq can start and run to give IP addresses to Wifi users
#          - Added additional thoughts on installing Raspbian Pixel vs Raspbian Lite
#          - Added some specific recommendations to NOT connect your Rpi directly to the Internet
#            or have a port SSH port forward going to it until you harden it's configuration with
#            say exclusively using SSH keys and disabling SSH passwords, installing Fail2ban, etc.
#          - Made the recommendation to DELETE the "pi" user once the new account is working
#            for better security
#          - Updated the URL for buying a Syba USB sound device

# 12/31/17 - Added a link to the new script to bring up AX.25 on a D74 HT
#          - Enhanced section 19 to say that if you aren't going to use Direwolf and, instead
#            are going to use a TNC-Pi or D74, skip to section 25 to get that going
# 12/30/17 - Updated the OS installation chapter to recommend installing Raspbian Stretch at all
#            costs.  
#          - Updated the details on the different hardware versions of the Rpi 

# 12/28/17 - IMPORTANT:
#            ----------
#            Added note that changes in some Linux distributions (Debian Stretch on x86 CPUs)
#            are making making the VE7FET AX.25 sources to go toxic but the Official AX.25 sources are 
#            working fine.  That's not to say there aren't important fixes in the VE7FET repo that 
#            aren't in the Official AX25 repo either.  For now, the VE7FET repo is fine for Raspbian 
#            Stretch but time might prove a switch might be required.  Stay tuned.
#          - Added libncursesw5-dev to compile ax25-apps
#          - Added a note about NOT to move the ax25.h GLIBC file if using Debian Buster

# 12/27/17 - Updated the Bluetooth section to support connecting to a Kenwood D74
#            as well as added some more advanced bluetooth commands
#          - Updated the first time power up section to monitor power brownouts via
#            seeing a yellow lightening bolt in the the upper right corner of the HDMI
#            display or the red power LED blinking.  Mentioned an inexpensive 5.1v @ 2.5A
#            power supply
#          - Added the useful tool "stress" for checking Rpi power brownouts
#          - Updated the different Rpi comparison section a bit

# 12/16/17 - New release

# 12/11/17 - Updated the Linpac version to 0.25

# 12/08/17 - Fixed some spelling errors

# 12/07/17 - Move the ax25mailutils and linpac downloads steps a bit

# 11/22/17 - Added top pictures of the LCD and RTC with click-on zoom
#          - Added reading the temp off the DS3231 RTC

# 11/20/17 - Added a new appendix section to display date, time, Internet health check, heard AX25 
#            packets, and CPU load to an I2C driven 20x4 LCD display
#          - Added a new appendix section to have the Rpi set it's date via an I2C driven
#            DS3231 RTC.  

# 11/17/17 - Updated the USB APM section and added a script to manually spin down the drive

# 11/05/17 - New publish

# 11/01/17 - Updated the Linpac configuration section regarding SSIDs to be a bit clearer

# 10/31/17 - Clarifications on BBS hierarchical addressing in Linpac

# 10/30/17 - Align the axports file to use a speed of 19200 though it doesn't really matter here
#          - Mentioned that WD Blue and WD Green series drives also do NOT support APM_level 

# 10/26/17 - Added a new hostapd issue and work around where dnsmasq won't come up 

# 10/25/17 - Added a new review the bootup logs chapter to confirm that the system is booting up without
#            errors.  Recommended to periodically do after applying OS patches to make sure things didn't
#            break
#          - Fixed some HTML character encoding issues like &, etc

# 10/22/17 - Removed the delaycompress option from all the logrotate configuration files
#          - Fixed the logrotate section to properly manage the ulogd_traffic-emu1.log file

# 10/21/17 - Added an attribute for the Linpac patch from Martin Cooper KD6YAM

# 10/16/17 - Added critical steps to enable HOLDS on the libax25, ax25-apps, ax25-tools, and Linpac
#            packages which are currently known TOCIC in the Deb repos.  Without these "holds" in place,
#            your locally built packages will get overwritten with the known toxic versions
#          - Updated the Linpac section to apply a new patch to avoid some issues when built with newer 
#            versions of GCC.  This patch will soon be integrated into Linpac 0.25
# 10/15/17 - Changed out to a new script that includes debouncing to avoid false shutdowns
#            due to say RFI, etc.
#          - Added that users now need to disable apt-daily.service to avoid automatic updates
#            in addition to removing the unattended-upgrades package

# 10/12/17 - Added package requirements to run scripts

# 10/08/17 - Fixed a missing permission stage for creating /usr/src/archive
#          - moved up the zlib1g requirement for the base libax25 package
#          - updated details on the predictable network interface names issue
#          - Some additional Direwolf checkinstall cleanups for vanilla Debian

# 09/29/17 - Fixed a cut/paste issue for installing ax25mail-utils-0.13

# 09/26/17 - Fixed some incorrect AX.25 interface names named "vhfport" when they should have been
#            vhfdrop
#          - Philosophy mention of why the direwolf.conf is in /etc/ax25
#          - added missing zlib dependencies for ax25-tools

# 09/05/17 - Increase the RAM drives for /tmp to 10MB and /var/log/ to 50MB
#          - Added a log rotation max size limit of 10M to the /var/log/packet, ax25-listen.log, 
#            and ulogd_traffic-emu1.log files
#          - Significant changes to the Wifi AP section to be compatible with Stretch
#          - Added an important warning about possible wifi vs. bluetooth reliability issues
#          - Added a recommended USB-based GPS receiver
#          - Retooled and enhanced the image backup section a bit
#          - Updated the intro section

# 09/02/17 - Added a CRITICAL work around for AX.25 and Persistent Interface naming issues
#          - Added alternative media idea to send logs to instead of the temporary RAM drive
#          - added a GPSD fix if IPv6 is disabled
#          - Added steps to install linpac and ax25mail-utils from apt-get 
#          - mentioned there might be issues with using the Linpac binaries and the VE7FET ax.25
#            repo
#          - Enabled another F-key in the example for Linpac
#          - Added a final testing section
#          - Updated the and ax25-up.new2 scripts to add more testing, Linpac start,
#            etc

# 08/29/17 - Added openssl-blacklist to the Email/Postfix section
#          - Made logrotate it's own section and renumbered all other sections to fit
#          - Added the Ulogd logs into the logrotate system
#          - Added key missing "--" in the mailx test
#          - Noted that Watchdog support in Stretch is questionable; will revisit

# 08/28/17 - Signification improvements in documentation, clearer steps throughout, etc.
#          - Added that simultaneous wifi and BT support on the Rpi v3 doesn't work well
#          - Corrected sudo command for iptables-save compound command
#          - Added how to use alternative SSH listening ports 
#          - Added a key note that no IPv6 firewall is created and to disable IPv6 for now
#          - Completed the ulogd section and using the new NFLOG approach so no more iptables
#            filter hits in the /var/log/syslog nor dmesg logs!

# 08/27/17 - Added a top note that I will be updating this document to support Raspbian Stretch
#            as time permits

# 08/21/17 - Various fixes as reported from KI6NJF : appending new unix groups to existing groups; 
#            disable auto-login added some clarification on hard drive spindown issues; missing 
#            '" root' on the mailx command on reboots; mentioned notes of not needing to unmount
#            /tmp; moved the packet monitor to TTY8

# 08/20/17 - Added an option section in the Direwolf.conf section on how to enable APRS-IS RX-only Igate
#            and MSG only TX-Igate functionality
#          - Added a section on how to interactively test APRS-IS filters with TELNET
#          - Updated the Direwolf compiling section to reflect improvements and a repaired Direwolf-1.4-patch
#            file
#          - updated the /usr/local/sbin/ script to use non LVM-partitioned USB HDs
#          - Mentioned an alternative tool "iptables-apply" to safely enable to firewall rulesets
#          - fixed some index numbering in the IPTABLES section and corrected some HTML formatting
#            issues for < characters

# 08/06/17 - Minor formatting cleanups for the index and other sections; spell check run

# 08/05/17 - Renamed section 1 to reflect it's contents a bit better

# 07/23/17 - New intro section
#          - Added a new section about other scripts to monitor the Rpi's
#            CPU and temp and other useful sysadmin scripts

# 07/05/17 - Extensively updated the Wifi AP and Linpac sections
#          - Updated the pyshutdown GPIO button section
#          - more clearly deprecated the legacy rtl8192 wifi sections

# 06/03/17 - Enhanced the script with the new ampr-ripd 2.2 and other cleanups

# 04/27/17 - Updated Direwolf to 1.4 (final release version)

# 04/24/17 - Added a test OBEACON object

# 04/20/17 - Updated the Direwolf build a bit

# 04/07/17 - Corrected required Direwolf checkinstall packages as we don't need the -dev versions

# 03/16/17 - updated checkconfig package description to be all on one line

# 03/09/17 - Updated the SD card imaging section to recommend using larger card sides, pre-format it,
#          - Updates on the Rpiv3 vs Rpiv2 boards
#          - Updated GPS setup section

# 02/28/17 - Added a URL for Bluetooth audio support

# 02/26/17 - Added a note to remove the unattended-upgrades package

# 02/21/17 - Updated setting the proper hostname and FQDN for the Rpi

# 02/20/17 - Added systemd logging to the pyshutdown section to better monitor when it's
#            being activated

# 01/13/17 - Added sending an email to root when the pi is rebooted
#          - Updated the watchdog section a bit

# 12/12/16 - Added HW watchdog support
#          - Added the beginnings of ulogd2 support to send iptables log lines to
#            a different file

# 12/10/16 - Added specific links for the script
#          - added the removal of the Avahi daemon

# 11/27/16 - Added libgps-dev to add gps support to direwolf
#          - Add some clarifying points for compiling Direwolf 1.4 Alpha

# 11/06/16 - Added a short section on HW vs SW TNCs 
#          - Added an appendix on supporting the TNC-Pi HAT HW TNC

# 10/23/16 - Updated the postfix relayhost section

# 10/22/16 - Added missing gpio group to new user creation

# 10/20/16 - Added in a lot of missing sudo command in the firewall section
#          - Enabled a beacon into Direwolf itself to indicate the system's
#            position
#          - added dnsutils as another package to install in the postfix section

# 10/19/16 - Combined the LED and Bluetooth tricks section

# 10/17/16 - Added NTP support 
#          - Added the beginnings of i2c-tncpi support to the script
#          - Added a ax25 testing subsection
#          - Added a silent audio quality check section 

# 10/14/16 - Updated the GPS section to support Jessie
#          - Updated the SD card backup section to make duplicate cards

# 10/13/16 - Updated intro to talk about the Rpi v3 hardware

# 10/12/16 - More clarity on Direwolf sound device naming
#          - Added "audio" unix group to the new user creation
#          - More thoughts on recommended security hardening (TBD)

# 10/11/16 - Fixed the incorrect command usermode (should be usermod)

# 10/03/16 - Updated section 4's name a bit
#          - Added routing to clean up old rpi-update kernel modules

# 09/29/16 - Swapped some of the sections around for the PTT circuit

# 09/15/16 - Updated to direwolf 1.3 release from -F beta version
#            also improved the installation steps and the Makefile.linux
#          - Increased the tmsfs size for /tmp from 1Mbyte to 10Mbyte
# 09/14/16 - Wifi support completed
#          - Added a new Bluetooth cheatsheet section
# 09/11/16 - Initial Wifi for Rpi v3 support started

# 09/08/16 - Updates from W6ELA
#            - Added URLs for proper TXDELAY tuning
#            - Started a new section on configuring the Wifi AP using the Rpi3 wifi and
#              deprecating the RTL8192 support (hacky, poorly supported, etc)

# 08/26/16 - Added the video unix group 
#          - Added a link to tuning your packet levels

# 08/17/16 - Moved up the connecting your radio and Wifi AP sections

# 08/14/16 - Working on adding Raspbian Jessie based Wifi AP support

# 08/07/16 - Added a note about allowing the HDMI port to always be enabled

# 08/06/16 - Added the PiShutdown section
#          - Added more details on GPIO pinouts, selection for Direwolf DCD

# 08/04/16 - Added the part number to the Syba soundcard recommendation

# 08/01/16 - HTMLized the document

# 05/22/16 - reordered the initial security section
#          - implemented the script
#          - Changed the method to lock the pi account, groupadds, etc

# 05/06/16 - Added a point to install rpi-update if it's not installed already

# 04/30/16 - Added to the HDD powerdown section

# 04/15/16 - Added an alternative way to find sound card input sampling rates
#          - Added rough notes to set NTP time ASAP

# 03/16/16 - Added recommend to create a new sudo-enabled account and DISABLE 
#            the pi account

# 03/06/16 - Added an additional todo item

# 03/05/16 - Added a gotcha section on how to fix an Rpi not being able to reboot

# 03/04/16 - Added references to alternative / pre-build Rpi images

# 02/27/16 - Added a new interactive GPIO pinout website URL

# 12/12/15 - Added DHCP client support to the firewall

# 12/11/15 - Updated iptables example to drop but not log chatty network traffic
#          - Added changes to the /etc/rsyslog.conf file for a broken setting that
#            creates a huge amount of of logs as well as other overly chatty logs
#            and duplication
#          - Added a critical fix for proper keyboard mappings to log in via the 
#            local HDMI console

# 12/10/15 - Updated logrotate configs to be more aggressive

# 12/06/15 - Added a note on the FIX_BITS option

# 11/30/15 - Fixed raspi-config typo

# 11/29/15 - Updated the Linpac section
#          - Updated the /etc/ax25/ax25-up.new2 script

# 11/28/15 - More clear wording about needing to adapt the PTT circuit for peoples
#            specific radio
#          - Mentioned that the settings in /etc/ax25/ override settings 
#            originally loaded in direwolf.conf
#          - Added Linpac

# 11/26/15 - Recommend to create a new user account and DISABLE the default "pi" 
#            account
#          - Formatting improvements

# 11/24/15 - Added a critical point about microphone bias voltages from soundcards 
#            and radios

# 11/21/15 - Added an iptables section to secure the Rpi as soon as possible
#          - Dump more packages upon first install

# 11/07/15 - Added index; revamping all sections sequentially

# 10/21/15 - Added HD APM ; shutdown button

# 10/14/15 - initial version (based on the old Wheezy doc)