Setting up a Raspberry Pi running Raspbian 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, specifically the "Stretch" or 9.0 version. This document also covers the previous Jessie version of Raspian which both of these versions use the new SystemD method of configuration. This document includes SD card hardening with a relatively secured configration for general connection to the Internet. It's also directly manageable via Wifi via say a smartphone/tablet for off-Internet maintinace as well.


0. Intro to setting up a Raspberry Pi

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:

   - Only use quality SD cards in your Pi.  It will save you from countless amount of anger of 
     "stability issues" and the setup will last a LOT longer (but it won't last forever).

   - 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.  Be sure to have all that.  Random power bricks and
     cables will not work in your favor.. especially 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 powwer bridges:

        Hobbywing RC UBEC 5v 3A Switching Regulator

   - Install the Raspbian OS on it :: Raspbian Stretch to be specific

     - I *highly* recommend you run Rasbian Stretch and not any other older versions of Raspbian.
     This document focuses on Stretch and this newest version of the OS resolves a lot of 
     SystemD issues that existed in Raspbian Jessie.  If you you're starting out with a pre-imaged
     microSD/SD card and /etc/os-release doesn't show Debian 9.x, please just bite the bullet
     and upgrade the image to Stretch.  It's eash to do as long as you have a micro-sd card reader
     on an already functioning Windows, Linux, or Mac machine:

     - Why Raspbian?  Yes, there are other alternative Linux OSes that run on the
     Raspberry Pi  but *none* of them match the support and bug fix cadence of Raspbian.  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 this approach makes it so easy to just try 
     new software stuff by just swapping out different micro-SD flash cards.  Do be wary though...  

       - Are these pre-made images using the official Raspbian OS to benefit from the patches and 
       - Were those images built and and secured properly?  
       - Are these image publishers trustworthy?  

     With that said, 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.  Here is a partial
     list of images I've tried in the past:

        - Bernard F6BVP's new Jessie based image for TNC-Pi

        - Mitch AB6MW's Wheezy based image with setup GUI which supports TNC-X and Direwolf

        - Brett's TNC-Pi centric image

        - Pidora/JNOS package with an embedded JNOS configuration manager is included 

     Word of Warning:
     I once downloaded a RPI packet radio image from a trustworthy HAM and 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 published it 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 security here but I bet 
     95% of the Rpi images out there are good.  Just watch for that last 5%.

   - If this Rpi setup is going to be directly connected to the Internet, please keep the OS patched 
     every week (ideally every day) and install a firewall on it.  Don't expose say SSH 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/2222.  Also, ONLY use SSH 
     keys (ideally with passphrases) if you can over just using SSH passwords.  These two steps 
     greatly reduces your security attack surface.

  - 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 turn it off.  You *will* eventually
    corrupt the OS if you do this.  Adding this button is very easy but takes a little project work (some 
    wire, 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 and now 3B+ versions of 
the board.  I recommend people to either start with the v3+ or upgrade to the v3+ due to many of 
it's substantial improvements:

   - CPU Cores:
        Rpi 3A+, 3B+, 3, and 2 : four ARM cores
        Rpi Zero W and v1 A/B  : one ARM cores

   - CPU Core types:
        Rpi 3A+, 3B+, 3     : Cortex-A53 ARM8 cores
        Rpi 2               : Cortex-A7 ARM7 cores
        Rpi Zero W, v1 A/B  : ARM1176JZF-S ARM6L core

        CPU Performance:
        Rpi 3 / 3A+, and 3B+ have four Cortex-A53 ARM8 CPU with 32kB Level 1 and 512kB Level 2 
        cache memory.  These A53 CPU cores have a 30% performance improvement in the CPU instruction 
        set performance PER CORE compared to the Raspberry Pi 2's Cortex-A7 4-core ARM7 cores.  That 
        alone is a substantial performance increase and remember: that's 30% better x 4 cores or 
        120% faster!   

        CPU OS support:
        The Rpi Zero-W, Older non-wireless Zero, v1-B, and v1-A boards use the old and obsolete 
        ARM ARM1176JZF-S CPU with the v6L instruction set.  While this CPU is still supported in 
        the Raspbian distro, many other ARM-enabled Linux distrubutions have DROPPED support for it.  
        This CPU is substantially slower and is less efficent than even a Raspberry Pi v2.  Raspbian 
        is one of the last Linux distros to actively maintain this old CPU and instruction set.

        CPU Clocking:
        The four cores on the RPi 3B+ and 3A+ are much faster than the previous generations:

           3A+   : 1.4Ghz per core (below 70 degrees C and 1.2Ghz when above 70 degrees C)
           3B+   : 1.4Ghz per core (below 70 degrees C and 1.2Ghz when above 70 degrees C)
           3     : 1.2Ghz per core
           Zero W: 1.0Ghz on a single core
           2     : 900Mhz per core
           1     : 700Mhz on a single core

        64 vs 32bit:
        Rpi 3A+, 3B+, 3        : 64bit cores
        Rpi 2, Zero W, v1 A/B  : 32bit cores

           The four cores on the v3 and 3B+ are now 64bit - Raspbian Jessie (8.0) kernel does 
           support 64bit but the distro binaries remain built for 32bit CPUs as there there is 
           questionable speed vs bloat benefit.  The Raspberry Pi v2, Zero W, and v1 are only 
           32bit cores.  Please remember that even though a CPU is 64bit, it doesn't gain you 
           much unless you have LOT more memory to compensate for the 2x larger data space.  
           A little board like an Rpi doesn't have a lot of RAM so it makes little sense.

   - RAM Size
        The RPi 3B+, 3 and v2 have 1GB of LPDDR2 RAM (faster speed too) where as the 3A+, 
        Zero W and v1 model B has 512MB of RAM

           3B+ / v3 / v2  : 1GB   of RAM 
           3A+, W and v1  : 512MB of RAM

   - RAM Clocking:

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

           3A+ / 3B+ / v3 / Zero W : 450Mhz 
           v2 and v1               : 400Mhz

   - 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:

           3A+ / 3B+ / 3 / Zero-W : 300Mhz
           v2, v1                 : 250Mhz

   - Wifi Networking:
        3A+, 3B+    : dual-band 2.4Ghz and 5.8Ghz 802.11AC(Wave1) wifi : new / superior on-board
                      antenna design : no U.FL external antenna solder pads

        v3          : single band 2.4Ghz 802.11N wifi : old ceramic "chip" antenna design : has U.FL 
                      external solder pads

        Zero W      : single band 2.4Ghz 802.11N wifi : new / superior antenna design : has U.FL 
                      external antenna solder pads

        v2 and v1   : No wireless

        More details on the Wifi:
           3A+ / 3B+     - 2.4Ghz and 5.8Ghz 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
           v3 and Zero W - 2.4Ghz only 802.11N  Wifi via a Cypress CYW43438 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

   - Bluetooth Connectivity:
        3A+, 3B+            - BT v4.2 with BT-Low Energy (LE) support on the 2.4Ghz spectrum
        v3 and Zero W       - BT 4.1 with BT-Low Energy (LE) support on the 2.4Ghz spectrum
        2, 1, and Zero-nonW - No BT support

   - Wired Ethernet Connectivity:
        3B+                : Gigabit Ethernet (1000Mbps)
        3, 2, 1            : Fast Ethernet    ( 100Mbps)
        3A+, Zero, Zero-W  : No wired Ethernet
        3B+           - Gigabit Ethernet (1000Mbps) using the Microchip LAN7515 chipset.  
                        Performance is still limited due to this Ethernet chip still being 
                        connected via a USB2 bus internally (roughly 300Mbps)

                      - 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       - Fast Ethernet (100Mbps) using the SMSC LAN951x chipset (Rpi 3 and 2B)

   - USB Connectivity 
        3B+, 3, 2     : Four USB 2.0 ports connected to a single 480Mbps USB 2.0 controller
        1             : Two  USB 2.0 ports connected to a single 480Mbps USB 2.0 controller
        3A+, 1        : One  USB 2.0 port  connected to a single 480Mbps USB 2.0 controller
        Zero, Zero-W  : One  USB 2.0 port  as On-the-Go (OTG) port via a single 480Mbps USB 2.0 controller

   - Cooling:
        The RPi 3A+, 3B+ CPU now has a heat spreader on the chip to better support cooling
        without a heatsink.  It also has an improved power management system for being more 
        stable at sustained high loads.

   - Power Management and Consumption:
        The 3A+/3B+ has a new power management chip which should make the Pi more stable at 
        sustained high loads.  It's also mentioned that the power consumption of the 3B+ is 
        notably HIGHER than the model 3 so a high quality 2.5A power supply is even *more 
        required* than it was before.   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:


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

A nice set of benchmarks can be found here:

A complete 3B+ breakdown:


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

The manufacturer (branch) and even the models of the various SD cards can matter.   
Please see for a lot more details but I would 
highly recommend the following:

   - NOTE:  Newer Raspberry Pi units support booting from USB (Mass Storage Device - called MSD) 
            which means you can boot from USB(hard drives and SSDs, USB flash pen drives, 
            etc,).  This means booting via a micro-SD is technically no longer 
            required (I beleive PXE is only available on the 3B+ but MSD support
            is available on the 3)

   - NOTE #2: The new 3B+ version also supports PXE booting off Ethernet

   - 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 
     counterfit cards not giving the advertised capacity or failing very quickly.
     Using off-brand cards could prove unreliable (corruption, later full-on card 
     death, etc)

        - Buy a larger card than you need : By using a larger card, the SD card can 
          better leverage it's built in wear level systems 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 encouraged to format the 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 a recommended quality blank MicroSD card to existing working Linux computer's 
     SD card reader.  This can be on your computer itself or via say a USB card reader.
     If using a micro-SD card, you might need a micro to full SD card adapter.  These
     are very inexpensive to buy and 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

  3. Download the newest Raspbian OS release 

     Raspbian Stretch image named is the current 
     image version at the time of this writing.  I would recommend to download this image 
     to a reliable location on your computer.  

        - NOTE #1: If you're going to use a Rpi 3B+, your version of Rasbian has to be
          newer than 2018-03-13 or it won't boot (older versions will see 8 flashes at the
          rainbow screen and stop there)

        - NOTE #2:  Per the comments in 
 , Rasbian
          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

        - NOTE #3:  There are two versions of Raspbian you can run:

          You can either choose to download the Raspbian version that includes a GUI interface 
          (called Pixel named after it's included web browser) which also comes with a lot of
          other packages.  You can also download the CLI only image (called Lite) which is
          considerably smaller and light weight.  

          For Rpi installations that will never have a monitor attached to it and you'll most
          likely always 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 Pixel version.  This document assumes the Lite version is

  4. At this stage, you have a few choices to get the Raspian image installed on the SD card:

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

          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.

    4.b.  From Linux: 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= of=/dev/mmcblk0 bs=2M

    4.c.  From Windows or Mac: If you are using a Windows or Mac machine for the imagine process, 
          please read these alternative guidelines:


  5. Remove your newly imaged MicroSD card and install it into your Raspberry Pi.  On the Raspberry
     Pi v0,1/2/3, install the SD card with the shiny electrical contacts pointing UP.

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 some HDMI to VGA converter devices that cost about $25.  I have one but I found the
     resulting video quality wasn't very good and it ironically spewed RF trash all across
     the VHF spectrum.  Sigh.

  b. 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

        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.  It's HIGHLY recommended that you put your Rpi behind a home "router" 
        or NAT device which doesn't have any SSH or other port forwards pointing to the 
        Raspberry Pi.  If you don't do this, 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 Raspbery Pi Zero W or Rasperry Pi 3 with Wifi-only 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

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

  e. Plug in the micro-USB cable power cable which is connected to an appropreate 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.  

        The official recommendation from the Raspberry Pi Foundation is to use a 5.1v (not 5.0v) 
        power supply that provides 2.5A of power for a Raspberry Pi3 though a thick, short, and 
        quality made USB cable.  I would say that all users need to 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
        and yellow lightening bolt light up as I added more stuff to it (I2C LCD, USB soundcard, 
        external USB HD, 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 Raspbery 
                  Pi crashes, corrupt file systems and even permanently physically damaged SD cards!  
                  Back up often!

  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:

    - 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 best settings for the video output.  Since this chapter is about connecting
            a monitor after that stage, the display WILL come up but it might not look the best
            or might not be at the highest resolution.  There are commands to try to improve
            the display such as:

              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 monitor to an already running Rpi,
             the OS will crash and you have to remove and re-connect the USB power cable.
             I'm not sure why this happens.

  2.b.  How to disable Bluetooth on the Rpi v3 and Rpi Zero W

    | Optional:                                                      |
    |                                                                |
    |    Disabling BT minimizes any issues with Wifi and opens back  |
    |    up using the on-board serial console via the GPIO pins.     |
    |    Do NOT disable Bluetooth if you intend to use it with other |
    |    Bluetooth devices like the Kenwood Th-D74 HT.               |

  With the introduction of the Raspberry Pi v3 and Zero W, the Pi team added both Wifi and Bluetooth 
  functionality.  While I welcome the wireless support, the Rpi team unfortunately also made some 
  disruptive changes:

     - the primary hardware serial console support connected on the GPIO pins to /dev/ttyAMA0 was taken 
       over by the Bluetooth interface instead.  The GPIO-pin connected serial port is now run by an 
       emulated serial port which is variably clocked based on the speed of the GPU.  If you're running
       the Pixel version of Raspbian, the changing clock speed of the emulated serial port *will*
       hurt the serial port from operating properly.

     - they moved the classic TTY-level RS232 serial port usually on GPIO pins 14/15 from /dev/ttyAMA0 
       to /dev/ttyS0 

     - It seems that simultaneous usage of the Rpi's Wifi and BT support is not very reliable.  You
       may see lots of disconnections and reassociation on both the Wifi and BT sides.  This might
       get improved over time.

  If you don't have any need for the bluetooth interface to work on your Rpi, you can disable
  it from running with:

     sudo systemctl disable hciuart

  If you want to restore console serial port access on GPIO pins 14 & 15 to use the Broadcom 
  hardware UART chip 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

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 and password

        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* log in to the directly connected HDMI/keyboard console!  In troubleshooting 
           this, if I tried to type in my password in the username prompt, the wrong characters
           were popping up (like | or +, etc)!  To fix this critical issue, see below to set 
           the right keyboard via "raspi-config"

        1. Login to your new Rpi as the user "pi" and create a new user.  For example, to 
           create the user "dranch" (please replace "dranch" with your desired username):

                 sudo adduser dranch

        2. Add this new user into the following UNIX groups:

              - "audio" (allow users to access the soundcard)
              - "dialout" (allow serial port access - if needed)
              - "gpio" (allow access to the GPIO pins)
              - "sudo" (allow root access)
              - "video" group (allow diagnostic permissions to the GPU)

                 sudo usermod -a -G audio,dialout,gpio,sudo,video dranch 

           2.a. 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

        3. Later, we will disable the "pi" account but we won't do it just yet

   3.b  Removing or disabling unwanted services

        1. avahi-daemon : This service is Linux's equivelent to Apple's Bonjour services advertisment 
                          protocol.  It's very chatty and creates a security risk. As such, I recommend
                          you remove it:

                          sudo dpkg -r avahi-daemon libnss-mdns

   3.c Install and configure a simple IPTABLES firewall

      Assuming your Raspbery 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-get update
          sudo apt-get install iptables-persistent
          # Accept any needed dependencies like iptables-persistent and netfilter-persistent

      Depending on your version of Raspbian, you might be prompted if you want to:
         "Save current IPv4 rules".  Select YES
         "Save current IPv6 rules".  Select YES

      Create an initial security based upon the rules from 
      #  Please note that the above URL file points to the WRONG files installed by
      #     iptables-persistent
      # (modified to allow SSH, not allow HTTP and HTTPS)
      #   You can also find a copy of this file at:

      1. cd /etc/iptables

         This directory should already exist, but if not, create it with:  

            sudo mkdir /etc/iptables

      2. Make a copy of the preinstalled ruleset:

            sudo cp rules.v4 rules.v4.orig

      3. Change the default firewall policies by running:

            #  If your not familar 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 not to be completely 
            #          hidden on the Internet, consider using "REJECT" instead of "DROP" 
            #          below in the actual rules.v4-test ruleset.  Packets that are 
            #          ultimately REJECTED will get a rejection notice vs. be silently
            #          dropped.   Please note, the seeing of REJECT in these top policy
            #          lines is NOT allowed (only ACCEPT and DROP are allowed here).  
            #          As such, leave these lines to DROP for now
            sudo vi rules.v4    

      4. Save and exit your changes in the rules.v4 file

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

            sudo cp rules.v4 rules.v4-test
            sudo vi rules.v4-test

         This "rules.v4-test" file will be used to TEST all firewall changes before they are made 
         the default firewall upon every boot).  Add in the the following rules (if not already 
         present).  Make any changes you so desire but just be sure you understand what you're doing:

         The below firewall example:

            + ALLOWs incoming SSH connections on TCP port 22
            + 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

         Do the appropreate copy/pastes and any possible changes you might want


# 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

# 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.

# 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

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


      6. Activate the new rules with the following command:

         # NOTE:  If you made any mistakes in the above rulset file and if you activate 
         #        the firewall without special precautions, you run the risk of loosing 
         #        your network connection!  If this happens, you'll need to re-connect 
         #        the Rpi via the local keyboard and monitor to can restore access with:
         #             Basic way to enable rulesets which can pose risk
         #             iptables-restore < /etc/iptables/somefile
         #  #1 -  Alternatively, I encourage you to use my protected firewall-confirm 
         #        script.  This script will activate the 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!
         #           cd /tmp
         #           wget
         #           sudo chmod 700 /usr/local/sbin/
         #           sudo mv /usr/local/sbin/
         #  #2 - AH6IX wrote in and told me about the included "iptables-apply"
         #       program that essentially does the same thing as my script.  I haven't 
         #       looked at this progrm yet but this might be a good (or better) way to 
         #       go too

         #Load and merge the new settings
         sudo iptables-restore < rules.v4
         sudo iptables-restore < /etc/iptables/rules.v4-test 

      7. Hopefully you didn't just loose your network connection to your Rpi (you wouldn't
         if you use my recommended script) due to any typos.  Confirm 
         you still have a working network connetion 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:

            sudo iptables -L

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

           8.a.  Basic approach:

                 sudo sh -c "iptables-save > /etc/iptables/rules.v4"

           8.b. approach:

                 #It's critical that you include the trailing "&" character for proper operation
                 sudo /usr/local/sbin/ &

                 #Once you start this command, you'll start seeing a timer run, showing 
                 # text like:  [10][11][12][13][14][15][16][17][18][19][20][21][22][23][24][25][26][27][28][29][30]

                 # Since you can see the timer, that means the network is still working.  That's
                 # good!  To keep this version of the firewall runningi, type in the command:
                 touch /tmp/fwok

                 #Your typing of the command above might get intermixed with the timer running but
                 #it will work fine.  If you typed in that command in time before the 30 second
                 #timer expired, you should see:
                 # /tmp/fwok found.. new firewall took effect..
                 # [1]+  Done                    sudo /usr/local/sbin/

           8.c.  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/iptables.checked

      9. Now enable the firewall to start up upon every boot by adding the following
         lines in the key startup file:

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

     10. Make the script executable with:

           sudo chmod +x /etc/network/if-pre-up.d/iptables
     11. To make sure things are working by default if your Rpi is rebotted, let's reboot!

            sudo /sbin/shutdown -r now

     12. Once the Rpi has rebooted, log back in, and ensure that the output of the command:

            sudo iptables -L

         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)

      | IMPORTANT:                                                                   |
      |           It's very important to understand that the above firewall ONLY     |
      |           secures the IPv4 protocol.  If you have a public IPv6 address and  |
      |           you don't have a firewall on it, your system is VULNERABLE!        |
      |                                                                              |
      |           If you're not sure if you have an IPv6 address already running,    |
      |           try the command:                                                   |
      |                                                                              |
      |              netstat -6 -rn | grep UG                                        |
      |                                                                              |
      |           If you see something come back, you INDEED have IPv6 connectivity! |
      |           The above IPv4 firewall does NOT impact the IPv6 protocol what so  |
      |           ever as an IPv6 firewall is configured via the ip6tables command.  |
      |           If you intend to enable IPv6 on your Rpi, you MUST enable a        |
      |           similar ruleset for v6.  If you need help with this, feel free to  |
      |           reach out to me.                                                   |
      |                                                                              |
      |           For now in this document, I will DISABLE IPv6 protocol support.    |

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

Now that your Raspberry Pi has some initial protection, let's start configuring things:

  | NOTE:                                                                           |
  |      It's important that you run this command using your newly created username |
  |      and NOT being run as the "pi" user.  It matters!                           |

   1. Run the Raspian OS configuration tool:

         sudo raspi-config

   2. Change the following areas

      NOTE:  The raspi-config program has changed a LOT over they years and this following
             prompts reflect the layout and settings for Raspbian Stretch.  If your version
             looks different or has things in different places, that's ok.
         - Hostname
              - Make the hostname something unique

         - Boot options
             - Desktop / CLI
               - If you installed the "Lite" version of Raspbian, you're not going to 
                 be running Xwindows and consuming all that RAM for the GUI.  A such, 
                 select "Console"

         - International options
              - Locale 
                   - I selected "en_US.UTF-8 UTF-8"  (USA)
                   - I unselected "en_GB.UTF-8 UTF-8"  (Great Brittan)
                   - When prompted, I then selected default locale: en_US.UTF-8

              - Timezone
                   - I selected US --> Pacific-New

              - Keyboard layout (this option is only seen when running raspi-config via
                the HDMI console):
                   IMPORTANT: If you are in the US and you're only presented with 
                              "English (UK)", select OTHER, then select "English (US)"

              - Wifi country
                   - If you have an Rpi v3 or Zero W, I selected "US United States"

         - Interfacing options
              - Camera     : If you plan on using a Raspberry PI camera, 
              - SSH        : I recommend to enable SSH
              - VNC        : If you installed the full version of Raspian Pixel and intend to manage
                             it via a remote GUI, enable this
              - SPI        : If you have any SPI high speed devices and plan to use then, enable this
              - I2C        : If you have any I2C low speed devices and plan to use them, 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, do NOT enable this option

              - 1-wire     : If you plan on using the 1-wire slow speed devices, enable this
              - Remote GPIO: If you plan on enabling the remote GPIO via pigpio network functionality,
                             enable this

         - Advanced options
              - "Expand the file system" - (OPTIONAL): If you noticed when you first booted your 
                                           Raspberry Pi that it was "Expanding the Filesystem on 
                                           the SD card", you won't need this step.  If you didn't 
                                           see this or missed it, enable this option.  It will prompt 
                                           you to reboot.  Accept that and reboot

              - Memory Split: If you're running the Lite version of Raspbian, you can reduce the
                              the amount of RAM given to the video system to 16MB and give as 
                              much back to the OS.  I'm using 16MB

   3. If you've made any changes to your Rpi via raspi-config, it's time to reboot

   4. Once the Rpi boots back up, log in as your newly created use (in this example, I created 
      the user "dranch").  Did it work and you were able to login?  Great!  If not, you MUST
      fix this before moving on.

         NOTE: As mentioned above, I saw an issue here where I couldn't SSH in with the  
               password that was set for the newly created user when it was done on the 
               Rpi console.  This issue turned out to be an issue with the wrong keyboard 
               layout (default is UK and not US) set in the OS.  Once I changed the mapping 
               to US, I had to change the password again).  See above

   5. If you're now logged in as your new user, make sure you can use the "sudo" command
      such as:

         sudo ls -la /root

      Did that work too?  If not, you MUST fix this before moving on.

   6. DELETE the "pi" user

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

           a. First make sure there isn't anything important in the /home/pi directory that
              you might want to keep:

                 sudo ls -la /home/pi

              If there is anything you want to keep, copy out to somewhere else first

           b. Now delete the "pi" account

                 sudo userdel -r pi

   7. Disable auto-login

         Double check: If you installed the GUI version of Raspbian (not the Lite version), the system 
         by default will auto-login the "pi" user to the LXDE desktop.  This is insecure.
         To disable this, run:

            sudo raspi-config

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

   8. Remove any unneeded or unwanted applications

        Depending on the Linux distro you installed on your Rpi (Pixel), you probably 
        brought in a bunch of stuff you won't need.  I recommend you uninstall what 
        you don't need.  For example:

           The Pixel version of Raspbian includes:
              - OpenOffice suite of document, spreadsheet, and presentation creation tools
              - Wolfram GUI scientific package is included on the Pixel version of Raspbian
              - The triggerhappy hotkey tool used for IR remote controls, etc
           # To remove these programs
           sudo apt-get remove --purge wolfram-engine libreoffice* nuscratch

        You can get a complete list of what's installed in your Raspbian OS by running:

           sudo dpkg -l | less

        | IMPORTANT:                                                                |
        |  Unless you know what each package does and understand it's dependencies, |
        |  do NOT remove it                                                         |

   9. It's worth noting that Debian includes an auto-updating package.  While some people
      might like and even NEED this concept here (aka.. lazy or inattentive people), it's
      probably NOT good idea for amateaur radio applications and I've just seen too many 
      upgrades cause problems.  Once a system has gone bad, remote system can become 
      unreachable and repairing it can be very difficult if not impossible until fixed 
      packages are released.  As such, I recommend you check the presence of the tool 
      and remove it:

               dpkg -l | grep unattended-upgrades

               If the package is installed, remove it with:

                  sudo dpkg -r unattended-upgrades

               Next, there might be some left over cruft that needs cleaning:

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

            If you have multiple remote Rpi based sites you're maintaining, I'd 
            recommend to upgrade the most "accessible" *first* (including a reboot).  If that 
            upgrade does well, then kick off remote upgrades for all your other deployed 
            units.  Can be as simple as using SSH and running the following commands to 
            start an upgrade and reboot (with checking the Unix exit code for each step).
            You can also consider using audomation systems like Salt, Ansible, Puppet, etc.
            but that's beyong the scope of this document

  10. Now, 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):

          sudo apt-get clean
          sudo apt-get update
          sudo apt-get autoremove
          sudo apt-get upgrade
          sudo apt-get dist-upgrade

  11. Prepare a new script to occasionally purge old kernels

      Raspbian (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 enter in as followins:

          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-get -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 go ahead and put it in the right place, give it execution permissins and run it:
          sudo mv /tmp/ /usr/local/sbin/
          sudo chmod 700 /usr/local/sbin/
          sudo  /usr/local/sbin/

  12. IMPORTANT:  Update the RPI's firmware and possibly move to a better, bleeding edge
      kernel, etc

          sudo rpi-update

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

         sudo apt-get install rpi-update 

  13. If any new updates or new kernels were  installed, reboot to make all updates active

         sudo /sbin/shutdown -r now  

  14. 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 implimented the above IPTABLES firewall, you'll need to update it
            to first port TCP port 2222.   Add that rule in the /etc/iptables/rules.v4 
            file and follow the process to use the /usr/local/sbin/ script
            to make that active.

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

            #To restart the service
            sudo systemctl restart ssh

         d. If you implimented the above IPTABLES firewall, I'd recommend to 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.

         e. Once all that is completed, any incoming SSH program will have to be specifically
            told use port 2222 to connect:

               ssh -p 2222 your-username@your-hostname

   Future:  Advanced security thoughts that I'll add into this doc some day

         - use SSH keys ONLY (no passwords)
           - Makes brute force attacks almost impossible as long as your version of sshd
             doesn't have bugs.  Can create very large amount of log entries

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

5. Fixing some current Raspbian issues (Gotchas)

  1. If you plan on using NFS on your Raspberry Pi, 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

  2. Other gotchas and fixes will go HERE 

6. Configure temporary RAM file systems to minimize writes 

As your Rpi runs, it will accumulate logs in the /var/log directory.  This can be dangerous
as the SD card can fill up and over time, it can actually wear out the SD card.  Sending the
log files to a RAM drive removes this risk but if your Raspberry Pi reboots, you loose all your
logs if it's rebooted.  This is a decision you might not like if you're having instability
issues and want to capture all logs to troubleshoot the issue.  Other alternatives can include:

   - Mount the /var/log and /tmp directories to an external USB device such as a USB HDD, SSD,
     or even a USB pendrive

   - Using a MUCH larger SD card than you require so the RPi can better wear level the writes
     across the SD card (still not a great idea in my opinion)

   | NOTE:                                                                                      |
   |     Regardless of enabling the RAM drive logging or not shown in this section, I recommend |
   |     you follow the Logrotate section below to manage and compress all log files so the     |
   |     file system doesn't fill up.                                                           |

I still recommend to use the ramdrive approach so lets get started with that.  Run the "df" command 
and make sure you see key directories like:


Specifically, notice the use the "tmpfs" file system (or not) which is a ram drive.  It should 
look like:

tmpfs             441580    6012    435568   2% /run
tmpfs               5120       4      5116   1% /run/lock
tmpfs             441580       0    441580   0% /sys/fs/cgroup
tmpfs              20480     128     20352   1% /var/log
tmpfs               1024       0     10240   0% /tmp

The use of the tmpfs RAM drives is the normal setup on Jessie based Raspbian installs but NOT
Raspbian Stretch.  It's important to check and make /tmp and other log directories go to the 
RAM drive or they will wear down your limited write SD card.

The new way to configure the use of RAM drives (but is unclear how any changes 
here will be retained when/if that script is updated):

   #NOTE:  In Raspbian Jessie and Stretch, 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"

#Append the following lines below all other lines:
vi /etc/fstab
tmpfs           /tmp            tmpfs   defaults,noatime,mode=1777,size=10m   0   0
tmpfs           /var/log        tmpfs   defaults,noatime,mode=0755,size=50m  0   0
#/var/lock is still handled via the tmpfs system to /run and /var/lock is a symlink to /run/lock
#tmpfs           /var/lock       tmpfs   defaults,noatime,mode=0755,size=10m   0   0

Don't reboot your Rpi just yet...

6.a. Next, Noatime File system optimization

Enable the noatime option to minimize file system writes on your root file system.  
For example on my Rpi2:

  vi /etc/fstab

     # for Stretch that uses UUIDs, it looks like:
     PARTUUID=92f034a6-02  /               ext4    defaults,noatime  0       1

     # for Jessie, it looks like:
     /dev/mmcblk0p2  /               ext4    defaults,noatime  0       1

Go ahead and reboot your Rpi right now.  When it comes back up, make sure the various 
mounts now are mounted to a "tmpfs" file system

7. Enable/Disable IPv6 upon booting

Since there isn't any IPv6 firewall loaded upon boot, I current will explicitly recommend to 
DISABLE the IPv6 protocol.  To confirm IPv6 is currently running, run the following command:

  ip address

From there, under the second interface, you'll see a line prefixed with "inet6".  That's the 
IPv6 link local address.  Your setup might have even other lines showing IPv6 site-local, 
privacy address, 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: enxb827eb2532fc:  mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
      link/ether b8:27:eb:25:32: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

To disable IPv6, edit the /etc/sysctl.conf file and change or ADD the following lines 
to the bottom of the file:

   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

Ok.. now reboot your Rpi and once it's back up, log back into it and run the "ip address" command.  
Make sure there aren't any "inet6" addresses showing up (even link-local ones).

[Chapter Gap]

9. Enable power management for attached USB HDs 

For some program compiling tasks, running the compiles via a remotely mounted NFS share doesn't work 
as for some reason, the "autoconf" stage of configuring the Makefiles fail.  As such, the only other 
option here is to compile things on a locally mounted file system.  Doing this on a Raspberry Pi's SD 
card is dangerous as you can easily wear out the flash cells on the card.  The far better solution here 
is to use an external USB HDD or SSD.  The challenge with using hard drives is that the Raspberry Pi 
defaults to leaving the hard 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 too (that and consume excess power).  To make sure the HD's
auto-spin down feature is enabled, do the following:

   NOTE: One challenge here is that some hard drives might be 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.  If your USB hard drive is like this, you MUST first connect a *powered* USB hub    |
       | (one that has a power brick connected to the wall) to the Rpi and then connect the USB drive to |
       | the hub.                                                                                        |
       |                                                                                                 |
       | 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-get 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 allow the HD to power down

       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 HD adapter 
              is not passing all the IDE commands codes though.  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, edit the /etc/hdparm.conf and change:

      #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.

   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, let it spin down.  ;-)

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

   SystemD cheatsheet:

   #show running daemons
   systemctl | grep running

   #I recommend to disable Avahi (Bonjour) for it's network spamming
   sudo systemctl disable avahi-daemon.service

   #See what else might be running
   ls /etc/rc3.d/

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

   # Disable the special key keyboard mapping tool
   sudo update-rc.d -f triggerhappy remove

   #Disable the Rsync daemon - usually doesn't autostart without editing the /etc/default/rsync file
   sudo update-rc.d -f rsync disable

11. Specific Syslog Tuning

  a. (OPTIONAL) On 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 xconsole not running (when you Rpi isn't running Xwindows 
     because you're using 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 consumes additional log space:

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

  c. You'll find that Raspbian begins log 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 tempoary RAM drive now):

         rm -f /var/log/debug*

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

Once you enabled the IPTABLES firewall from the previous section, you probably noticed
it begins log too much stuff to too many 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, you'll be pretty safe.  

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

Why do you have to do something special?  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.  

I recommend you just set this up *AS IS* since using other facility levels have other 
ramifications like sending messages to the console, dmesg, etc.  It's a pain and something 
I've never liked about IPTABLES when the old stateless IPCHAINS system never did.
Oh well.. that was then.. this is now so lets fix it.

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

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

     #Three library files
     find / | grep -e -e -e

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

  2. Install ulogd2

      sudo apt-get install ulogd2

  3. Confirm it's been already 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





  5. Restart Ulogd to get the new settings

      sudo service ulogd restart

  6. Alter your firewall to use the new Ulogd system

       Edit the /etc/iptables/rules.v4 file and find the line:
       -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: "

  7. Reload the firewall set following the previous recommendations in the Firewall section of this
     doc and 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!

  You can learn more about Ulogd2 here:

In a little bit, we'll add 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

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-get install postfix logwatch bsd-mailx dnsutils openssl-blacklist

# As the Postfix package installs, it will prompt you for specific settings for your
# environment.  Most likely, you'll want to select Postfix to be:

    "Internet with Smarthost"

       This means that your Rpi will need to contact another email server to "relay"
       the email to the Internet.  This "smarthost" is almost always your ISP and
       most require this to control email spam.

    # In this example, the hostname I entered in is the following.  Change this to
    # match both your Rpi's system's hostname and domain name

    # Smarthost / SMTP relayhost - here, it's not that you put in the
    # actual IP of the remote host but the domain name that will accept
    # this email.  In my case, I would put in a hostname that has an MX record
    # configured to accept email for the "" domain.  If you're not 
    # sure, contact your ISP for the proper MX relay or "smarthost" hostname and
    # domain name or full qualified domain name (FQDN).  For me, that's

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:			dranch@removed&ft;change this to reflect your full email address>

Once you edited that file, run the command:

    sudo newaliases

This command will silently compile this new alias 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.

Next, on the upstream relayhost you entered in above, make sure that this machine will actually 
accept email from your Raspberry Pi's IP address.  For most ISP's MTAs (remote email servers 
that accept email), this won't be needed but if you run your own upstream "smarthost", you might
to need to update the "access" database.  If you do have to make changes to the access database,
make sure to also compile 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 "test1 " | mailx root

There won't be any output on the command line but you can see if there were any other issues
by looking at the local email server log:

   sudo less /var/log/mail.log

Next, go see if this new email was ultimately received on your chosen destination email address.  
If it wasn't received, you need to check the local and remote email logs.  Do NOT proceed past
this step until this is resolved.

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

If the test email notification was received, I would recommend to now recommend to have the 
system send you an email when 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):

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

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

Now that you have an email server running, are hopefully running an IPTABLES firewall with
logging support going through Ulogd, etc, all going to a RAM drive, 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

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

   sudo apt-get 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 to have the follow items at the TOP of the file and 
delete any duplicate lines from any of the other stanzas in the file.  

Also, if the "delaycompress" parameter is present, comment it out by adding a "#" in front of

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

Finally, if you followed the instructions on the Ulogd section for IPTABLES logging,
I recommend to rotate those logs as well.  Edit the /etc/logrotate.d/ulogd2 file
and append the following lines:

   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 rotate the logs on it's regular schedule.

14. Install important sysadmin and monitoring packages?

Thought 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

   #Install them and their required dependencies
   sudo apt-get install vim tcpdump lsof gpm telnet

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

  # Install a very useful serial terminal program to troubleshoot serial ports, TNCs, etc
  sudo apt-get install minicom

Next, if /boot partition on the SD card gets corrupt, you can fix it if you install these
tools ahead of time (if not already):  

  Please note that the Raspbian Wheezy version of dosfstools is broken

  sudo apt-get install dosfstools

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

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

# A nice tool to confirm if your Rpi is stable and isn't experiencing power brownouts as either identified
# on your Rpi as:
#   - The RED power LED blinks
#   - You see a yellow lightening bolt in the upper right corner of the Rpi's HDMI console

   sudo apt-get install stress

   #This put a CPU load of 38 on an RPi v3 for 2 minutes
   stress --cpu 20 --io 20 --vm 6 --vm-bytes 25M --timeout 120s

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

One of the critical issues with the entire Raspberry Pi SBC line (and many other Linux SBCs btw) 
is there is no way to safely shutdown the OS w/o logging into the device via the console, 
SSH, etc.  Some SBCs include a shutdown button on the device itself but the Rpi line doesn't.
This is *very* bad as Linux can and will corrupt the OS on the SD card if it cannot be 
gracefully shutdown.  Fortunately, it's not too hard to add a shutdown button.

The first thing to do is to figure 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, pick
a GPIO pin for your setup.  I'm using the following pins:

    Direwolf PTT on Rpi2:
      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 on Rpi2:
      Rpi pin 33 (Broadcom GPIO 13) :: connect to cathode of LED (short lead / smaller metal inside LED)
      Rpi pin 34 - GND              :: connect to anode of LED (long lead / larger metal inside LED)

      Rpi pin 18 (Broadcom GPIO 24) :: connect to 10k resistor, then one side of a momentary switch
      Rpi pin 20 - GND              :: Connect to other side of momentary switch

I used to use as an outline for 
this section and code BUT:

   - This person's design does not use a resistor to protect the GPIO line.  This is an
     EXTREMELY bad idea and can physically damange 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 switch to protect the Pi.

   - The above script doesn't support a debouncing capability and I was experiencing false shutdowns
     due to I beleive RFI issues.  The below script comes from:

     This script requires you to hold down the button for THREE seconds and then the Rpi will 
     gracefully shut down.

   - I enhanced this script with improved system messaging that was previously mentioned in this 

Ok, do the following:

   a. Get the script on the Rpi
      cd /tmp
        #Old script - doesn't support debouncing 
        #   don't use this one - wget
        #sudo mv /usr/local/sbin/

      sudo chmod 700 /usr/local/sbin/

   b. 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
      INT = 24

      and replace it with say (I'm using broadcom pin 24):

Next, edit the /etc/rc.local file as root:

  sudo vi /etc/rc.local
  find the line that says "exit 0"
  exit 0

  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.  The key here is that it DOESN'T give any errors on loading.
Ok.. you're ready for the next step.  Go ahead and type in control-C
to exit the Python program.  It will throw an error on exit but go
ahead and just ignore it.

Ok, next, let's wire up the button.  Go ahead and shutdown 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).  Disconnect the USB power cable to the Rpi.

Now, connect up the following simple circuit (this example uses Broadcom GPIO 24):

   1. Rpi pin 18 (Broadcom GPIO 24) connected to on 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 Rpi pin 18 - GND
Once the button is wired up and connected to the correct GPIO pins on the Raspberry
Pi, go ahead and power up your Rpi.  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.

Once the Rpi is fully booted, let's give the shutdown button a try.  Give the momentary 
switch a push (the voltmeter shows the voltage going in 0.0v) but the Raspberry Pi should
stay up.  Ok, now HOLDDOWN the button for at least three seconds and the Rpi should 
begin to gracefully shutdown the OS.  The Raspberry Pi will then blinks it's GREEN 
activity LED 10 times.  Once the OS is shutdown,  only the RED power button will stay 
on.  On the Rpi pins, I now see the voltage at 1.03volts.  To boot your Rpi back up, 
you have to remove and then re-connect the Rpi's USB power cable.

One final note:

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

Alternative shutdown solutions if you don't like this recommended solution:

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.  The goal here is 
to have the computer (the Raspberry Pi) brought back online instead of you having to manually 
cycle the power.  

   NOTE:  Whenever the watchdog kicks in, you 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                                                         |
   |                                                                                                  |
   |            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 Out of Memory (OOM killer)     |
   |            but it doesn't seem to always work for system hangs.                                  |
   |                                                                                                  |
   |            It's unclear if enabling things 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. Rasbian Stretch includes watchdog 5.15-2 which is supposedly fixed      |
   |            but the documentation hasn't caught up.  I beleive the proper solution now is to      |
   |            exclusively use the Systemd approach and NOT use the watchdog package.  TBD           |
   |                                                                                                  |
   | 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 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
         ls: cannot access /dev/watchdog: No such file or directory

   3. For Raspbian Stretch, temporarily follow the recommendations found in

      Seems this recommendation is avoiding the SystemD approach 

      10/03/18:   I've received reports that the Systemd approach is working fine

   4. For Raspbian Jessie:

         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

         #Stretch does not need this setting due to the tighter integration with Systemd

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

   5. 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

   6. 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 

   7. Raspbian Jessie ONLY - Install the software side of things:

         sudo apt-get update
         sudo apt-get install watchdog

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

         # Raspian Stretch
         #   TBD on it's compatibility

         #  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:

   9. Now, enable (but not yet start) the service with:

         sudo systemctl enable watchdog

   10. Now edit the /etc/watchdog.conf file and un-# out the following lines:

         max-load-1             = 24
         watchdog-device        = /dev/watchdog

   11. Go ahead and enable this service to start now and in the future

         sudo systemctl start watchdog.service

   12. Make sure the watchdog kernel module is now being used by showing a "1" at the end

         sudo lsmod | grep bcm2835_wdt
         bcm2835_wdt             4133  1

   13. I would recommend to now reboot the Rpi and after it's rebooted, log in and repeat
       step #11 to ensure the watchdog is running again

   14. If you followed the email section, root should also receive an email that the Rpi was
       rebooted if the watchdog ever kicks in

   11/03/18 Notes for enabling on Raspbian Stretch purely via Systemd:
      - edit /etc/systemd/systemd.conf
        - change #RuntimeWatchdogSec= to RuntimeWatchdogSec=10
        - uncomment #ShutdownWatchdogSec=10min

   That’s all it took (I'd recommend to do a reboot to ensure it gets enabled every time).   
   I tested with the forkbomb mentioned in some of the on-line articles,

      # prevent swapping to the SD card!
      sudo systemctl stop dphys-swapfile.service

      #Root file system is still R/W but lets make it as clean as possible
      sync; sync; sync

      # start the bomb (this is a one line shell script designed to crash your Rpi)
      : (){ :|:& };:
      Shortly after starting the bomb, the system rebooted as desired.

16. Install the required tool-chains to be able to build Linux programs

To build some of the programs that are either not available in the Debian repositories
or to build newer verions, you need to install the compiler took chains.  Do that
now with:

   #Install the required programs and any of their dependencies
   sudo apt-get update
   sudo apt-get install build-essential
   sudo apt-get install autoconf
   sudo apt-get install libtool
   sudo apt-get install checkinstall
   sudo apt-get install 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 overlflow to /tmp happens without having a large enough
secondary mount, 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 can
actually permanently damage the SD card.  Why?  SD cards are generally intended for writing 
data a few times but READ many times.  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 Stretch Lite will 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, would focus 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, you'll need to then 
     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 more suited (but still not great) for more writes.  The reason for this is they have 
     something called "wear leveling" to distribute the writes throughout the flash cells on 
     it's media.  Not all flash pendrives are equal in terms of compatibility, performance, 
     reliability, etc.  but arguably Linux is very forgiving here and most will work fine.  I 
     would use nothing smaller than a 8GB pendrive.

   - RECOMMENDED: Use an external USB hard disk drive (HDD) or Solid State drive (SDD).  These 
     devices are designed for handling lots of writes.  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.  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.  NOT a FAT16, FAT32, ExFAT, etc file system.  It's out of the scope
      of this document how to do this but feel free to email me if you need help.

   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 boots in the future, these steps are required to be 
      re-applied 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 a drive via a script.  You can choose to download and
modify this script which supports syntax differences for Raspbian Wheezy vs Jessie/Stretch
as well as both simple primary partition schemes and LVM enabled partitioning.  You *will*
need to change it to meet your needs:

   cd /tmp
   chmod 700
   sudo chown root
   sudo mv /tmp/ /usr/local/sbin
   Attach the USB HD
   sudo /usr/local/sbin/

  # Essentially, this script above mount a partition onto /tmp and creates some symlinks to
  #   /usr/src/archive for a build area
  #   Attach the USB HD
  #   mount /dev/mapper/vg_dranchlt3-lv_home /mnt/lvm/root/home/ 
  #   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

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 to a local file system to the system be it the SD card                            |
  |                (NOT RECOMMENDED) or attach a USB HDD or SDD (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 client programs
sudo apt-get install nfs-common

#This is required for mounting remote legacy NFS machines - the error seen is:
#   mount.nfs: rpc.statd is not running but is required for remote locking.
update-rc.d -f rpcbind enable
service rpcbind start

#Update the remote NFS server's /etc/exports file and run "exportfs -avr" on it

#On the local machine, edit the /etc/default/nfs-common file and change the line to:

# Create the mounting script - change it to suit your environment
#   NOTE:   This script is specific to my environment -Please edit to suit your 
#           environment

# /usr/local/sbin/

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

There is a script to do this if you wish to review and modify to suite your needs

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

18. Build VE7FET AX.25 packages from git

Why use the VE7FET AX.25 packages and not the official AX.25 packages? This is fully documented here:

But... (there's always a "but")... things have been changing a big.  Back in late August 2019, there 
had been some very distruptive changes coming in from the Debian Stretch and Debian Buster 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 beleive things should be ok now.


Anyway, assuming you've setup some scratch compile space and /tmp overflow, let's 
get started in building out the AX.25 packet system:

   #If you didn't already create this via the
   sudo mkdir -p /usr/src/archive
   sudo chown $USER /usr/src/archive
   mkdir -p /usr/src/archive/Rpi2-scratch/
   #Use the new directory
   cd /usr/src/archive/Rpi2-scratch/

18.a  Install libax25:

#Download the current VE7FET sources for AX.25.  If you want to know why these
# sources vs the official AX.25 sources, see:
git clone
cd linuxax25/libax25/

Next, we need to install the Zlib and zlib-dev libraries as programs in this package requires it

   sudo apt-get install zlib1g zlib1g-dev

#This command can seemingly look hung for 20 seconds before it starts to show output
autoreconf --install

#       If you received an error above about "autoreconf", you probably skipped 
#       ahead and DIDN'T follow "Section 16 Install the required tool-chains to be 
#       able to build Linux programs".  Go back and do that first!

#Assuming the above comment worked after say 30 seconds, do..

#Now configure the package 
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var

#Build it
make -j8

#Run a work around trick for a checkinstall bug which incorrectly reads RPM spec files
mv libax25.spec libax25.spec.old

#Temporarily work around a known GLIBC conflict
#   Do NOT do this on Debian Buster or the configure stage will FAIL
sudo mv /usr/include/netax25/ax25.h /usr/include/netax25/ax25.h.old

#Determine what version of libax25 you have
grep " VERSION" config.h

Now run the checkinstall program but subsitute in the correct version if required
and package things up:

   sudo checkinstall --pkgname libax25 --pkgversion 1.1.2 --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:
This library is used for applications that use the ax25 protocol. Included are routines to 
do ax25 address parsing, common ax25 application config file parsing, etc. This development 
library package includes some man pages and include files for compiling applications which 
use libax25

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 library is used for applications that use the ax25 protocol. Included are routines to ]
2 -  Name:    [ libax25 ]
3 -  Version: [ 1.1.2 ]
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 attempt to install the package

   | NOTE #1:                                                                   |
   |       If you notice that all kinds of strange of spaces are winding up     |
   |       in the output above, this means you didn't rename the .spec file     |
   |       as mentioned above!                                                  |

   | NOTE #2:                                                                   |
   |      The above commands should work with the newest VE7FET repo but if     |
   |      you're using either any combination of an older version of the VE7FET |
   |      repo, the "Official AX25" repo, or the very old inclued AX.25 Raspbian|
   |      packages, things WILL fail. To work around this, keep reading:        |
   |                                                                            |
   |      The above commands could FAIL at the "Installing Debian package" stage|
   |      due to a known conflict in that repo's  AX.25 source code.  Do email  |
   |      me if you see issues and I've reported previous issues directly to    |
   |      to VE7FET.  Until then, if you see a failure to install the packet,   |
   |      you can overwrite the conflicting file with the following command:    |
   |                                                                            |
   |         sudo dpkg --force-overwrite --install libax25_1.1.2-1_armhf.deb    |
   |                                                                            |
   | You can read more but this bug at:                                         |
   |                         |

   | NOTE #3:                                                                                                        |
   |                                                                                                                 |
   |      A long standing Glibc conflict issue described below has been FIXED in the Aug 2018 version of the         |
   |      VE7FET repo.  If you're using either an older version of the VE7FET repo, a version of the Official AX.25  |
   |      repo,  or the very old Raspbian repos, this work-around script will still be needed.                       |
   |      --                                                                                                         |
   |      As you upgrade your Raspberry Pi, it's important that you keep up on security and other bug fix updates.   |
   |      You will eventually need to install glibc/libc updates which unfortunately will break around the libax25   |
   |      package process similar to the NOTE above.  That 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, do the following:                                                                |
   |                                                                                                                 |
   |         #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 package you built and make it always available for the script to   |
   |         # find it.  My instructions recommend to build all those 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 to reflect your username                                                       |
   |            mkdir /home/dranch/libax25/                                                                          |
   |                                                                                                                 |
   |            # cd to wherever you built the VE7FET AX.25 packages and find the libax25 deb file                   |
   |            cd /usr/src/archive/Rpi2-scratch/linuxax25/libax25/                                                  |
   |            cp libax25_*_armhf.deb /home/dranch/libax25/                                                         |
   |                                                                                                                 |
   |         Finally, edit the script's "FET_LIBAX25_PATH" variable to point to the  |
   |         directory where the libax25 package is available.  For example:                                         |
   |                                                                                                                 |
   |            FET_LIBAX25_PATH="/home/dranch/libax25"                                                              |
   |                                                                                                                 |
   |      After that, simply run the update script:                                                                  |
   |                                                                                                                 |
   |         sudo /usr/local/sbin/                                                    |
   |                                                                                                                 |
   |      This which will download the required glibc/libc packages, force install them, and exit.  Once that's run, |
   |      you can again run:                                                                                         |
   |                                                                                                                 |
   |         sudo apt-get upgrade                                                                                    |
   |                                                                                                                 |
   |      and your machine will now download and install all the other packages  You should be good to go at that    |
   |      point!                                                                                                     |

   | CRITICAL NOTE #4:                                                               |
   |      With a recent toxic release of the AX.25 packages from Debian, it          |
   |      became 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 the built package on some other machine, use the 
#following command on that other machine once the package is copied over:

   sudo dpkg --install libax25_1.1.2-1_armhf.deb

18.b  Install ax25-apps:

This source was already downloaded via the previous git command for libax25.  To
compile this packet, we first need to install the Ncurses libraries as the "call" 
program requires it:

   sudo apt-get install libncurses5-dev libncursesw5-dev

Next, go into the source directory and start building:

   cd /usr/src/archive/Rpi2-scratch/linuxax25/ax25apps

   #This command can seemingly look hung for 20 seconds before it starts to show output
   autoreconf --install

   #Now configure the package 
   ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var

   #Build it
   make -j8

Now work around a checkinstall bug incorrectly reading RPM spec files:

   mv ax25apps.spec ax25apps.spec.old

   #work around a busted makefile
   sudo /bin/mkdir -p /var/ax25/ax25rtd

   #Determine what version of libax25 you have
   grep " VERSION" config.h

Now run the checkinstall program but subsitute in the correct version if required
and package things up:

   sudo checkinstall --pkgname ax25-apps --pkgversion 2.0.0 --pkgrelease 1 --pkggroup \
hamradio --pkgsource --maintainer \ --provides ax25 --requires libax25 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: [ 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 ]
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, this means you didn't rename the .spec file     |
   |       as mentioned above!                                                  |

After that, depending on the version of ax25-apps you're installing, try running the 
following commands to install the example config files if this is a fresh install of
this package.  This is package is currently doing things in a NON-standard way so hopefully
this will change in the future:

   # Copy over example config files into /etc/ax25:

      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 pacakges.
   # If you wish to stay with those versions, you need to run the command:
   #    sudo make installconf

   | 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_1.0.5-1_armhf.deb

   and then

      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  

The sources were for this final package were already downloaded via the previous git command 
so let's get started:

   cd /usr/src/archive/Rpi2-scratch/linuxax25/ax25tools

   #This command can seemingly look hung for 20 seconds before it starts to show output
   autoreconf --install

   #Now configure the package 
   ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --datadir=/usr/share --datarootdir=/usr/share

   #Build it
   make -j8

Now work around a checkinstall bug incorrectly reading RPM spec files:

   mv ax25tools.spec ax25tools.spec.old

#Determine what version of libax25 you have

   grep " VERSION" config.h

Now run the checkinstall program but subsitute in the correct version if required
and package things up:

   sudo checkinstall --pkgname ax25-tools --pkgversion 1.0.4 --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 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-tools ]
3 -  Version: [ 1.0.4 ]
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, this means you didn't rename the .spec file     |
   |       as mentioned above!                                                  |

   | NOTE #2:                                                                   |
   |      If you're running an older version of the VE7FET repo, you'll see     |
   |      various conflicts around man pages.  This below issue detailed below  |
   |      should be resolved in 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 ths conflict, I recommend to do a forced overwrite fo the    |
   |      conflicting files with the following command:                         |
   |                                                                            |
   |   sudo dpkg --force-overwrite --install ax25-tools_1.0.4-1_armhf.deb       |
   |                                                                            |
   | You can read more but this bug at:                                         |
   |                         |

After that, depending on the version of ax25-tools you're installing, try running the 
following commands to install the example config files if this is a fresh install of
this package.  This is package is currently doing things in a NON-standard way so hopefully
this will change in the future:

   # This means you'll now need to do the following:

      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 and
   # older VE7FET repo, an older Official AX25 repo, or the very old Raspbian pacakges.
   # If you wish to stay with those versions, run the command:
   #    sudo make installconf

   | 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.4-1_armhf.deb


      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

   | MANDATORY: Work around for a significant bug with AX.25 and Raspbian Stretch          |
   |                                                                                       |
   |    I have confirmed that with Raspian 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" but instead, you'll see something like           |
   |    "enxb827eb5f05".  How's that for catchy?  For known reasons to the AX.25 kernel    |
   |    maintainers, in the 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                                                   |
   |                                                                                       |
   |    Programs like beacon will fail to start.  Linpac will also 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:                                                |
   |                                                                                       |
   |       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                                                     |

19. Hardware vs. Software TNC

This document focuses on installing and using the Direwolf software TNC as this solution offers 
a cheaper yet superior solution for AX.25 packet decodes compared to almost any hardware TNC 
on the market (past and present) including:

   Kantronics KPC (version 2, 3, 3+, KAM, etc)
   MFJ 1270 / 1272 TNC2 TNCs
   PacComm TNCs
   Timewave / AEA PK96 TNCs)
   Kenwood D710, D72, and D74 TNCs
   TNC-X (a PIC microcontroller based TNC)
   TNC-PI (the same PIC microcontroller based TNC on a Raspberry Pi HAT board)

With that said, this documentation and scripts DOES support both the Coastal Chipworks TNC-Pi 
board via the GPIO header as well as the Kenwood D74 handheld via Bluetooth.  This suppport is 
either mentioned indirectly in this document's appendix and/or via the /etc/ax25/ 
packet bring up script.  No doubt, soldering up a TNC-Pi is a fun project and offers a reliable
packet TNC and doing Bluetooth on a D74 is sexy but regardless of each solution, Direwolf's 
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 D74, or other hardware
          TNC, there is NO reason to configure up a sound card, install the Direwolf, etc.
          As such, you can skip ahead to Chapter 25 to take it from there.  It's worth 
          mentioning that if you are looking for running an APRS setup and won't be running
          direwolf, you'll need to run a different APRS application.  A good alternative 
          is APRX and I have that documented in my HamPacket doc:


20. Setting up the Sound device
Ok, assuming you're going with the Direwolf software-TNC approach, you first need to get 
your soundcard setup tuned up.  The Raspberry Pi (v1/v2/v3,etc) boards do NOT support a
microphone or line-in so you MUST buy an external USB sound device.  Read the Direwolf
User Guide for other recommended devices but I recommend:

   Syba SD-CM-UAUD sound device which can be had for $7

It's is proven reliable and also doesn't spew RF noise on 144.000MHz!

   Tangent:  What am I talking about "noise on 144.000Mhz?  Take a hand help radio, QSY it's
             VFO to 144.000mhz  and walk around your home.  You'll probably find many strong 
             signals (birdies) as many devices and sound cards have a poorly shielded 12Mhz 
             crystal oscillators.  Why does that matter? The 12th harmonic of 12Mhz is 144MHz!
             Tangent over.

20.a Identify and test the soundcard

Anyway, to start, plug in your sound device directly into the Raspberru Pi (do NOT plug it 
into an attached USB hub {a known issue with Direwolf).  From here, let's now identify it:

   #First, install some Alsa utilities
   sudo apt-get install alsa-utils

   #To view all output capable sound devices:
   aplay -L | grep -A2 plughw

Look for all the devices that show with a "plughw" option.  My Syba USB sound device shows 
up as the following:  
    C-Media USB Audio Device, USB 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

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
  iProduct                1 C-Media USB Audio Device
        tSamFreq[ 0]        48000
        tSamFreq[ 1]        44100
        tSamFreq[ 0]        48000
        tSamFreq[ 1]        44100

Alternatively if you have a PCI-based card (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:

   arecord -D plughw:CARD=Device,DEV=0 -t wav -f S16_LE -r 48000 -d 10 /tmp/test.wav

If this works ok, you should see the output:

   Recording WAVE '/tmp/test.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono

and on the Syba sound devices, the green LED should slowly blink when recording and
go back to solid green when idle.

Next test, if you have speakers connected to the Rpi's speaker out jack, 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

   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

You can also play the file you just recorded with:

   aplay /tmp/test.wav

   #If you don't hear anything, audio might be routed to the HDMI port, change it 
   # to the analog jack
   amixer cset numid=3 1   #analog jack
   amixer cset numid=3 2   #HDMI jack

To play the same files through the Syba USB sound card (assuming you temporally 
connected speakers to the output jacks), do:

   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

Even better... record from the Syba and playback throug the Rpi's headphone jack
#   This method is VERY helpful for getting the initial audio levels
#  Don't forget the trailing "-" at the end of the command line (this is the STDOUT 
#   system)
arecord -D plughw:CARD=Device,DEV=0 -t wav -f S16_LE -r 48000 -d 10 - | \
aplay -Dplughw:CARD=Device,DEV=0 -

20.b Setting up the Sound Card levels for 1200BAUD AFSK Packet Radio

  - This example is using a Alinco DJ-580 HT with a simple PTT circuit similar to the 
    one shown here (more about this later):

The PTT connetion 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)
      Vol knob: 2.9 out of 10

20.c. Soundcard Mixer settings

The following levels 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 levels

With the HT turned on and the SQL/VOL knowbs set above, run the command:

   #We want to run this as root to set the main system levels
   sudo alsamixer

In this Ncurses interface, use the following keys

  - F6 to select right sound card - in my case for the Syba sound card: 
         C-Media USB Audio Device

  - F3 playback
      Set the "speaker" level at 19:19 and ensure is activated (that's shown as 00 
      in the bottom box of the vertical slider).  If it shows "MM", hit the "m" key

      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)   
      [need to understand if this should be on or off - use "m" to disable]

  - F4 Capture
      Set the "Capture" to a level of 31 and make sure you can see the word "Capture" by 
      using the space bar

  - F5 How All controls
      Some specific sound cards don't show their AGC controls in the "F3 - playback" 
      window so it's best to double check here

  - Hit the Escape key to exit and leave the current audio level settings in place

20.d. 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 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

           arecord -c 2 -d 15 -f cd -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 44100 Hz, Stereo

     b. Temporarily disconnect the packet radio from the USB soundcard's playback jack, 
        connect in a pair of headphones to the soundcard, and listen to the playback the silence 
        sound file:

           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 44100 Hz, Stereo

        Audio wise, you should hear the noise floor increase a little bit in the headphones

          NOTE:  08/29/17 : I'm hearing very pronounced TICKING on on the recordings both created 
                 on a Raspberry Pi and Centos box.  Inspecting the file in Audacity shows the ticks
                 so I think there is a bug in arecord here!   As a tempoary alternative, try using:

                    aplay -Dplughw:CARD=Device,DEV=0 /usr/share/sounds/alsa/Front_Center.wav

             - There should be zero 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.

20.e - Setting the right audio levels for packet

Now that you're familiar how to change the levels on the soundcard side, I recommend to
read and then re-read: 

especially 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 levels to be pretty close to perfect.  Remember, the adjusting these 
levels is a combination of the levels coming in/out of your radio as well as the soundcard 
levels coming out of the Raspberru Pi's soundcard.  You MUST adjust both sides to have and 
effective and functioning packet station.

Once you have the soundcard side tuned up, 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 your radio to your soundcard, it's CRITICAL that you check to 
see if:

   1) Your soundcard's microphone jack does or doesn't provides a "bias" voltage 
      for condenser-type microphones.
   2) Your radio's microphone jack does or doesn't provide a "bias" voltage for
      condenser-type microphones

On my chosen 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.  As such, it's CRITICAL that you insert a 10uF 
capacitor between the soundcard and your radio.  Any ceramic or electrolytic 
capacitor will work fine to isolate this DC voltage offset do but 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 
side, check the radio side as well and if it also provides an 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 important to note that some GPIO 
pins are pulled HIGH (+3.3v) by default:

   On the Raspberry Pi B+ and Rpi v2, these line initialize HIGH:
   GPIO 2, GPIO 3, GPIO 4, GPIO 7, GPIO8 and possibly GPIO 14 too

If you use one of these pins with the simple PTT transistor circuit mentioned above/below, 
you'll find that whenever your Rpi is rebooting or is powered yet off, it will leave 
your radio keyed up (PTT asserted)!  That's BAD!  So DON'T use one of those above 
GPIO pins!!

Ok, then what GPIO pins should you use?  Well, the Rpi1 and Rpi2 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*:

   Recommended Rpi pinout graphic

   Alternatively, here are some other URLs to check out:

     Raspberry Pi B+ and Raspberry Pi-2:

  The official documentation as well:

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 A+, B+, 2, and 4 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 pick
   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 v2 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 500ohm resistor to a GPIO pin to use it.  Its a very helpful indicator!

So I'm using the following different GPIO pins on my Rpi3 for various uses:

    Direwolf PTT on Rpi2:
      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 on Rpi2:
      Rpi pin 33 (Broadcom GPIO 13) :: connect to cathode of LED (short lead / smaller metal inside LED)
      Rpi pin 34 - GND              :: connect to anode of LED (long lead / larger metal inside LED)

      Rpi pin 18 (Broadcom GPIO 24) :: connect to 10k resistor, then one side of a momentary switch
      Rpi pin 20 - GND              :: Connect to other side of momentary switch

   | 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

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), you run the very real risk of damaging your USB sound card *and* the radio    |
   | itself!                                                                               |

Other options:

   - Use the Easy Digi isolation kit which includes an opto-isolator for PTT but also includes
     audio isolation transformers as well.  This works well for 1200bps AFSK packet but it
     will NOT work for say 9600bps FSK packet (and faster) as those 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

   - A slick solution is to get a nice PCB version of WB2OSZ's circuit 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!

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 the "RX power saver" as well as the
     Automatic power off features of the radio.  If you don't do 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 storage is mounted per the previous document section, lets compile 
up the newest version of Direwolf.

  a. Let's install the required dependencies to build Direwolf 

     sudo apt-get install libasound2-dev unzip

     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-get install gpsd libgps-dev

     | IMPORTANT:                                                                                 |
     |                                                                                            |
     |      If you disabled IPv6 on your system per the section above, you might run into an      |
     |      error installing gpsd and this is a known bug per:                                    |
     |                                                                                            |
     |                          |
     |                                                                                            |
     |      To work arounds this, do the following (per the bug report):                          |
     |                                                                                            |
     |         remove the line "ListenStream=[::1]:2947" from the /lib/systemd/system/gpsd.socket |
     |         file with:                                                                         |
     |                                                                                            |
     |            sudo vi /lib/systemd/system/gpsd.socket                                         |
     |                                                                                            |
     |         then run to retry the package config:                                              |
     |                                                                                            |
     |            sudo apt-get -f install                                                         |

  b.  Enter the compiling area and make it writable by users in the "adm" group

         cd /usr/src/archive/Rpi2-scratch/
         mkdir direwolf
         cd direwolf

  c. Get a copy of the Direwolf sources
     The current Direwolf release version is v1.5 as of 10/08/18 - size is 16.87MB including 
     all documentation).  If there are newer versions of Direwolf at: 

      I would encourage you to use the newer version.

      NOTE:  Sometimes Direwolf make distruptive changes from one version or another.  This 
             documentation has been tested with v1.5 only

     Get the newest code:


  d. Uncompress it and go into the directory

      cd direwolf-1.5

      #If using an existing source directory, make sure it's clean
      make clean

  e. Download and apply KI6ZHD's Makefile.linux patch which fixes a few path and install issues

       patch -p0 < direwolf-1.5release-makefile.patch

  f. Prep the sources and compile Direwolf

       make -f Makefile.linux tocalls-symbols

       #Pre-compile the sources using all four cores on your RPi - If you have an Rpi v0 or v1, use "-j2"
       make -f Makefile.linux -j8

  g. Package and install Direwolf

   g.1.  If you already had a /etc/ax25/direwolf.conf file installed, lets make a backup of it just in case.
         If not, you can just skip this section
            sudo mkdir /etc/ax25/Old
            sudo cp /etc/ax25/direwolf.conf /etc/ax25/Old/direwolf.conf-`date +%m%d%y`

   g.2  Since you're compiling Direwolf for Raspbian (Debian), don't let the older RPM spec file support in
        the checkinstall program fake things out.  (This is a work around for a known bug in the checkinstall 
        program).  This step might not be required if Direwolf doesn't include a .spec file:

           rm direwolf.spec

   g.3  I recommend to use the checkinstall program to package up Direwolf and install it.  It's not perfect
        though and needs a little help before we use it.  Run the following commands:

             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

   g.4  Checking the libgps version

        NOTE:  Be sure to update the version number in the command below to match the version you're 

        NOTE#2: The "Stretch" version of Raspbian names it's libgps library "libgps22" (the version number is 
                in the base package name for some reason.  The "Jessie" version of Raspbian names it's package
                "libgps21" which reflects an older version and because of this difference, the resulting Direwolf
                package built for one OS version is not usable for the other OS version. You can run the command:

                    dpkg -l | grep libgps

               to see what version is installed on your Rpi.  
               to match.  

   g.5  Let's package up and install the new Direwolf:

        Ok, run the following command:

           NOTE:  If on Wheezy, make sure you change "libgps22" with "libgps21" in this command

sudo checkinstall --pkgname direwolf --pkgversion 1.5 --pkgrelease 1 --pkggroup \
hamradio --pkgsource --maintainer \ --provides "tnc" --requires libasound2,libgps22 \
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

          Description for the package: 
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,libgps22 ]
   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

NOTE #1:  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.  While it's not techncially required, I say you should have followed the 
          previous section on creating a temporary /tmp mount point using a local USB hard disk 
          drive (HDD), SSD drive, or even a USB pendrive.  An NFS mount works for Direwolf too 
          if you know how to do that too.   

          If you cannot setup an external mount, you can try increasing the running Raspian 
          "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:

             sudo umount /tmp
             sudo mount -t tmpfs -o size=104857600,mode=1777 overflow /tmp

          Please remember that on a Raspberry Pi 2 or newer, you only have 1GB of RAM available.  
          Raspberry Pi v1A only have 256MB and v1B only have 512MB.  I do NOT recommend to increase
          the /tmp file ssytem go over 50% of that available memory and ONLY do so only temporarily.

NOTE #2   In the final field check of the checkinstall program, if you see fields like "1%{?dist}" 
          filled in for the "Release" field, this incorrect text is coming from the direwolf.spec 
          RPM file.  This is why these instructions told you to delete that file.  You can manually
          change this field now in the checkinstall program by just entering the "1" key or just
          cancel out of checkinstall program, remove the spec file and re-run the checkinstall
          promgram again

NOTE #3:  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

   g.6  (OPTIONAL) Install the new Direwolf config file:

        If this is a new Direwolf install and you want a base direwolf.conf file, you need
        to run another command as the file is not packaged in with checkinstall.  Run the
        following to install a an exmaple direwolf.conf file:

           sudo make install-conf

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/Rpi2-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.

Now that you've been able to create a debian package of Direwolf, you can copy this .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)
   - Running the same OS version of Raspbian (Wheezy, Jessie, Stretch)
   - You've also installed all the other required packages

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/

  NOTE#2: 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.

  #To do the install on to other Rpis once the .deb package is copied over to them:

     sudo dpkg --install direwolf_1.5-1_armhf.deb
     sudo cp direwolf.conf /etc/ax25/

24.a. 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 ALSA sound device for your 
      computer.  Please note that this is an ALSA device.. not PulseAudio or PortAudio but 
      the lower level ALSA device name and syntax.  This reflects my Syba USB device:

      sudo vi /etc/ax25/direwolf.conf
            # ADEVICE  plughw:1,0
              ADEVICE  plughw:1,0

      change the 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 
      signally line 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 pretty conservative (most radios are like 100-150ms).  
      You ideally want these values to be as fast as possible.

                 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" command
              on a remote KPC3 TNC.  I had to change the TXTAIL variable from 10 to 
              50 to get things to work properly!

              Please see 
              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 standard packet centric error prediction:

        - The first parameters of 1 or 2 is the number of bits Direwolf will try to 
        - the second parameter of AX25 essentially disables the APRS-centric hinting 
          which is useful if you're a classic packet user and not an APRS user
            FIX_BITS 1 AX25


     GPS locations beacon for using on APRS:

     It's a good idea that your packet system beacons it's presence on the frequency.
     If your station is NOT expected to move very much, I encourage you to:

       a. Configure a static location vs using GPS coordinates.  Why? Avoid GPS noise which 
          might shift your location around from position to position.  

          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) 

               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
           PBEACON delay=00:15 every=60 SYMBOL=/- lat=37^20.36N lon=121^59.59W power=4 height=20 gain=6 comment="Santa Clara, 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 APRS Igate for 
          general packets but APRS-IS to RF enabled transmit Igate 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 this setting assumes your Raspberry Pi has Internet access.  If it doesn't have Internet access,
                 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 accurate), things either won't work at all or you'll get data from APRS-IS
                 that isn't appropreate 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 the author if you can't figure out how to generate the APRS passcode
          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 equivlent 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.b. 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
      sudo direwolf -t 0 -d o -a 100 -c /etc/ax25/direwolf.conf

    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]   ___||||||

    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 1k 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 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.c. Testing APRS-IS filters with TELNET

Interactive APRS-IS filter testing over the Internet:  

   Configuring and tuning appropreate APRS-IS filters to ensure 
   you're not gating too much data, not congesting the local APRS RF frequency, etc. is NOT
   trival and 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 thet Linux "telnet" 
   program.  For example, if you wanted to test receive APRS-IS APRS messages within 5km of your
   location, you'd run the following commands.  You must subsitute 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 we 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 within 
Direwolf but it does allow you to perform advanced packet functions as well as play with
classic AX.25 packet:

   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

      - the next field is the Data Terminal Equipment (DTE) speed which is the speed between
        the computer and the TNC.  This is is generally going to be FASTER than your Data 
        Communications Equipment (DCE) speed like 1200bps packet.  I would recommend to leave
        this at "19200" which means 19200bps

      - the next field is the PACLEN or 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 max PACLEN you can use is 236

      - the next field is the WINDOW field which is related to the PACLEN field.  This value 
        controlls the number of packets your station can send until it waits for an acknoledgement
        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 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.

      - the last field is a comment field.  You can put anything in here that helps identify 
        this AX.25 device

      The final 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. Add packages that are dependent for these scripts

      #Need killall
      apt-get install psmisc
      #Need ifconfig
      apt-get install 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

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:
   -- starting up

   Wed Aug 30 21:27:27 PDT 2017
   axudp port not enabled in /etc/ax25/axports.. skipping
   TNC Type: direwolf
   Restoring audio levels on soundcard
   Starting direwolf
   Installing one KISS connection on PTY port /tmp/kisstnc
   PTS0 device: /dev/pts/3
   Setting kissparms (changes only shown in /var/log/packet.log)
   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

   ax25-up.new2 starting up

   beacon started

   mheardd Started

   ax25-up.new2 done

You can also see more details by looking in the /var/log/packet.log

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 - 31354
   Ending mheardd - 31357
   Ending listen - 31343
   Stopping Kissattach
   spattach: no process found
   Detach Ax/Nr/Sp Devices
   ls: cannot access '/proc/sys/net/ax25': No such file or directory
   Stopping mkiss
   Stopping Direwolf
   Ax25 Stopped

26.a. Linux AX.25 stack testing:

Grab another radio and put it on the same frequency as your Direwolf packet radio frequency 
and do the following:

   a. On the monitoring HT, key up the radio and call out your callsign to make
      things legal

   b. Manually push the PTT button on your Direwolf radio and listen to the empty
      FM modulation.  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, do this test now.  If there is any issues with your
      transmitted signal, you need to mitigate that with better cabling, cable routing,
      RFI toroids, etc. or 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-"

      You'll hear static all the time which is normal but this also temporarily disables any 
      RX power saving settings on your HT.   The heard packet should have an audio level that
      should be clear, have no clipping or other distortion, have no background noise, whine, 
      or clicking sounds and be completely undistorted.
      How did that signal sound?  Clean?  Not distorted?  I recommend to read this 
      excellent URL on how to tune your TNC's transmission levels to ensure you have a 
      good signal (recommended above as well):

   d. Next, try making a fictious AX.25 connected session:

         call vhfdrop n0call

      You should see the following text in the terminal window:
         GW4PTS AX.25 Connect v1.11

      Type in control-c to exit.  If you instead see "call: no AX.25 port data configured", 
      you have probably made a mistake in the /etc/ax25/axports file.  Make sure that your 
      "vhfdrop" line is the VERY last line in the file and all preceeding 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 radio to that frequency
      and issue the command:

         sudo listen -arp vhfdrop

      You should then 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}

27. Enable log rotation for 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 files are present, the logrotate system will automatically
       start using them the next time the cron system runs logrotate

28. Install Linpac for Connected and UnConnected packet QSOs and PBBS

   OPTIONAL for APRS users:  

   Linpac is a classic packet program for Linux that runs in a terminal window 
   which is similar to the Pakkratt or PKGold programs for DOS.  It supports
   multiple simultaenous 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:

   | Signifincant issue with AX.25 and Raspbian Stretch                                    |
   |                                                                                       |
   |    I have confirmed that with Raspian 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, Rasbian 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 Linpac 0.25 (RECOMMENDED) or apply the  |
      |   patch in the URL above.                                                             |

      #NOTE #2:  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. 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
   be complete

     | 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 but you shouldn't |
     |     get your hopes up with this functionality with Linpac today.                              |

   - You can either install pre-built binaries from the Raspbian repositories (NOT recommended) 
     by doing:

         #Make sure you get the Linpac 0.25 version or newer
         sudo apt-get update
         sudo apt-get install linpac ax25mail-utils

     Or you can build Linpac from sources (this is the RECOMMENDED approach).  Below are the needed 
     steps on how to build the newest version of 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.

RECOMMENDED: Building Linpac and ax25mail-utils from sources:

   Assuming a USB HD is mounted per the previous section...

   Get the newest ax25mail-utils sources  - 0.13 is current  as of 9/2/17

      cd /usr/src/archive/Rpi2-scratch
      mkdir Ax25mail-utils
      cd Ax25mail-utils

   First, let's build and install the ax25mail-utils program

      tar xzvf ax25mail-utils-0.13.tar.gz
      cd ax25mail-utils-0.13
      ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var
      make -j8

   Now let's package and install it:

      sudo checkinstall --pkgname ax25mail-utils --pkgversion 0.13 --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 but if you manually 
   want to install it, use the following (configuration files aren't included in the 
   checkinstall based deb)

   sudo dpkg --install ax25mail-utils_0.13-1_armhf.deb

28b. Install Linpac

Ok, now let's now move on and configure Linpac

   #RECOMMENDED - gets the newest available code
   Get the newest pre-release version of Linpac - 0.26 is current as of 02/10/19:

      cd /usr/src/archive/Rpi2-scratch/Linpac
      cd Linpac
      git clone linpac-linpac
      cd linpac-linpac
      git checkout develop
      autoreconf --install
      ./configure --prefix=/usr

   #LESS RECOMMENDED - This downloads the last release version which is quite old
     Get the newest RELEASE version of Linpac - 0.25 is current as of 12/10/17:

      cd /usr/src/archive/Rpi2-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

        If you are trying to build Linpac 0.24 or older for Raspbian (please use 0.25 if 
        possible), you MUST download and apply a patch from Martin Cooper KD6YAM for recently 
        exposed POSIX issues:

           patch -p1 < segfault-patch.diff

Now let's compile / install Linpac:

   #build it - takes about 31 seconds on a Rpi3
   make -j8

  NOTE:  There seems to be some strange bugs with Linpac's installer on Debian Stretch/ Jessie where it's 
          not creating the correct directories for the first time 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

   Now let's package and install Linpac - Be sure to update the version number learned above in the command

      sudo checkinstall --pkgname linpac --pkgversion 0.26 --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: 
Linpac is a modular console-oriented packet radio terminal for Linux with a built-in messaging client.  
Using Linux's native AX.25 network stack, it can support eight concurrent connected sessions (QSOs) 
as well as send UNPROTO packets (UI) to any pre-configured ax25 digi path.

   Validate the output:
   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.26 ]
   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,libncurses5 ]
   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 Debian apt version of Linpac <=     |
   |      toxic.  To protect your system from having Apt overwriting your custom |
   |      compiled version of the Linpac package, run the following command:     |
   |                                                                             |
   |         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.                                                              |

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 know first in configuring Linpac:

   If you want the built-in AX.25 traffic montitor, you either :

     a. need to run Linpac as root  (what we are doing in this doc for now)

     b. make the ax.25 listen program ( /usr/bin/listen ) SUID root

     c. setup and configure the "ax25spyd" program as a proxy (not documented here)

Anyway, let's focus on Linpac for now:

   1. Make sure you have root permissions via running the command as the setup wizard
      has issues with being run with sudo:

         sudo su

   2. Now start Linpac by running the command 

   3. When prompted for your callsign, enter in your callsign without any trailing 
      SSID.   We'll come back to this in a bit.

   4. When prompted for your home BBS callsign, you need to enter in a valid or valid-looking 
      BBS address.  It should be noted that this is only used when the ax25mail-utils package 
      is installed.  If it's not installed, this section of Linpac won't function but it won't 
      error out either.  It should also be noted that Linpac and the message relay system ONLY 
      supports F6FBB BBS type systems today.  It doesn't understand the prompts of other alternative
      BBSes like JNOS, KPC3 PBBS, etc.  

      For this example, I'm using "N0ARY-1" which 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:

   5. When prompted for "name of port to connect to" (used to connect to your real or ficitious BBS), 
      you need to specify your AX.25 port configured in /etc/ax25/axports.  For this example, I am 
      using "vhfdrop"

   6. When prompted for "the digipeaters used to connect", I just hit enter to mean NO digipeaters
      as I can hear my local BBS directly

   7. When prompted for "Enter the full hierarchical address", put in the correct address.
      For my example, I'm using "#NCA.CA.USA.NOAM" for my geo-centric location.  See the above
      URL for more details and understanding of other geo-centric addresses.

   8. At this point, a set of configurations will go into /root/LinPac/ and Linpac 
      will automatically start up!

   9. Unfortunately, we're not quite ready to use Linpac just yet so let's exit Linpac by typing in:


      (yes, you need to include the colon).  After exiting, we need to continue to configure Linpac

  10. Now edit /root/Linpac/macro/init.mac and find the lines that start with:

         sudo vi /root/LinPac/macro/init.mac
         mycall@1 KI6ZHD

      In this example, I ONLY only want to associate the KI6ZHD-6 callsign and SSID
      to the F1 and F2 keyboard keys (by default, it has F1-F8 associating).  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 radio frequency you intend to operate on, 
      there can be different SSID schemes in use.  There are only defacto standards here and they
      can 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 going to be operating your station on an APRS frequency, make sure that Linpac 
           isn't using one of the primary APRS SSIDs.  That APRS SSID would most likely configred 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 packet use, the SSIDs can differ from region to region.  In Northern California, 
           we've standardized on:

              -0 :: (aka.. no SSID) keyboard to keyboard chat
              -1 :: PBBS mailboxes
              -2 :: not specifically used
              -3 :: not specifically used
              -4 :: not specifically used
              -5 :: for nodes and netrom 
              -6 :: not specifically used
              -7 :: for nodes and netrom (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 and work it's way down to 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:

           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.

         sudo vi /root/LinPac/macro/init.mac
         statline 15
         chnline 30
         infoline 5
         NOTE:  When you start Linpac say from within Screen as shown later in this document and 
                it's looks all squashed up and see an error in Linpac saying "invalid value", it's
                talking about these various line counts.  Try reducing some of the line sizes here
                for say "chnlin" to a smaller number

       You can find more advanced Linpac configuration tips at:

   13. Finally, I recommend to start Linpac via the included shell script found in 
       /usr/share/linpac/contrib/ .  If you want to use this 
       script, you'll also need to do two things:

          a. install screen with:
             sudo apt-get install screen

          2. As the root used, edit the script /usr/share/linpac/contrib/
             and change the line that reads:
                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 by running the command:

   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 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. If you want to auto-start some of the additional packet services including Linpac, 
      first edit the /etc/ax25/ file and at the bottom of the script, remove the #ed out 
      line that will run the /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

      Next, 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
         #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

         #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  "

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 slowly blinking
   - 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. Configure your Rpi to support BOTH being an Access Point and Wifi client (managed mode)

Configuring a Raspberry Pi 3/0w to act as either a standard Wifi client to connect to an existing Wifi
AP or act as a full Access Point is pretty strait forward.  This section will tell you how the Rpi3 or
Rpi ZeroW can do BOTH SIMULTANEOUSLY.   The Wif range is pretty decent considering that the Rpi3 only 
has a very small chip antenna.  If you want better range, consider doing a hardware modification to add 
a u.fl connector and an external wifi antenna (mentioned below - not possible on the Rpi 3B+):

   NOTE: Previous doc versions focused on working with an RTL8192CUS based Wifi device but no longer


         The above work is now mostly unneeded now as the Raspberry Pi 3 and Rpi Zero W 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 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, this new SBC hardware supports built-in 802.11N 
Wifi and Bluetooth 4.1.  This Wifi hardware support is limited to the 802.11 2.4Ghz band and there 
isn't any 5.8Ghz support nor 802.11A or AC link support.  The only downsides to this built-in wireless 
support in my opinion is:

   - The stock antenna is a decent  "chip antenna" which means your wifi distance 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 3B+ 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, etc

Anyway, for now, let's move forward with first enabling the Rpiv3 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     If you're using Wifi on your Rpi today being it's primary Internet connection, 
       or *be* 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 simplier 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-get update

   #Accept all additional package dependencies
   sudo apt-get 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

Non-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

Temporaryily testing the wifi setup
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 forground 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 resolf.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 minimim 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.b Testing the Wifi system out

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 commnands 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 sytem
      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 RPIv3
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.a 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 connectng 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-donlgle 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 tself, 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 arent 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 arent 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 workound script
   /usr/local/sbin/ &

Assuming you setup the Iptables firewall per this documeent, 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)     |
|   oredit 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 Rasbpian 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-get update
   sudo apt-get 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

apt-get 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

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 by running:

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

     Now try running it:
        Current CPU speed governor: (valid is 'powersave', 'ondemand'):

        Current CPU frequency:

        Max allowed frequency

        SOC Temp (in Celius) - 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 add 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 options with the current firmware (changes over time)
   cat /sys/class/leds/led0/trigger

   * Anything 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.

32.c - Setting up Bluetooth on the Rpi for pairing BT keyboards
Assuming you didn't disable the bluetooth support on your Rpiv3 via the raspi-config
program, here is an example to associate to a BT keyboard to interact with the Rpi 
while viewing the display via the HDMI port.

   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.  You might see many        |
   | disassociations and reassociations on the Wifi and/or Bluetooth side when   |
   | either system is busy.  It sounds like this could be limitations on the     |
   | Raspberry Pi hardware.  Maybe this 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:AA:AA:91  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 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 
      # commandline tool looking like:
      #    [NEW] Device 24:71:89:96:de:AB TH-D74
      # This output MUST showup 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 bluetoothcyl 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 permanetly with 
      trust 24:71:89:96:DE:AB

      # You should see the trust acknowledgement 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 Compatibilty mode

     # Now tell Systemd to recognize the modified configration 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 porti (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 windowa 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 lightup 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:


   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. Configure a USB-based GPS receiver with GPSD for position, date and time

By adding a GPS to your Raspberry Pi, not only can you use the location for say being 
an APRS client but also get ultra-reliable date and time!  

  | 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 and      |
  |     that could take like ten minutes.  Compare that to my smartphone which      |
  |     could get full lock within 60 seconds.  I'm currently having decent         |
  |     luck with the following $26 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 it makes things easy.  Let's keep going.

Now install the required GPS software:

   sudo apt-get update

   #Unfortunately, you must install all the additional package dependencies here 
   # (something like +30 packages are require)
   sudo apt-get install gpsd gpsd-clients libgps-dev

We now need to configure gpsd to use the new device.  The easist 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

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 SystemD.. NOT)
    ps aux | grep gpsd
    sudo lsof -nPi | grep 2947

       #If you see that the socket is still listneing, 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 line:

          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:

   # -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 ther is the "Sats used" lines.  If they show up, you should be good!
Other information lines will display and continue to come but but gpsd is successfully running.  

   It's important to know that this command will not start spewing out NMEA sentences.  

The key items in my setup to look for is:

   1. device <serial-by-id> activated

   2. startup at <timestamp>

   3. identified as type SiRF

Go ahead and hit control-c to stop this manual gpsd process.  

For test #2 - put the GPS into NEMA mode and display 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

   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) : position is found and not moving wildly
         Time           : Date and time is accurate for the UTC timezone
         Fix            : You have at least 3 more more satellites locked onto

      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

NOTE on poor GPS receivers:

       In the above display, make sure the DATE is correct.  As mentioned at the top of this section,
       a previous USB-based GPS receiver 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 setup from being inside my house
       to outside with a WIDE, clear view of the sky, it would fix itself and report the right things.
       This essentially proved that this cheap USB receiver wasn't very sensitive at all!

       As a work around to this busted time/date, you can do the following (or just get a better GPS

          sudo fake-hwclock save
          systemctl enable fake-hwclock

       This should 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 setup 
       from inside my home to outside with a clear view of the sky.  

If all the above test steps work, edit the /etc/default/gpsd file, find the line that says
"DEVICES="" and update it to reflect your proper device-by-id serial port.  In my case:

   # NOTE: 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).

   sudo vim /etc/default/gpsd

Now try to start the 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 command:

   ps aux | grep gps

   Which you should see something like:
   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 shows that the gpsd process is running.  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


      - This program offers a slightly simplier, cleaner view to the number of satellites being used 
        in the left-side box under the "Used" column


      If you're running Raspbian Pixel 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: 

34. Adding NTP 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.  This means, when they boot, their date and time will always be WRONG.  
It's key to get that 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 protoco) 
be it from the Internet or more interestingly from a GPS data feed!

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-get 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:
     17 Oct 12:36:04 ntpdate[19961]: step time server offset 0.001824 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, 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

#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:

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. Make a backup of your MicroSD card

This section will let you make complete image backups of you Raspberry Pi SD card to 
a heavily compressed file on another computer.  If you ever accidently delete a file,
a directory, or have your SD card get corrupted, you can restore from this image!

  a. Shutdown the Rpi with:

       /sbin/shutdown -h now

  b. Unplug the power cord from the Rpi

  c. Eject the MicroSD card from the Rpi and install it into a different 
     Linux machine's card reader while that machine is fully booted

  d. run the "dmesg" command on that Linux computer to confirm SD card device as being seen
     and to also identify what SD card reader's device name is.  For my machine, I see it 
     as device: /dev/mmcblk0

  e. 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.

     e.1. Install the xz compression utility

          #These commands assume the other Linux computer is running a Debian-like OS
          sudo apt-get install xz

     e.2  Identify the REAL size of the SD card

              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

     3.e. Mount the SD card with:

          sudo mkdir -p /media/sd-card/p1
          sudo mkdir -p /media/sd-card/p2
          sudo mount /dev/mmcblk0p1 /media/sd-card/p1
          sudo mount /dev/mmcblk0p2 /media/sd-card/p2

     e.4. Clear out all unallocated space in the file system for max compression

          #Fill up and clear out the "boot" partition - this will be fast (7 seconds)
          sudo time dd if=/dev/zero of=/media/sd-card/p1/bigfile.dd bs=1M
          sudo rm -f /media/sd-card/p1/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/sd-card/p2/bigfile.dd bs=1M
          sudo rm -f /media/sd-card/p2/bigfile.dd

     e.5. Unmount the card partitions

          sudo umount /media/sd-card/p1/
          sudo umount /media/sd-card/p2/

  f. Create a binary image of the SD card with the "dd" tool:

        # Go ahead and change the filename from "ki6zhd-jessie-w-linpac.dd.gz" to 
        #   reflect your callsign, Raspbian versio, and anything else you want

        cd <a directory you place your backup stuff in>
        sudo time dd if=/dev/mmcblk0 bs=1M | xz -9 > ki6zhd-16gb-stretch-w-linpac-090417.dd.xz

     NOTE: This command will not give any output until the process is complete
           and it can take quite a while to do depending on the size of your SD card and
           the speed of your system.  A 16GB card took 51 minutes to copy and compress.

     NOTE2: 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!

  g. Ok, you have your backup!  Now remove the SD card from this secondary Linux machine and put 
     it back into your Raspberry Pi

  h. Power back up your Raspberry Pi and everything is as it was but now you have a backup

  i. If you'd like to put a copy of this newly created SD image onto another SD card

     i.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)

     i.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-jessie-w-linpac.dd.xz | dd of=/dev/mmcblk0 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

[Chapter Gap]

60. Optional projects to add to your Raspberry Pi / APRS / Packet Project

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 importnt 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-get 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.

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 ther ethough.

   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 conneted 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 dimentions 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
Building on the above section of getting an I2C-based LCD working, this section uses the same
I2C bus to communicate to a DS3231 real time clock to set the system's date/time upon power up.

   NOTE:  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 consier this:

          1. An DS3231 RTC consumes almost no power, is always running, and will give the 
             Raspberry Pi system the date/time upon initial boot for accurate logging ASAP.
             Using a GPS setup 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 DS3231 RTC unit I bought is this one:

   #Actually this URL buys THREE units for $7 including the batteries!

Assuming 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 gromets 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 boths 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 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 run the following command to see if the I2C display 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: -- -- -- -- -- -- -- --

As you can see here, the previosly mentioned LCD display has an I2C address of 0x3f,
the RTC's internal 32K EEPROM is at address 0x57, and the RTC shows up at address 0x68.
If you see a "UU" in the address spot where you expect your RTC address, this means
that address in use.   Maybe your Raspberry Pi distro already recognized it and has 
configured it.  To confirm that, try running:

   ls -la /dev/rtc0

If that comes back with something like the following, your system should be done:

   crw------- 1 root root 253, 0 Dec 31  1969 /dev/rtc0

also try running the command "dmesg | grep rtc" and if the output looks like this,
things are indeed already setup:

  [    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" like this 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 "registered ds1307" text, you'll need to update your /boot/config.txt
file as instructed below to gain access to some of it's advanced features like temperature 
sensors, etc.

If things didn't get setup automatically, your specific RTC board might be at different 
address.  You'll need to research what I2C addresses it will show up as.  If you don't see 
ANYTHING in the above i2cdetect output, make sure the I2C bus is turned on in the raspi-config 
tool, check your wiring from the Rpi to the RTC module, etc.

Assuming your RTC wasn't pre-configured (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 and NOT sudo to run the entire command as it's passing multiple parameters
   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.  Check the output of i2cdetect again.  If the command didn't 
give any errors, Linux should have loaded the DS1307 kernel module which also supports the 
DS3231 chip.  Confirm the 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

At this point, if you re-check the I2C bus, you'll now see the RTC device as being IN-USE
with a "UU" identifier:

   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: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- --
   70: -- -- -- -- -- -- -- --

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

Awesome.. it seems to work but it has the wrong date and time. That's ok as it's 
brand new and has never been programmed.  Assuming you Raspberry Pi has been configured
to be an NTP client per the previous chapter in this doc, setting the time 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 system I'm currently using
for time:

   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, let's update the DS3231 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
   sudo hwclock -r -f /dev/rtc0
   Mon 18 Feb 2019 03:23:22 PM PST  -0.247576 seconds

Great!  You've set the time on it!  Now if you're curious how accurate the RTC is 
compared to NTP over time, you can try running commands like this one at any time where
"hw-time" is the RTC and the "system-time" is the NTP set Raspberry Pi time.  Btw,
"ppm" is essentially errors in "Parts Per Million":

   sudo hwclock -c -f /dev/rtc0
   hw-time      system-time         freq-offset-ppm   tick
   1511382606   1511382605.521373
   1511382618   1511382617.521630                21      0
   1511382629   1511382628.522096                31      0
   1511382640   1511382639.521910                16      0

   Enter in control-c to exit the program

Now all you have to do is have the RTC system load up at boot time.  To do this, edit the 
/boot/config.txt file.  In that file, find the line that reads something like:


remove the # character and make it now read:


Next, you need to remove the stock Raspberry Pi "fake" hardware clock system with:

   sudo apt-get remove fake-hwclock

That should be it.  Go ahead and reboot your Raspberry Pi.  If things work correctly,
you should see the driver load up in the output of "dmesg" and when you run "date"
after SSHing into your Rpi, it should have the right date and time regardless if the 
Internet is up or not.

BONUS:  Temperature sensor!
The DS3221 RTC chip includes a highly accurate temperature sensor as it's ability to understand
the environment is how it keeps far better track of time than NON-temperature compensated
RTCs.  You can read the temperture off the DS3231 unit at any time by using this command:

   cat /sys/devices/platform/soc/3f804000.i2c/i2c-1/1-0068/hwmon/hwmon0/temp1_input

That's showing it's 23.250 degrees Celcius or 73.850 degrees Fahrenheit.  

If you get an error running this cat command, it's possible that one of two things happened:

  1. The sysctl address for your RTC is different.  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.  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:




If you had to change this, reboot your Raspberry Pi for the changes to go into effect.

[Chapter Gap]

70. Stuff that still needs to be updated from Wheezy to Stretch/Jessie


N7NIX Dan tracker

Need to integrate hampacket2:/usr/src/archive/RPi/n7nix-udrtracker-install.txt

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/  

# ---------------------------------------------------------------
# The Rpi's HW watchdog is disabled by default though the init script runs (stupid)

If you want to use the watchdog to keep your system up though it might be constantly
rebooting (and/or corrupting the SD card), edit the /etc/init.d/watchdog script

Add watchdog

# Maybe install Xastir - old though - currently at 2.0.4
  apt-get 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

[Chapter Gap]

80. Todo 

03/06/15 - Add NTP via GPS support -
11/21/15 - ULOG w/ firewall log rotate

90. Special Topics

90.a - Bringing up a Coastal Chipworks TNC-Pi on Raspbian Jessie

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 --> 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-get 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:

91 - Kernel Compiling the Raspbian 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 thermomoter) 
      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 heatsinks 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/Rpi2-scratch is present... ready to go!

   2. Move into the external drive

      cd /usr/src/archive/Rpi2-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-get install git bc

Get the Raspian 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
   comman (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 seperate 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

# 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 fomatting for the ax25 packges 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 minimial /etc/iptables/rules.v6
#            ruleset in the RPi direcory 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 Rasbian 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 Rasbpian (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 Rasbian Pixel vs Rasbian 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 browouts 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 thed 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 overwriten 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 debounding 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
#          - Philosphy 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 Internface 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 Raspian 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; spellcheck 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)