Using Keybase pgp keys for github gpg verification

September 28, 2017

I recently started using the excellent app for encrypted chat and all the crypto goodness motivated me to finally set up gpg verified commits on Github. I started with this helpful article: Github GPG + Keybase PGP which I recommend you take a look at, but I had to do a few more steps that I wanted to document.

Installing Keybase

Keybase is easy to install: For arch, it was a simple install and setup:

packer -S keybase-bin  

Once installed, you’ll need to start up the app and create an account if you haven’t already.

Generate a key

Generate a new key with keybase, and upload it to your profile. Alternatively, use keybase pgp select to use your an existing key. To use this key for Github verified commits, it will need to have the same email as on your Github account.

$ keybase pgp gen

Export your keybase secret key to your gpg keyring:

$ keybase pgp export -s -p | gpg --allow-secret-key-import --import --

List keys in your gpg keyring and locate your keybase key

$ gpg --list-secret-keys --keyid-format LONG
sec   rsa4096/C17228D898051A91 2017-01-30 [SC]
uid                 [ultimate] Jay Baker 
ssb   rsa4096/7C87801D5E56F673 2017-01-30 [E]

sec   rsa4096/C24CD98AB0900706 2017-09-28 [SC] [expires: 2033-09-24]
uid                 [unknown] Jay Baker 
uid                 [unknown] Jay Baker 
ssb   rsa4096/4599729752E8D5C4 2017-09-28 [E] [expires: 2033-09-24]

I have two keys here, the second one is the one I made with keybase pgp gen. We want to grab the keyid string from the second line:

sec   rsa4096/C24CD98AB0900706 2017-09-28 [SC] [expires: 2033-09-24]

Let’s set a trust level for our key. Since we just made it, we can give it full trust.

$ gpg --edit-key C24CD98AB0900706
gpg (GnuPG) 2.2.1; Copyright (C) 2017 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

sec  rsa4096/C24CD98AB0900706
     created: 2017-09-28  expires: 2033-09-24  usage: SC  
     trust: unknow      validity: unknown
ssb  rsa4096/4599729752E8D5C4
     created: 2017-09-28  expires: 2033-09-24  usage: E   
[unknown] (1). Jay Baker 
[unknown] (2)  Jay Baker 

gpg> trust

Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)

  1 = I don't know or won't say
  2 = I do NOT trust
  3 = I trust marginally
  4 = I trust fully
  5 = I trust ultimately
  m = back to the main menu

Your decision? 5
Do you really want to set this key to ultimate trust? (y/N) y

sec  rsa4096/C24CD98AB0900706
     created: 2017-09-28  expires: 2033-09-24  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/4599729752E8D5C4
     created: 2017-09-28  expires: 2033-09-24  usage: E   
[ultimate] (1). Jay Baker 
[ultimate] (2)  Jay Baker 

gpg> quit

Now we can decide to do global or per repository signing with git. This step is optional, you can always manually sign commits with git -S or git --gpg-sign on a per commit basis.

$ git config commit.gpgsign true

This is per repository, add a --global flag after config if you want to enable gpg signing globally for git. If we change our minds later and want to disable signing just run the same command but with false. Also, if want to do just do a single commit without signing:

$ git --no-gpg-sign commit

Now let’s tell git which gpg key to use:

$ git config user.signingkey C24CD98AB0900706 # per repository

Again, add a --global flag if you want.

To verify that our commit worked:

$ git log --show-signature
commit 1f10113fadeae03fd8de870fb18c8563d0b3c602 (HEAD -> master)
gpg: Signature made Thu 28 Sep 2017 17:23:20 EDT
gpg:                using RSA key F21FC721B22B0C176BAFBE35C24CD98AB0900706
gpg: Good signature from "Jay Baker " [ultimate]
gpg:                 aka "Jay Baker " [ultimate]
Author: Jay Baker 
Date:   Thu Sep 28 17:23:20 2017 -0400
	detailed commit message goes here

Add our key to Github

Finally, we need to add our key to Github. Remember, your key will need the same email as your Github user email. You can add more email addresses to your key with gpg --edit-key and then the adduid command.

Let’s get our public key from keybase:

$ keybase pgp export


Copy that, and head to, click “New GPG key”, paste it in, then click “Add GPG key” to save it. verifi

That’s it! You can now have verified commits on Github with your keybase pgp key!


Using Go and fsnotify to watch a directory for new files

April 8, 2017

I’ve been very busy at work, mastering infrastructure as code tools and work-flows, but somehow I’ve found the time to start learning Go!

I had already learned some python and even used it for a couple of small projects at work. Python is a great language with beautiful syntax that makes coding a joy, but it’s slow as molasses and managing dependencies is no fun. Docker can help here (that’s how I solved my dependency and environment parity issues), but you just can’t beat static binaries for portability and ease of deployment, not to mention speed.

Go is a newer language compared to Python or Java, but it has quickly gained popularity. Most of my favorite DevOps tools are written in Go: Docker, Kubernetes, Consul, Nomad, Packer, Terraform … the list goes on. When new open source DevOps tools appear, it’s more surprising at this point when they’re not written in Go!

For a previous project, I wrote a little tool in python that watches for newly uploaded files and feeds them into an ETL pipeline. It wasn’t pretty but it got the job done. Since that’s a problem I can wrap my head around, I decided to build the same thing in Go, or at least the file system watching part. Moving files around the filesystem is fairly trivial in any language.

The code:

I’ve since created a more powerful version of this which I hope to finish up soon and post here, but I figured this little snippet would be useful for anyone just getting started with Go or fsnotify


Installing Antergos Linux on a MacBook 4,1

March 12, 2016

Linux is a great way to breathe life into old hardware, but getting it to play nice with Mac hardware can be difficult. This guide will show you how to replace OSX entirely with Antergos Linux on a MacBook 4,1.

Before you begin

This guide assumes you want to completely remove Mac OSX from your hard drive and completely replace it with Antergos Linux. It is possible to dual boot with OSX, or even triple boot with Windows as well. For me, all I wanted was to put Linux on my aging MacBook. I don’t care about having OSX and I definitely don’t care about Windows.

This method doesn’t require any special bootloaders (like rEFInd), using only systemd-boot to get the job done. The upside to this is that it’s simple and follows The Arch Way. The downside is that you’ll have to hold down the alt/option key each time you start or reboot your MacBook. For me, this is a small price to pay, but if you think it will bother you, you’ll have to follow another guide. Good luck!

Finally, you should back up any important data before proceeding. It may also be useful to ensure you have an OSX installation medium handy, in case you change your mind and wish to reinstall OSX. That being said, let’s get to it!

Prepare the installation medium

You will need a USB drive with at least 8Gb of space. Head to the Antergos website and download the 64 bit iso. Follow these steps to create a bootable USB in Mac OSX. If you’re creating the USB on Linux then just do:

sudo dd if=/path/to/downloaded.iso of=/dev/sdX

Be patient, it will take a while. Replace /dev/sdX with the name of your inserted USB drive. Be Careful! The dd command can destroy your disks, always double check to be sure you’re specifying the correct drive with of=. A sure fire way make sure you’ve got the right drive is to remove the USB drive, open up a terminal window, and enter lsblk. This will print a list of all the drives connected to the system. Now insert the USB drive and enter lsblk again, your USB drive’s designation will be the one that wasn’t there before.

You could, of course, just burn the Antergos iso to a DVD, but who has time for that?

Install Antergos

Insert your newly created Antergos USB installer and reboot your MacBook. When you hear the Mac startup sound, press and hold the alt/option key. Click the little arrow underneath the orange USB drive symbol that says “EFI boot.”

Once the boot menu loads for the Antergos iso, I found that you’ll have to select the first option in the menu rather than the defualt. Select it and wait for the Gnome live environment to load. Once it loads, you’ll be presented with the beautiful Cnchi installer. Click through the various options, selecting your preferred Desktop Environment of choice.

Personally, I went with Cinnamon because my girlfriend will be using this MacBook alot and she’s already familiar with Cinnamon. The MacBook 4,1 seems to handle it pretty well (especially if you turn off some of the visual effects), but you’ll get even better performance with MATE, xfce, or Openbox. I would recommend against Gnome or KDE on a MacBook 4,1, however. They will run and perform tolerably for the most part, but they can become painfully slow at times. Cinnamon is about as flashy as you can get for a desktop environment on the 4,1.

When you get to the drive set up section, you can leave the default choice to let the installer prepare the drive, but on the Bootloader section, select systemd-boot. It won’t work out of the box for the MacBook 4,1, but it will lay the ground work for our next steps.

Once you’ve selected all of your preferred options in the installer, wait for the packages to be downloaded and installed. Depending on your selections and your internet connection, it could take a while. Once the installation completes, you’ll get a warning about systemd-boot possibly not installing correctly. No big deal, we’re about to fix that. Click the button to restart later.

Repair systemd-boot

Open up a terminal (Press the Command key to open up Gnome’s expose thing, and start typing “terminal”) and verify your partitions with lsblk.

Now, we need to mount the partitions that we’ve just installed Antergos on. If you let the installer partition the drive, then the following commands will work. If you set your own partition scheme, then you’ll need to make sure that your / partition gets mounted to /mnt and your /boot partition gets mounted to /mnt/boot.

sudo mount /dev/sda2 /mnt
sudo mount /dev/sda1 /mnt/boot

Now, we’ll need to chroot to our mounted partitions:

sudo arch-chroot /mnt

Now we’ll first verify that dosfstools is installed, then we’ll set up systemd boot and create a boot menu entry.

pacman -S dosfstools

bootctl --path=/boot install
nano /boot/loader/entries/antergos.conf

Paste in the following and save with ctrl+x:

title Antergos
linux /vmlinuz-linux
initrd /initramfs-linux.img
options root=/dev/sda2 rw elevator=deadline quiet splash resume=/dev/sda3 nmi_watchdog=0

Next, we update /boot/loader/loader.conf to recognize our custom entry:

nano /boot/loader/loader.conf

Paste in the following, and press ctrl+x to save. The timeout is the number of seconds before the default option is selected, since we only have one option I’ve set it to 1. Change it to whatever you like. Leave editor as 0 though, it’s a security risk to change it. There will be some options already there, just comment them out with #.

default  antergos
timeout  1
editor   0

Finally, we update systemd boot to recognize the configuration changes and exit out of our chroot:

bootctl update

Restart your MacBook, and remember to hold down the alt/option key when you hear the Mac startup sound. You’ll see your hard drive display with the text “EFI Boot” underneath. Click the little arrow to boot into your Antergos installation. Since we didn’t set up rEFInd, we’ll have to do this every time we power on or reboot the MacBook. It’s sort of a pain, but it’s the price you have to pay to have a Linux only installation, and come on, it’s not really that bad.


Minimal, Clean Conky

January 26, 2016

Conky is a lightweight system monitor for X. It’s a great way to display all sorts of helpful information right on your desktop. It’s somewhat similar to Rainmeter (for Windows) or GeekTool (for OSX), but it’s far more powerful. Unfortunately, as with many things in Linux, powerful can mean hard to configure. In this guide, I’ll go over my ~/.conkyrc for a minimal, clean conky configuration that provides useful info without polluting your desktop with clutter.

desktop screenshot with conky

My current desktop with conky. I’m on Fedora 23 with Gnome for a desktop environment.


First, let’s install Conky. It’s available in the official repos of most distributions.

pacman -S conky          #For Arch
apt-get install conky    #For Debian/Ubuntu
dnf install conky        #For Fedora 23, use yum for older versions

Note that configuring Conky with your desktop environment/distribution may require additional packages to be installed. If you’re using Gnome on Fedora 23, then the .conkyrc I provide below will work for sure. If you’re using another desktop environment with Arch, check out the Arch wiki on conky. It provides tons of details on configuring conky, and even lots of little mini guides for how to cusomize your .conkyrc

If your distro doesn’t have a conky package, or if you want to compile it yourself, instructions can be found here.

Once installed, you could start using the default configuration right away. Just start conky with conky &. The default configuration is fine, but didn’t suit my tastes. Conky will look in ~/.conkyrc for any user configurations, so that’s where we’ll put ours.


Our minimal, clean .conkyrc:

# - Conky settings
update_interval 1
total_run_times 0
net_avg_samples 1
cpu_avg_samples 1
imlib_cache_size 0
double_buffer yes
no_buffers yes

# - Text settings
use_xft yes
xftfont Sans:size=12
override_utf8_locale yes
text_buffer_size 2048

# - Window specifications 
own_window_class Conky
own_window yes
own_window_type normal
own_window_argb_visual yes
own_window_argb_value 255
own_window_transparent yes
own_window_hints undecorated,below,sticky,skip_taskbar,skip_pager
alignment top_right
gap_x 40
gap_y 40
minimum_size 300 550
maximum_width 550
default_bar_size 550 8

# - Graphics settings
draw_shades no
default_color cccccc
color0 white
color1 E07A1F
color2 white

Kernel: ${alignr} ${execi 5000 uname -r | sed "s@.fc.*.x86_64@@g" }
Uptime: ${alignr}${uptime}

CPU1: ${cpu cpu1}%${alignr}CPU2: ${cpu cpu2}%
CPU3: ${cpu cpu3}%${alignr}CPU4: ${cpu cpu4}%
Temp: ${alignr}${acpitemp}°C

Memory: ${mem} ${alignr}${membar 8,60}
Disk: ${diskio}${alignr}${diskiograph 8,60 F57900 FCAF3E}
Battery: ${battery_percent BAT0}% ${alignr}${battery_bar 8,60 BAT0}

# Processes
Processes: ${alignr}$processes
Highest: ${alignr 40}CPU${alignr}RAM
${voffset -11.5}${hr 1}
${voffset -4}${top name 1} ${goto 124}${top cpu 1}${alignr }${top mem 1}
${voffset -1}${top name 2} ${goto 124}${top cpu 2}${alignr }${top mem 2}
${voffset -1}${top name 3} ${goto 124}${top cpu 3}${alignr }${top mem 3}
${voffset -1}${top name 4} ${goto 124}${top cpu 4}${alignr }${top mem 4}

${voffset -4}SSID: ${alignr}${wireless_essid wlp3s0}
${voffset -4}Local IP: ${alignr}${addr wlp3s0}
${voffset -4}External IP: ${alignr}${execi 600 curl}

${voffset -4}hal:${alignr}${execi 600 /home/user/bin/pingtest}
${voffset -4}helper:${alignr}${execi 600 /home/user/bin/pingtest}

Just open up your favorite text editor and paste in the above. Save the file as ~/.conkyrc. To test it, start conky with conky &. You should now see my conky configuration on your desktop!

A close up view of my conky configuration.

A close up view of my conky configuration.

Conky Config Explained

The first few sections deal with Conky’s appearance and position on the screen. If you want to change colors or positioning, poke around in here. Otherwise, let’s move on to TEXT section, this is the stuff that actually gets displayed on the screen.

First, let’s take a look at this line, and break everything down:

Kernel: ${alignr} ${execi 5000 uname -r | sed "s@.fc.*.x86_64@@g" }

On Fedora, uname -r returns this: 4.2.7-300.fc23.x86_64, which is more info than I want. I already know I’m on 64 bit Fedora 23. It’s just the kernel version that I want displayed. So we use sed to replace fc.*x86_84 with nothing, so we’re just left with the kernel version that precedes it. The * here is a regular expression meaning, any number of any characters. That way, when I upgrade to Fedora 24, I won’t have to change my conkyrc.

Of course, conky has a built in way to display the kernel version, with ${kernel}. I could just use this instead:

Kernel: ${alignr} ${kernel}

But just like uname -r, it would display the Fedora version and whether we have a 32 or 64 bit kernel: 4.2.7-300.fc23.x86_64. If you’re happy with what ${kernel} displays for your distribution, then just leave it. If you want to display just the kernel version, then modify the sed command as needed. sed is a very powerful tool, but it can be a little daunting at first. If you’re new to it, then check out the wikipedia entry for more info.

Let’s turn our attention to the networking section, as you may need to make some changes here:

${voffset -4}SSID: ${alignr}${wireless_essid wlp3s0}
${voffset -4}Local IP: ${alignr}${addr wlp3s0}
${voffset -4}External IP: ${alignr}${execi 600 curl}

${wireless_essid wlp3s0} will display the SSID (wireless network name) of whatever network the wlp3s0 interface is connected to. If your wireless interface is named differently, you will need to change this value. To find your wireless interface name, simply issue ip addr:

It will return information on all of your network interfaces, but we’re just looking for your wireless interace:

2: wlp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000

To get the local IP address, we use ${addr wlp3s0}. Again replace wlp3s0 with whatever your interface name is. Note that if you have a wired connection, it will not be displayed here. You’ll have to use ip addr to find the name of your wired interface and put it here.

There are several ways to get your external IP address, but I find that the simplest is to do curl Thus, our conky code is ${voffset -4}External IP: ${alignr}${execi 600 curl}.

Finally, we come to the handy little lines that show whether my servers are up.

${voffset -4}hal:${alignr}${execi 600 /home/user/bin/pingtest}
${voffset -4}helper:${alignr}${execi 600 /home/user/bin/pingtest}

/home/user/bin/pingtest is a super simple bash script that pings whatever url you give it and returns “Up” if it gets a response and “Down” if it doesn’t. Save this script to your /home/user/bin:


if ping -c 1 -W 2 "$1" > /dev/null; then
echo "Up"
echo "Down"

Alternatively, you could put the script anywhere in your $PATH. You can always check your $PATH environment variable with:

$ echo $PATH

If /home/user/bin isn’t part of your $PATH environment variable, you can add it by adding this line to your ~/.profile:

export PATH=$PATH:/home/user/bin

If you don’t have any servers to monitor, just remove those lines or comment them out.

And that’s all there is to my conky set up. Conky is a very powerful tool and can be used to display all sorts of information. I like mine simple and clean, but feel free to go crazy. There are tons of really slick conky configs out there.


Color Bash Prompt (PS1) with git Integration

December 11, 2015

You’ve seen it in screenshots and guides around the net: colorful custom bash prompts with useful info like what branch you’re currently in and if there are any uncommitted changes. Let’s learn how to make our own custom prompt with git integration!

Screenshot from 2015-12-11 18-17-28


Obviously, you will need git installed for this to work. But if you didn’t already use git, then you probably wouldn’t be reading this post so … Anyway, in order for us to add git info to our PS1, we’ll need to find the script on your system. On Fedora, it’s located at /usr/share/git-core/contrib/completion/, but on Arch it’s at /usr/share/git/completion/ If it’s not in either location, then just use the locate command to find it:

sudo updatedb && locate


Bash looks in a few different places for customizations, but the best place to put yours is usually your ~/.bashrc file. Anything in this file will sourced by Bash when you open a new shell or terminal window. The ~/.bashrc is specific to your user. Other user accounts on the system (like root) won’t source your user’s .bashrc. Learning your way around the .bashrc file is an essential skill for any Linux power-user. There is a lot you can do with it, but we’ll just focus on the PS1, aka the bash prompt.

Most distributions have a simple, default PS1, usually something like this:

user@host $ 

Note: The $ usually indicates that this is an unprivileged user, whereas # denotes the root user

That’s a serviceable prompt, but Bash allows you to customize it to your heart’s content. I’m only going to cover my personal PS1 in this post. If you want something tailored just for your needs and want to create your own custom bash prompt, then a good place to start is the Arch wiki: Color Bash Prompt.

If you just want to use my PS1, then comment out your current PS1 (in case you don’t like the new one and want to go back) and paste the following into your ~/.bashrc

# Simple PS1
#PS1='(\u:\h), \W, '

# Change this to the location of on your distribution.
source /usr/share/git-core/contrib/completion/

# Creates the bash_prompt function
bash_prompt () {

# Checks to see if the current directory is a git repo or not
gitcheck_branch="$(git branch &>/dev/null; if [ $? -eq 0 ]; then echo "yes"; else echo "no"; fi)"

if [ $gitcheck_branch == "yes" ];
        # If we are in a git repo, then check to see if there are uncommitted files
        gitcheck_status="$(git status | grep "nothing to commit" > /dev/null 2>&1; if [ $? -eq 0 ]; then echo "clean"; else echo "unclean"; fi)"

	if [ $gitcheck_status == "clean" ];
                # If there are no uncommitted files, then set the color of the git branch name to green
                # If there are uncommitted files, set it to red.
        # If we're not in a git repo, then display nothing

# This is what actually sets our PS1. The ${git prompt} is what will display our git status.
PS1="\[\e[0;36m\]┌─\[\e[1;37m\][\u@\h]\[\e[0m\]\[\e[0;36m\]─\[\e[0;93m\](\w)${git_prompt} \n\[\e[0;36m\]└─\[\e[1;32m\][\A]\[\e[0m\]\$(if [[ \$? == 0 ]]; then echo \"\[\033[0;32m\]$\"; else echo \"\[\033[0;31m\]$\"; fi)\[\033[00m\] "

# PROMPT_COMMAND is run just before the PS1 is printed. We've set it to run our bash_prompt function.

The key to all of this working is the PROMPT_COMMAND. Bash will execute whatever the PROMPT_COMMAND is set to just before it prints the PS1, in other words, every time you open a new shell, execute any command yourself, or even just hit the enter key. With the above in your .bashrc, Bash will check to see if the present working directory is a git repo or not. If it is, it will check to see if there are uncommitted files. If there are no uncommitted files, it will append the branch name in green after the working directory in our PS1. If there are uncommitted files, it will append the branch name in red. If the working directory isn’t a git repo, then it will print nothing after the working directory in the PS1.

Oh, I almost forgot to mention. There’s another neat little trick in here that I really appreciate:

\$(if [[ \$? == 0 ]]; then echo \"\[\033[0;32m\]$\"; else echo \"\[\033[0;31m\]$\"; fi)\[\033[00m\]

This bit will check the exit code of last executed command. If it’s zero (successful), then the $ will be green. If the command failed, the $ will be red. Can be handy for commands that don’t tell you whether they succeeded or not.

Screenshot from 2015-12-11 18-18-32

There are of course, other ways to implement something like this. A quick google search will turn up plenty of guides for doing it differently. But ultimately, this is the method that works the best for me. It’s also quite versatile. Having PROMPT_COMMAND call a function that sets the PS1 allows you to do all kinds of conditionals on what your PS1 will look like. You could have different colors for different times of the day, A status indicator for whether you’re connected over ssh or through a local terminal emulator (useful if you have the same .bashrc on all of your remote machines), an indicator for whether you’re connected to your vpn or not. Anything you can do with a bash script, you can put in your PS1.