More about IOS Bluetooth radios not shutting off

Reading Time: 3 minutes

The other day I was writing about a method for Proximity Presence Detection using a Raspberry Pi and the Bluetooth radio in your smartphone.

(Basically, when your phone (or other Bluetooth device) gets within range of the Raspberry Pi’s Bluetooth, the MAC Address of the phone is noted and a script sends some data to an MQTT server, so you can determine with some confidence that you are home. It’s quick, lightweight and doesn’t require any software to be installed on the phone. Once the script notes your presence, you can do things such as turn on lights, have your home automation system greet you or do pretty much anything that computers can do.)

While setting it up, I noticed something odd, though–turning off Bluetooth didn’t really turn off Bluetooth, at least on my iPhone.

Here’s what I expected to see. The number in bold, right after “confidence” is the value that shows that the radio is active within range. When it disappears from range, the number tapers down over a period of 90 seconds or so:

{"confidence":"100","name":"J’s iPhone","scan_duration_ms":"1394","timestamp":"Sun Feb 03 2019 09:39:04 GMT-0500 (EST)"}
{"confidence":"83","name":"J’s iPhone","scan_duration_ms":"5150","timestamp":"Sun Feb 03 2019 09:39:47 GMT-0500 (EST)"}
{"confidence":"66","name":"J’s iPhone","scan_duration_ms":"5153","timestamp":"Sun Feb 03 2019 09:39:55 GMT-0500 (EST)"}
{"confidence":"50","name":"J’s iPhone","scan_duration_ms":"5148","timestamp":"Sun Feb 03 2019 09:40:04 GMT-0500 (EST)"}
{"confidence":"33","name":"J’s iPhone","scan_duration_ms":"5148","timestamp":"Sun Feb 03 2019 09:40:12 GMT-0500 (EST)"}
{"confidence":"16","name":"J’s iPhone","scan_duration_ms":"5149","timestamp":"Sun Feb 03 2019 09:40:20 GMT-0500 (EST)"}
{"confidence":"0","name":"J’s iPhone","scan_duration_ms":"5149","timestamp":"Sun Feb 03 2019 09:40:28 GMT-0500 (EST)"}

To test it, I tap the home button on my phone and swipe up, revealing the Control Center:

Oddly, when I clicked the Bluetooth icon, it dimmed, as you’d expect, but it was still appearing as 100% in my script:

{"confidence":"100","name":"J’s iPhone","scan_duration_ms":"1218","timestamp":"Sun Feb 03 2019 10:00:26 GMT-0500 (EST)"}
{"confidence":"100","name":"J’s iPhone","scan_duration_ms":"385","timestamp":"Sun Feb 03 2019 10:00:57 GMT-0500 (EST)"}
{"confidence":"100","name":"J’s iPhone","scan_duration_ms":"1197","timestamp":"Sun Feb 03 2019 10:01:28 GMT-0500 (EST)"}

My first suspicion was that my installation of the script was at fault or that perhaps I was reading the wrong MAC address, but I checked those and quickly started to suspect my phone.
To test this, I shut off my phone and saw the confidence percentage drop gracefully to zero.
I turned the phone back on and the script performed perfectly, detecting the radio instantly.

(“Airplane Mode,” I found, did actually turn off the radio, as you would expect.)

Next, I connected a Bluetooth speaker and started playing music, while watching my script. Hitting the Control Center icon disconnected the speaker, but didn’t shut off the radio.

This struck me as odd behavior, but not surprising, given that it’s Apple and I have little confidence in them to be upfront about something like this.

I dug around a bit this morning and came across an Apple support article titled “Use Bluetooth and Wi-Fi in Control Center with iOS 11 and later.” In that rather vaguely titled article, it says the following:

In iOS 11 and later, when you toggle the Wi-Fi or Bluetooth buttons in Control Center, your device immediately disconnects from Wi-Fi and Bluetooth accessories. Both Wi-Fi and Bluetooth will continue to be available, so you can use these important features:

Apple Pencil
Apple Watch
Continuity features, like Handoff and Instant Hotspot
Instant Hotspot
Location Services

Not in the list, but according to another source, Apple’s AirPod earphones apparently also do not disconnect when Bluetooth is deactivated from Control Center. (I have no AirPods to test this.)

Also worthy of note is that if you do it this way, it will automatically restore Bluetooth to full capacity the next day at 5:00 AM local time. Why it does this isn’t clear, but it’s probably so your Bluetooth alarm clock will still function or something.

If you go into IOS’s “Settings” app, you the Bluetooth controls behave as you would expect–turning off Bluetooth actually does shut off the radio, so I doubt this is anything beyond Apple making their own proprietary technologies and accessories work better than third-party stuff.

Anyway, I thought it was interesting enough to dig into a bit and share with you all.

The big takeaway is that using Control Center is not the same as controlling things via the Settings app and may not behave as expected.

Threat Level: Mostly Harmless ;-)

Learn Byobu while Listening to Mozart

Reading Time: < 1 minute

If you do much of anything using a Linux terminal, you really owe it to yourself to take a look at Byobu, which is, according to Wikipedia, “an enhancement for the GNU Screen terminal multiplexer or tmux used with the GNU/Linux computer operating system that can be used to provide on-screen notification or status, and tabbed multi-window management. It is intended to improve terminal sessions when users connect to remote servers.

This is one of the first things I install on any of my Linux boxes.

Watch the video for a bit–it’s a bit like watching a master chef slice and dice vegetables.

Proximity Presence Detection with the Raspberry Pi

Reading Time: 2 minutes

There’s some cool code I’ve been playing with the last few days. It uses the Raspberry Pi’s Bluetooth capabilities to determine when you come within range of the Pi with your smartphone. It’s called Presence and explains itself as “Reliable, Multi-User, Distributed BT Occupancy/Presence Detection.”

What it does is run a script as a service on the Pi and watches for a pre-defined list of MAC addresses to enter its Bluetooth radio’s range. It sends out statuses on that MAC address to an MQTT server running on the Pi or elsewhere. The messages each look something like this:

home/bedroom/E4:E4:ZZ:00:XX:XX {"confidence":"100","name":"Jim’s iPhone","scan_duration_ms":"806","timestamp":"Tue Jan 22 2019 13:20:50 GMT-0500 (EST)"}

The first part of that is the MQTT topic (with my MAC address obscured): home/bedroom/E4:E4:ZZ:00:XX:XX

Next is a bit of JSON that tells you the script’s “confidence” that the device is home, as well as the name of the device:
{"confidence":"100","name":"Jim’s iPhone"}

There are several things that make this strategy particularly cool.
The first is that once it’s in MQTT, you can use this piece of information in any number of ways, the most obvious one being a Home Automation system such as Home Assistant or Domoticz. It would be trivial to whip up a script with Python and its paho-mqttlibraries, for example.

Another reason is that it doesn’t require any special software to be running on the phone–the Bluetooth radio broadcasts everything you need by default.

What all this gives you is a way to detect when your phone (you) comes within about 30 feet of a Raspberry Pi or even the $10 Raspberry Pi Zero. This is ideal for, say, turning on some lights when you pull into the driveway, (but perhaps not for unlocking an automatic door.)
I’ve only tried it with my iPhone, but in theory, you could do this with any Bluetooth device. It should even work with something like a Tile, the key-finding gizmo, something that would be of great interest. (I just need to figure a way to retrieve the MAC address from the Tile.)

Neat stuff.
So far, I like this better than other solutions I’ve found for presence detection.

Finally, something unexpected:

When I was setting this up and testing it, I noticed something unusual. To turn off Bluetooth on my iPhone, I would open this panel and tap the Bluetooth icon:

The odd thing is that when I did that, the Presence software would still see the iPhone as being nearby. Tapping “Airplane Mode” would actually turn off the Bluetooth radio and the script would see it as gone.

This seems odd at best, nefarious at worst.

Managing DotFiles with a “bare” Repository

Reading Time: 5 minutes

Note: This is probably only of use to those using “Unix-like” systems such as OS X and Linux. It may or may not work on Windows, using Git Bash. Probably not useful on Windows, otherwise.

In this post, we’ll be covering a few things. First up is the concept of “dotfiles,” the configuration files you keep in your home directory that provide customization and configuration.

After that, we’ll take a look at some strategies for maintaining these configuration files using Git, the version control package that powers the Open Source movement.

Finally, we’ll be looking at so-called “bare” repositories as well as some clever tweaks that you’ll be able to apply not only to your dotfiles, but to anywhere you might want to leverage Git for files that may not live inside a traditional repository.

First up, the Dotfiles

On a Unix/Linux system, when you don’t want to see a file by default, you can hide it from view by starting its filename with a “dot,” or period character. This is a convenience, not a security measure–it’s a way of keeping your view of a directory relatively uncluttered.

For example, if I take a look at my home directory using ls, here’s what I see:

$ ls                                                               
AppData Documents Music Pictures Templates
bin Downloads node_modules projects Videos
Desktop ember-quickstart package-lock.json Public

But that’s not the complete list of files in that directory. There are a lot more, visible if you use the -a flag:

$ ls -a

drwxr-xr-x. 4 jim jim 4.0K Nov 9 14:00 .ansible
drwxr-xr-x. 3 jim jim 4.0K Jan 16 15:06 AppData
drwxrwxr-x. 6 jim jim 4.0K Dec 9 11:22 .atom
-rw-------. 1 jim jim 593 Nov 2 09:52 .bash_history
-rw-r--r--. 1 jim jim 18 Oct 8 09:41 .bash_logout
-rw-r--r--. 1 jim jim 141 Oct 8 09:41 .bash_profile
-rw-r--r--. 1 jim jim 389 Nov 2 00:21 .bashrc
drwxr-xr-x. 3 jim jim 4.0K Jan 6 15:06 bin
drwxrwxr-x. 3 jim jim 4.0K Jan 12 11:33 .byobu
drwx------. 23 jim jim 4.0K Jan 14 12:25 .cache
drwx------. 21 jim jim 4.0K Dec 19 12:58 .config
drwxr-xr-x. 4 jim jim 4.0K Dec 19 14:58 Desktop
drwxr-xr-x. 2 jim jim 4.0K Nov 2 00:01 Documents
drwxr-xr-x. 4 jim jim 4.0K Jan 16 15:06 Downloads
-rw-rw-r--. 1 jim jim 85 Dec 10 14:07 .gitconfig
-rw-r--r--. 1 jim jim 12 Dec 10 14:08 .gitignore
drwx------. 3 jim jim 4.0K Nov 19 08:39 .gnome
drwxr-xr-x. 3 jim jim 4.0K Dec 19 17:32 .grip
-rw-------. 1 jim jim 10K Jan 16 19:15 .ICEauthority
drwx------. 2 jim jim 4.0K Dec 15 11:01 .irssi
drwx------. 5 jim jim 4.0K Jan 6 18:36 .local
drwxr-xr-x. 6 jim jim 4.0K Nov 2 00:10 .mozilla
drwxr-xr-x. 2 jim jim 4.0K Nov 2 00:01 Music
drwxr-xr-x. 115 root root 4.0K Jan 14 12:24 node_modules
drwxr-xr-x. 6 jim jim 4.0K Dec 8 09:50 .npm
drwxr-xr-x. 6 jim jim 4.0K Dec 8 09:47 .nvm
drwxr-xr-x. 11 jim jim 4.0K Dec 27 14:06 .oh-my-zsh
-rw-r--r--. 1 root root 30K Jan 14 12:24 package-lock.json
drwxr-xr-x. 2 jim jim 4.0K Dec 9 11:22 Pictures
drwxrw----. 3 jim jim 4.0K Nov 2 00:01 .pki
drwxr-xr-x. 4 jim jim 4.0K Dec 8 10:57 projects
drwxr-xr-x. 2 jim jim 4.0K Nov 2 00:01 Public
drwx------. 2 jim jim 4.0K Jan 11 10:40 .ssh
drwxr-xr-x. 2 jim jim 4.0K Nov 2 00:01 Templates
drwxr-xr-x. 2 jim jim 4.0K Nov 2 00:01 Videos
drwxrwxr-x. 3 jim jim 4.0K Nov 2 00:20 .vim
-rw-------. 1 jim jim 21K Jan 12 11:34 .viminfo
-rw-rw-r--. 1 jim jim 4.1K Dec 13 10:33 .vimrc
drwxr-xr-x. 3 jim jim 4.0K Dec 9 16:37 .vscode
-rw-r--r--. 1 jim jim 215 Jan 6 15:02 .wget-hsts
-rw-------. 1 jim jim 24K Jan 17 13:38 .zsh_history
-rw-------. 1 jim jim 6.3K Dec 4 14:13 .zsh_history.corrupt
-rw-r--r--. 1 jim jim 3.4K Jan 12 11:34 .zshrc

There are both dot files and dot folders in that list. (Hiding a directory is done the same way, just prepend its name with a dot.)

Many of these are configuration files and directories, especially for command line utilities. The Files .zshrc and .zsh_history and the folder .oh-my-zsh for example, are the configuration files that hold all of my customization directives for ZSH, the shell I use, as well as the incredible Oh My Zsh.

To edit files, I use Vim, also with a ton of customizations found in the files .vimrc , .viminfo and the directory .vim

These files are what make your working environment your own. When you’ve gotten them just how you like, you don’t want to lose them, or have them get out of sync with other machines you may work on. It makes sense to keep them in a structured version control system.

Git to the rescue.

If you’re reading this, you’re probably familiar with Git. You may have cloned a repository from or even created and shared repositories of your own.
Typically, you’ll clone a project, which will exist as a directory filled with source code that you’ll edit or compile or whatever. When you make changes, you can commit them back up to Github or BitBucket, or somewhere else.
Git’s great–you can work with highly distributed teams of collaborators or work offline. You can, (if you’ve set it up correctly,) jump back to any save point and step through every commit.
When you’re a single user, you can use it to sync your project across many machines, which makes it ideal for synchronizing your dotfiles.
What always stopped me from doing this is that I didn’t want to put my whole home directory into Git – there’s a lot of stuff I don’t want to sync and the only way I knew how to exclude it was by explicitly listing it in the “Git Ignore” file, which seemed like too much work.
What some people started doing was to create a git repo, one level down, that contained the files, along with a script that would create symbolic links from that directory to your home directory. To me, this seemed an inelegant solution.

An Elegant Solution

A while back, I decided to revisit the problem and did some Googling, eventually coming across a post on Ycombinator:

========= Start of Quoted post ==========

StreakyCobra on Feb 10, 2016
I use:

    git init --bare $HOME/.myconf
    alias config='/usr/bin/git --git-dir=$HOME/.myconf/ --work-tree=$HOME'
    config config status.showUntrackedFiles no

where my ~/.myconf directory is a git bare repository. Then any file within the home folder can be versioned with normal commands like:

    config status
    config add .vimrc
    config commit -m "Add vimrc"
    config add .config/redshift.conf
    config commit -m "Add redshift config"
    config push

And so on…

No extra tooling, no symlinks, files are tracked on a version control system, you can use different branches for different computers, you can replicate you configuration easily on new installation.

========= End of quoted post ==========

Let’s take a look at those lines that do the work. First, a bare Git repo is created in your home directory:

 git init --bare $HOME/.myconf

That’s simple enough, but what about that next line?

alias config='/usr/bin/git --git-dir=$HOME/.myconf/ --work-tree=$HOME'

This part is really, really cool–it creates a new command called config that you use just like the command git, that adds some special options that apply only to the dotfiles problem.
It’s a wrapper for Git that says that the working directory is in ~/.myconf, but the actual versioned files live in your home directory.
Read that a couple times until you completely understand the sheer awesome power of what that simple line does.
Elegant AF.

The last line uses our newly-minted command to tell git to ignore files that we haven’t explicitly added, something that makes a lot of sense, given how much junk gets stashed in $HOME:
config config status.showUntrackedFiles no

Anyway, what was supposed to be a quick post has grown a bit, so I’m going to go ahead and publish it. Let me know if you have any questions or see any errors.

Please note! Your .ssh directory is kind of special in that while you may want to back up your encryption keys, doing so on a site such as Github is a tremendously bad idea.
Just don’t.
Feel free to back up
.ssh/config though, if you’ve customized it.

Everything But The Code

Reading Time: < 1 minuteI’ve been working on a side project lately that, while isn’t anywhere near completion, is probably ready to start sharing.
It’s a course, of sorts, that I’ve been calling “Everything but the Code.” When I get a feel for how much time each section will take, I’ll begin the process of finding students for a face-to-face class.

It’s an introduction to some of the technologies I use that aren’t programming, but are all tools in a programmer’s tool box. Things like Unix and ‘Unix-like’ filesystems, Unix-like command interpreters, (AKA, “Shells,”) Git and GitHub–stuff that’s pretty much assumed that you know how to do, yet so many good programmers don’t.

So take a look at it and let me know what you think:
Everything But The Code

If you’d like to add something to the course, you can submit a pull request to This Repo.

What is a Bubble Sort?

Reading Time: 3 minutes


In this post, we’re going to be taking a look at sorting, with a particular focus on what’s known as a “Bubble Sort.”


In computing, sorting is one of those things you rarely think about. Applications that present users with lists usually have a button to sort search results. Your Amazon or eBay searches let you sort by price or distance, for example.

Linux has a handy commandline utility called ‘sort’. Let’s say you wanted to know about a certain subset of programs you were running and you started with:

$ ps aux |grep $USER

which dumps a whole lot of information to the screen, so you start piping that through other utilities, (often called ‘filters’ when used this way,) until you come up with something like this:

$ ps aux |grep $USER| grep bin| awk '{print $11}' | awk -F '/' '{print $NF}'|sort| uniq

(Note: This is not a useful set of filters. I just cobbed it together as an example)
It works and works well, without us having to think about how a computer performs the many, many operations needed to actually do the sort.
There are many algorithms, in many different languages and perhaps the simplest is known as a Bubble Sort.

So, what’s a Bubble Sort?

A “Bubble Sort” is an algorithm where the desired results “bubble up,” based upon the comparisons you do to pairs of elements, as you iterate through a stack of numbers. Basically, you step through your array and compare each value with the adjoining value. If it’s lower, move it to the left. Keep iterating until your array is sorted:
Gary Sims, from the excellent Gary Explains channel on Youtube explains it really well here:

(If you want to play with Gary’s code, but don’t feel like typing it in, you can grab it from my Github copy of it:

$ git clone

This is really a great way to understand what happens in a bubble sort, but of course, written in python, it’s probably only useful as an educational exercise. Python, after all, is a very high level language.
Take a look at this example, written in Assembler, a very low-level computer language that’s as close to machine code as anyone is likely to be working with:
(Example code by @stephenpaulger on GitHub)

; Runs on

	MOV C, data	; C tracks the address of end
	ADD C, 16	; of the unsorted section of data.

	DEC C           ; One byte is sorted each pass
	MOV D, data	; Start of the data
	MOV A, [D]
	CMP A, [D+1]    ; Compare two adjacent values
	JNA noswap      ; jump if the don't need swapping
	MOV B, [D+1]	; swap the two values
	MOV [D+1], A
	MOV [D], B
	INC D		; Move along the data one byte
	JB bubble	; loop if there's more unsorted data
	CMP C, data
	JNB start	; start again unless we've sorted all values.

	DB "_______"	; Align the sorted data nicely.
	DB "QWERTYUIOPASDFGH"  ; 16 characters to sort.

Even if you’ve never looked at Assembler before, with the comments, it’s not difficult to see what’s going on and that it’s not too different than Gary’s Python example.

This is all something that you could do with playing cards: take eight or so number cards from the deck and arrange them in random order, face up. Take the first two cards and compare them. If the card on the right is the lower of the two, swap the two cards. Move one spot to the right and repeat. Do this for the whole row. When you get to the far right, start again from the left and repeat the process, until you have no more cards to swap.

I hope that gives you a better understanding of one of those basic concepts that are too-often neglected in computer education.


tldr, what’s missing from Unix ‘man’ pages

Reading Time: 4 minutesToday’s article is an introduction to the ‘tldr’ utility, a collection of simplified and community-driven man pages. ‘tldr’ enhances Unix/Linux by providing clear, real-world examples for using command line utilities.

When I was a kid, I had the kind of parents who would never tell you the meaning of a word.
“Get the dictionary and look it up,” I was told over and over.
It was good for me, of course, as a learning exercise, but at the time, it seemed almost punitive.
“Ugh, do I haaaave to? Can’t you just tell me??”

Well, if you’re like me, that’s how it feels to work with Unix “man’ pages–you know that all the answers to your questions are in there, somewhere, but the compilers of the pages seem to have forsaken readability for completeness and uniformity.
That doesn’t help, when some commands are notoriously hard to remember:

tar tldr

Unix ‘man’ pages have been around since 1971, first written by Dennis Ritchie and Ken Thompson, the most venerated names in Unix. They are necessary and thorough, don’t get me wrong. I have nothing but respect for them. It’s just that, well, once in a while, they were a bit more, readable and perhaps, concise. For example, here’s (a bit of) what ‘man’ has to say about the ‘ls’ command:

$ man ls
LS(1) User Commands LS(1)

ls – list directory contents

ls [OPTION]… [FILE]…

List information about the FILEs (the current directory by default). Sort entries alphabetically if none of -cftuvSUX nor –sort is specified.

Mandatory arguments to long options are mandatory for short options too.

-a, –all
do not ignore entries starting with .

-A, –almost-all
do not list implied . and ..

with -l, print the author of each file

-b, –escape
print C-style escapes for nongraphic characters

scale sizes by SIZE before printing them; e.g., ‘–block-size=M’ prints sizes in units of 1,048,576 bytes; see SIZE format below

-B, –ignore-backups
do not list implied entries ending with ~

-c with -lt: sort by, and show, ctime (time of last modification of file status information); with -l: show ctime and sort by name; otherwise: sort by ctime, newest first

(That’s just the start. It goes on for a total of 206 lines on my system.)
Reading that feels a bit like taking that long walk to the bookshelf to open the dictionary, only to be overwhelmed with seemingly irrelevant information, when the information you actually needed could have been cleared up with an example or two. (Again, I’m not advocating the dumbing down of the ‘man’ page system–it’s comprehensive, as it needs to be. It’s just that there’s room for something more, especially as more and more casual users discover Linux.)

ls is one of the simplest commands in the *nix shell. Essentially, it lists out the contents of a directory. You can run it by itself:

$ ls
bar baz corge foo quux quuz qux

That will list out the names of the non-hidden files in a directory. If you want to see the hidden files, you add the ‘-a’ option:
$ ls -a
. .. bar baz corge foo .hidden_file quux quuz qux

If you want to list out pretty much everything, add a bunch more options, that spell out “-Flag” (That’s 4 options, ‘F’, ‘l’, ‘a’ and ‘g’, not a word. ‘galF’ would work as well, but ‘Flag’ is easier to remember.):
$ ls -Flag
total 48
drwxrwxr-x 3 jim 4096 Jun 6 17:45 ./
drwxr-xr-x 43 jim 4096 Jun 6 17:45 ../
-rw-rw-r– 1 jim 11962 Jun 6 17:41 bar
-rw-rw-r– 1 jim 0 Jun 6 17:42 baz
-rw-rw-r– 1 jim 544 Jun 6 17:44 corge
-rw-rw-r– 1 jim 7771 Jun 6 17:41 foo
-rw-rw-r– 1 jim 3259 Jun 6 17:45 .hidden_file
-rw-rw-r– 1 jim 4 Jun 6 17:43 quux
-rw-rw-r– 1 jim 182 Jun 6 17:44 quuz
drwxrwxr-x 2 jim 4096 Jun 6 17:43 qux/

Those are (almost) all of the options I’ve ever bothered to memorize. According to ‘man’ there are 59 different options, but no user-friendly examples, accessible for a newbie, or someone in a hurry.

'tldr' to the rescue!
The ‘tldr’ Github page describes itself as:
“A collection of simplified and community-driven man pages.”
That sounds pretty promising. Let’s install it and try it out!

$ sudo npm install -g tldr

(Unfortunately, on two of my systems, that produced hundreds of lines of errors about ‘node-gyp’ and something called ‘webworker-threads’. No worry, there’s a ‘snap’ package I can install:
$ sudo snap install tldr

which worked without a hitch.)
Let’s try it out with ‘ls’:
$ tldr ls
Page not found. Updating cache ..
Creating index…


List directory contents.

– List files one per line:
ls -1

– List all files, including hidden files:
ls -a

– Long format list (permissions, ownership, size and modification date) of all files:
ls -la

– Long format list with size displayed using human readable units (KB, MB, GB):
ls -lh

– Long format list sorted by size (descending):
ls -lS

– Long format list of all files, sorted by modification date (oldest first):
ls -ltr

That was even easier than Googling stackoverflow. (Of course, if you were to *ask* on stackoverflow something as simple as options for ‘ls’, you’d immediately get sent to the ‘man’ pages.) Fortunately, there are places to go for questions like this.

If you’re not ready to install tldr on your own system yet, you can always use the online version.

I hope this has been helpful. I only found out about ‘tldr’ this morning, as it was linked to from a post on Reddit and wanted to share it with you all.

SSH the secure way, with SSH keys

Reading Time: 8 minutes


(TL;DR) If you Google this sort of topic looking for the minimum commands needed to get it working, you simply need to generate a good key and copy it to the server. Below are those commands. (Code blocks with strikethough formatting are for illustrative purposes and should not be run.) Do consider reading the whole article, though, to better understand how to secure your connection.
To SSH without a password using SSH keys:
Generate a key pair:

$ ssh-keygen

You know, as long as we’re generating a key pair, let’s give it a more robust key than the default by specifying a byte length of 4096:
$ ssh-keygen -t rsa -b 4096

Copy it to the server:

$ ssh-copy-id you@remote.server


In this post, I will walk you through the setup of SSH keys and their basic usage.
(For a simple overview of the technologies involved, visit the Public Key Cryptography page on Simple Wikipedia.)
The goal is to enable you to log in to a remote server without having to type your password each time, while increasing security and improving your ability to automate what you do.

Why not just stick with passwords?

People, when given the opportunity, pick terrible passwords, then reuse them irresponsibly. Even if you pick a decent (8-character NTLM,) password, as of 2012, it was possible to brute-force crack it in ~6 hours, using a fairly affordable computer.
You simply cannot brute-force an SSH key. The NSA might be able to, but any hacker looking to get in to a system is going to look for a different way to get in.
For this, you’ll need a computer running Linux, Windows, or OS X, as well as a server running an SSH server on which you have a login and password.
For simplicity’s sake, we will be doing everything from the command line, so if you’re on Windows, you’ll want to first install Git Bash. If you’re on a Mac, open up Terminal from your Utilities folder. (Yes, many people using Window prefer Putty, but configuring that is outside the scope of this document.)

Generating your key pair

When you have your terminal open, we’re going to generate what is known as an RSA key pair.

$ ssh-keygen -t rsa -b 4096

This command will ask you a few questions. For now, we’re going to simply hit `enter` and go with the defaults, as well as an empty passphrase. (More on that later.)
Generating public/private rsa key pair.
Enter file in which to save the key (/c/Users/User/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /c/Users/User/.ssh/id_rsa.
Your public key has been saved in /c/Users/User/.ssh/
The key fingerprint is:
SHA256:RxUO7mLtlE3LSa1HrOJAkOJYg+JTzIHpZDvWIdR6Ws8 User@x230Len171025
The key’s randomart image is:
+- -[RSA 2048]- – +
|..*o. .. . o. |
|.*.*+ .. . + o |
|=.*+.o . o + + |
| O.+. . + * * |
|. * o S B B . |
| . E . B . . |
| o |
+- – -[SHA256] – -+

If everything worked and it generated that weird bit of ASCII art, we’re ready to move on to the next step:

Uploading Your Key

To be of any real use, you need to put your key somewhere. We’re going to upload it to the server. Let’s suppose that you are logging in to the host and your user name is jim.
We’ll first log in using a password:

User@x230Len171025 MINGW64 ~

If this is your first time logging in, you’ll be asked to confirm the server’s identity:

  $ ssh
The authenticity of host '' can't be established.
ECDSA key fingerprint is SHA256:u6fDHy25AXJD3MWXLkjhgkjhgLOjoBdZQOoQCZXBI.
Are you sure you want to continue connecting (yes/no)?

Type “yes”. (More on this later.)

  Warning: Permanently added '' (ECDSA) to the list of known hosts.'s password:

Type your password and hopefully you are now greeted with your remote prompt:$

Very good! Now log out, using Ctrl-d.
Back at your local terminal, we’re going to copy your key to

$ ssh-copy-id

This will (hopefully) give you output similar to the following:

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/c/Users/User/.ssh/"
The authenticity of host ' (' can't be established.
ECDSA key fingerprint is SHA256:u6fDHy25AXJD3MWXLi9Up2rmDp2LOjoBdZQOoQCZXBI.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys's password:

Number of key(s) added: 1

Now try logging into the machine, with: "ssh ''"
and check to make sure that only the key(s) you wanted were added.

Give it a try:

$ ssh

If everything went as it should have, you’ll be now logged in to the remote machine, without having been asked for a password. Pretty cool, eh?
How can we make it better?

Customizing your SSH Config

When we created the SSH keys, it stores them by default in a hidden directory in your home directory, called ‘.ssh’ where we can put a special file called ‘config’ that can hold some very useful configuration options.
Let’s edit the config file. (You may need to create it, but when you do, it will be instantly activated, as long as it’s in the correct directory.)
What would we want in this file? Keeping our example above in mind, we might add the following directives for this host:

host test web1 
User jim
Port 22
ServerAliveInterval 120

The first line defines a bunch of aliases for this host, any of which can be used, like:

ssh test

would be the same as typing:

ssh -l jim -p 22

(Yes, port 22 is the default, so explicitly specifying it may seem superfluous, but I’ve added it for when you want to specify a non-standard port.)
On my Windows laptop, I never changed from the user called “User,” so if I don’t specify a different user, that’s what it will try to log in with, so I specify “jim” in the config.

Next Steps

If you’ve gotten this far, you are well on your way, but there are things you can do to make your connection even more secure. Let’s get started:

Add a PassPhrase

First off, you need to have a good passphrase for your key. (Wait? What? Wasn’t the whole point of this to get away from passwords?)
The point of having a passphrase to encrypt your private key is to protect your key if your laptop is lost or stolen, or you lose track of an old backup. Without a passphrase, whoever has this key can log in whereever the key has been authorized.
The convenience of a password-free login has a great deal of appeal, which is reports that “More than 90% of all SSH keys in most large enterprises are without a passphrase.”
If you have a key that doesn’t have a passphrase, it’s easy to add one:

$ ssh-keygen -p
Enter file in which the key is (/c/Users/User/.ssh/id_rsa):
Enter new passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved with the new passphrase.

By default, SSH will ask you for this passphrase every time you invoke the key, something that gets tiresome quite fast. Fortunately, there is a way to minimize the inconvenience:

SSH Agent

SSH Agent is a program that will ask you once at the beginning of your session for your passphrase and cache it for the length of your session
You can run it manually

$ eval $(ssh-agent)

Having to put “eval” in the command has led to a lot of frustration and misunderstanding about ssh-agent. After all, running ssh-agent alone doesn’t seem to raise an error, but doesn’t do what we need:

$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-dHKgccDFLL7z/agent.14536; export SSH_AUTH_SOCK;
echo Agent pid 5588;

What’s happening is that ssh-agent is generating some environment variables, but ssh-agent cannot evaluate them for the parent process, (it’s a Unix security issue,) so we must call ‘eval’ explicitly.
Next, we must add our key to the agent:

$ ssh-add ~/.ssh/id_rsa

Believe me, this is *not* something you want to have to do every time you want to get some work done, so let’s script it all to run automatically at login.
On your workstation, open up your .bash_profile (for Git Bash on Windows, create a file called “.bashrc” in your home directory,) and add the following to the end of the file:


function start_agent {
echo "Initialising new SSH agent..."
/usr/bin/ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}"
echo succeeded
chmod 600 "${SSH_ENV}"
. "${SSH_ENV}" > /dev/null

# Source SSH settings, if applicable

if [ -f "${SSH_ENV}" ]; then
. "${SSH_ENV}" > /dev/null
#ps ${SSH_AGENT_PID} doesn't work under cywgin
ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {

.bash_profile is for Bash, of course. For other shells, you’ll need to find its ‘.profile’ equivalent. If, like me, you use Robby Russel’s excellent Oh My Zsh, there’s a plugin for ssh-agent.
When you have that all configured, reboot your workstation if you can, to properly test.
Open a terminal, ssh to your favorite host, enter the passphrase when prompted, hopefully for the only time this session.


To be truly secure, you need a good source for entropy. People have gone to great lengths to devise random number generators, but for our purposes, we’re going to look at the two built in to a Unix-like system: /dev/random and /dev/urandom.
There are a lot of differing opinions on which you should use. /dev/urandom is the default and it’s arguably a good choice, but if you’d like to use /dev/random, you can do that by setting an environment variable before generating your key:

$ export SSH_USE_STRONG_RNG=64

As long as we’re being paranoid, let’s now generate a *huge* key, the largest currently allowed:

ssh-keygen -b 16384

That will take some time, probably a minute or two on a typical home computer, but back in 2004, it would have taken days.
So, should you use a huge key? Perhaps, for bragging rights, if you happen to have friends who would understand what you are talking about, but you’d probably be looking at diminishing returns.

Verifying the Server

What good is any of this, if you cannot know for certain that the server you are talking with is not, in fact, who it says it is?
Remember, above, when we were told “The authenticity of host ‘’ can’t be established“? Well, it *is* possible to verify the server’s identity absolutely, but to do so properly, you need to have someone logged *directly* in to the server. Sitting in front of the actual machine, on an attached console or KVM, *not* using SSH to connect.
That person should run the following commands to extract the key signatures: (More on this.)

cd /etc/ssh
for file in *
do ssh-keygen -lf $file

Ideally, this should be done after the SSHD daemon is installed from trusted media, but before the machine is connected to the Internet.
Those signatures should then be printed, signed, notarized, copies made, those signed and the originals placed in an envelope that is sealed with a wax seal and placed in a bank vault deep in the Swiss Alps.
OK, perhaps that last bit is excessive, but how much do you need to be sure that your connection has not been compromised? Having the signatures printed off at install time would be a good idea, as well as having humans involved in the verification process would not be out of line if your organization uses these connections to deal with sensitive or valuable information.

Disable Password Login

Finally, when you are comfortable that you’ve done everything correctly, gotten your keys created, tested and backed up somewhere safe, it’s time to disable password logins completely. Be sure to do this only on a server that you have physical access to, so you can plug in a keyboard and monitor if you screw something up.

$sudo vi /etc/ssh/sshd_config 

Find the directives below in that file and change each of them to “no”:

ChallengeResponseAuthentication no
PasswordAuthentication no
UsePAM no

When that’s completed, restart the SSH server:

 $ sudo service ssh restart 

The great thing about SSH, as you have seen here, is that it will rise to the challenge of verifiably securing your data in transit, while staying fairly simple and unintrusive, after just a bit of configuration.


Thanks to the following Reddit users for reading this, pointing out errors and omissions and generally challenging me to write an article worth reading:


The Voice Kit is *not* a Google Home in kit form

Reading Time: 3 minutes

(Update: Please visit the AIY SubReddit!)
Yesterday morning around this time, I read the announcement of the new kits from Google and got pretty excited. The Google Voice Kit got an upgrade and now includes a Raspberry Pi WH model along with all the other hardware you need to put this together. They also released something called a Vision Kit that does some pretty cool image processing. (No doubt I will get one of those as well, but for now, there are things I want to try with the Voice Kit first.)

The hardware build was pretty simple, but there are places where you need to have the instructions, such as assembling the speaker’s wire harness. Do yourself a favor and follow the instructions. The cardboard case, in particular, should be done in a certain manner, as to not have it look like garbage when you have completed it.

So, I got the thing all together and booted it. The green LED on the Pi flashed and everything looked good. I ran the Android app and pushed the buttons as directed and… Nothing. I rechecked all of the connections and rebooted and again, nothing. The next step was to get a monitor and keyboard hooked up to it to see what was going on with it. The thing is, it has a Mini HDMI connector and Micro USB, unlike the other Raspberry Pi’s I’ve used. That means you need some special connectors and micro USB OTG cable and some way to get both a keyboard and mouse connected to the one micro USB, all which I fortunately happened to have and was somehow miraculously able to find.

I rebooted the device and it went to a black console screen with small Raspberry and a flashing cursor. It didn’t display the familiar rainbow square that my other Pi’s do and there was no scrolling of boot messages. I figured that the card’s image had probably gotten corrupted, either in transit, or by something I did after assembling it. (I probably powered it down at a bad point.) The thing is, there’s no way of knowing without a monitor connected.
I found the help section on the AIY website that has a link to the disk image, a modified Raspbian image. I downloaded that and flashed it to the card and rebooted with the monitor, mouse and keyboard connected.

This time, it worked and it displayed a Raspbian desktop. I pushed the big white arcade button on top, expecting to hear a familiar Google Home chime or a voice or something, but, again, it did nothing. Back to the instructions.

At this point, I had the hardware correctly assembled and configured and the software running and connected to my WiFi. It is time to start enabling the Google end of things, something which requires using the command line, either via SSH or on the Pi directly, using Raspbian’s console. Don’t worry if you’re not familiar with the command line–the instructions are clear and written with a beginner in mind. The section “Get Credentials” will probably be new and unfamiliar territory, if you are not a developer, familiar with API’s and all of that. Again, the instructions are clear and straightforward, though complex. Read them carefully.

When that’s all done, find Step 90, “Move to the demos folder” and type the commands as instructed to run the demonstration program. Running the demo, you really will want to keep an SSH session open, so that you can see what’s happening. Without it, there is simply too little feedback to be of use.

Is it a fully-fledged Google Home at this point? No. It doesn’t have any “Hey Google” listening capability. It can’t play or stream music yet. It does’t do *anything* if you just boot it up with a factory configuration.

Am I disappointed? Not at all. What this thing does give you is potential–it’s as hackable as any Raspberry Pi, with some cool new hardware. It’s got Python and some custom libraries that will let you do things that you could never do with a Google Home, such as experiment with its GPIO pins, or perhaps make it the interface for a completely different piece of hardware: “Google, preheat the oven to 425 degrees and then bake for an hour. Reduce the temperature to 300 degrees and bake for 20 minutes. Send me a text when it’s done.”

I’ll be writing more about what this thing can do, here and on Reddit’s AIY sub, but for now, I’m going to go hack around with it to find out.