Check Out the Packt Free Learning Campaign!

Packt is running a cool promotion right now where you can get a different free ebook each day until a March 5. Check it out!

My Book is Available!

My book, Learning SaltStack, is available for purchase!

It's available in paperback, as well as for kindle from Amazon.

You can also buy it directly from Packt.

Hope you enjoy it!

Mitigating GHOST with SaltStack

My coworker CR wrote up a great guide to mitigating the new GHOST vulnerability with SaltStack.

Check it out here: Mitigating GHOST with Salt

If you haven't already checked out SaltStack, I highly recommend it! You'll never have to manually patch all of your machines again!

The Problem with the Hobbit Movies

I was catching up on my RSS feeds and I found [this review of the last Hobbit movie by Ars Technica][1]. Sums up my feelings perfectly:

There's one big thing that doomed these movies from the outset—the fiscally smart but artistically bankrupt decision to make a single, shortish children's novel into three feature-length prequel films.

Artistically bankrupt. Perfect way to put it.

What these movies desperately need are boundaries, reasons to condense scenes or cut them out entirely instead of reasons to pile on more. Chopping these down into a pair of two-and-a-half hour movies would drastically improve the pacing even if you didn't address the characterization or the tone issues. You could leave around three hours of slow-motion action sequences, goblin chases, and Radagast the Brown on the cutting room floor! Sounds great, doesn't it?

Couldn't have said it better myself.

Fix Linode Manager Repeated Log-out (Force IPv4)

Recently I've been having issues with Linode Manager repeatedly logging me out every few requests. I figured this was related to ipv4/ipv6 switching, because sometimes the logout would also trigger a new IP whitelist request, which would sometimes be ipv4, and sometimes be ipv6.

After a little googling, I found this twitter conversation:

Turns out I'm not the only one experiencing this issue. So I decided to set up dnsmasq as one of the replies mentioned, and force Linode to a single ipv4 address.

Note that these instructions are for OSX (and were tested on Yosemite, 10.10).

First, I installed dnsmasq via Homebrew:

brew install dnsmasq

Then, I followed the homebrew instructions to install dnsmasq as a service to start on startup:

sudo cp -fv /usr/local/opt/dnsmasq/*.plist /Library/LaunchDaemons
sudo chown root /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist

Now, before we actually start the service, let's get our resolver in place. OSX allows us to define resolve data for specific addresses using files in /etc/resolver/. Here is my /etc/resolver/manager.linode.com:

nameserver 127.0.0.1

Basically, we're telling the operating system to use our local DNS server (provided by dnsmasq) for lookups for manager.linode.com.

We also need to configure dnsmasq to force manager.linode.com to a specific address. First, we need an IPv4 address to work with:

# dscacheutil -q host -a name manager.linode.com
name: manager.linode.com
ipv6_address: 2600:3c00::14
ipv6_address: 2600:3c00::34
ipv6_address: 2600:3c00::24

name: manager.linode.com
ip_address: 69.164.200.204
ip_address: 72.14.191.204
ip_address: 72.14.180.204

Then, copy the example configuration into place:

cp /usr/local/opt/dnsmasq/dnsmasq.conf.example /usr/local/etc/dnsmasq.conf

and edit /usr/local/etc/dnsmasq.conf, adding this line:

address=/manager.linode.com/72.14.180.204

Now, start dnsmasq:

sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist

Assuming you did everything right, you should only see one address when you query again:

dscacheutil -q host -a name manager.linode.com
name: manager.linode.com
ip_address: 72.14.180.204

I haven't done much on Linode since implementing this fix, but haven't had it log me out erroneously once yet.

If you have improvements or run into issues, please leave a comment below!

Blog Auto-Publish with Dropbox

This weekend I moved my blog over to Pelican from Octopress. I've been very happy with this decision.

But I decided I wanted to go a step further, and set up autopublish. I knew it could be easily done with a git hook, but I wanted to be able to easily blog from my iOS devices as well, so I decided to go with Dropbox instead.

Getting Dropbox

First, I needed to install Dropbox on my machine. Dropbox provides an easy one-liner:

cd ~ && wget -O - "https://www.dropbox.com/download?plat=lnx.x86_64" | tar xzf -

Now, when I first tried to start up dropbox, it gave me a cryptic error, which I traced back to not having X11 libraries installed. Turns out I just needed to unset my DISPLAY variable:

unset DISPLAY

Now Dropbox will start properly:

~/.dropbox-dist/dropboxd

Follow the instructions to get Dropbox authorized on your server, then once you see the success message, exit using ctrl-c.

Configure Dropbox as System Service

Next we need to create an init script for Dropbox. I found an example here. Here's the Ubuntu/Debian script:

#!/bin/sh
#dropbox service
DROPBOX_USERS="user1 user2"

DAEMON=.dropbox-dist/dropboxd

start() {
   echo "Starting dropbox..."
   for dbuser in $DROPBOX_USERS; do
       HOMEDIR=`getent passwd $dbuser | cut -d: -f6`
       if [ -x $HOMEDIR/$DAEMON ]; then
           HOME="$HOMEDIR" start-stop-daemon -b -o -c $dbuser -S -u $dbuser -x $HOMEDIR/$DAEMON
       fi
   done
}

stop() {
   echo "Stopping dropbox..."
   for dbuser in $DROPBOX_USERS; do
       HOMEDIR=`getent passwd $dbuser | cut -d: -f6`
       if [ -x $HOMEDIR/$DAEMON ]; then
           start-stop-daemon -o -c $dbuser -K -u $dbuser -x $HOMEDIR/$DAEMON
       fi
   done
}

status() {
   for dbuser in $DROPBOX_USERS; do
       dbpid=`pgrep -u $dbuser dropbox`
       if [ -z $dbpid ] ; then
           echo "dropboxd for USER $dbuser: not running."
       else
           echo "dropboxd for USER $dbuser: running (pid $dbpid)"
       fi
   done
}

case "$1" in

   start)
       start
       ;;
   stop)
       stop
       ;;
   restart|reload|force-reload)
       stop
       start
       ;;
   status)
       status
       ;;
   *)
       echo "Usage: /etc/init.d/dropbox {start|stop|reload|force-reload|restart|status}"
       exit 1

esac

exit 0

Note that when I pulled down that script originally, it had a typo. The DAEMON line near the top of the file should be .dropbox-dist/dropboxd -- they left off the trailing d in the version I downloaded.

Place this script in /etc/init.d/dropbox. Replace the DROPBOX_USERS setting with a space-separate list of users for which you want Dropbox running. Then, make the file executable and set it to execute on startup:

sudo chmod +x /etc/init.d/dropbox
sudo update-rc.d dropbox defaults

Now, start Dropbox again, as a service:

sudo service dropbox start

Selective Sync (Optional)

I have a very large Dropbox folder, and so only want to sync the Blogs folder from my Dropbox account.

I downloaded the CLI script mentioned on that installation page:

wget https://linux.dropbox.com/packages/dropbox.py

Then, with Dropbox running, I excluded all the directories within the Dropbox folder, then removed the Blogs folder from the resulting exclusion list:

./dropbox.py exclude add ~/Dropbox/*
./dropbox.py exclude remove ~/Dropbox/blogs

Perfect, now I have only my blogs syncing to my server's dropbox folder.

Autopublish: The Watcher Script

The automagic regeneration of my blog I modified from this post.

I'm going to assume you have a working Pelican setup. Assuming you used the Pelican quickstart, you should have both a pelicanconf.py and a publishconf.py. The publishconf.py is going to be what we use.

First, you must modify your publishconf.py file such that it can operate from any directory, rather than relying on relative paths. Thus, you should add your blog's absolute directory to the Python path inside of that script. Here is my publishconf.py:

#!/usr/bin/env python
# -*- coding: utf-8 -*- #
from __future__ import unicode_literals

# This file is only used if you use `make publish` or
# explicitly specify it as your config file.

import os
import sys

#sys.path.append(os.curdir)
# This is the directory where your pelican's
# configuration files reside
pelicanpath = '/home/basepi/Dropbox/Blogs/blog.basepi.net'
sys.path.append(pelicanpath)

sys.path.append(os.curdir)
from pelicanconf import *

SITEURL = 'http://blog.basepi.net'
RELATIVE_URLS = False

FEED_ALL_ATOM = None
CATEGORY_FEED_ATOM = None

DELETE_OUTPUT_DIRECTORY = True

These are the key lines:

pelicanpath = '/home/basepi/Dropbox/Blogs/blog.basepi.net'
sys.path.append(pelicanpath)

Now no matter what my current working directory is, the publishconf.py will be able to find the files it needs to operate.

Next, I created a publish script, publish.sh:

#!/bin/bash

PELICAN=/usr/bin/pelican
CONTENT=/home/basepi/Dropbox/Blogs/blog.basepi.net/content
OUTPUT=/home/basepi/Dropbox/Blogs/blog.basepi.net/output
SETTINGS=/home/basepi/Dropbox/Blogs/blog.basepi.net/publishconf.py

rm -rf /home/basepi/Dropbox/Blogs/blog.basepi.net/output/*
$PELICAN $CONTENT -o $OUTPUT -s $SETTINGS || exit $?
rsync -r --delete /home/basepi/Dropbox/Blogs/blog.basepi.net/output/ /var/www/blog.basepi.net

Note the use of || exit $?. This will cause the script to exit if the retcode of the pelican command is non-zero. I don't want to publish my blog if there are problems.

Make this script executable, and then run it to test that things are working.

The final step is to set up the watcher script which will run our publish script on changes. For this purpose we will be using this watcher script.

This script, conveniently, is ready to be used as an init script. Take the script and put it at /etc/init.d/watcher. Make it executable:

sudo chmod +x /etc/init.d/watcher

Now, we need to create the configuration file for the watcher. This file is at /etc/watcher.ini:

[DEFAULT]

; where to store output
logfile=/var/log/watcher.log

; where to save the PID file
pidfile=/var/run/watcher.pid

[job1]
watch=/home/basepi/Dropbox/Blogs/blog.basepi.net/content
events=modify,create,delete,move
excluded=
recursive=true
autoadd=true
command=/home/basepi/Dropbox/Blogs/blog.basepi.net/publish.sh

Now we just need to start the watcher:

sudo service watcher start

You can tail the log to see if it's working (change a file to trigger it):

tail -f /var/log/watcher.log

If everything is in order, just have the watcher start on boot:

sudo update-rc.d watcher defaults

And you're done! Now, any time you change the content of your blog, it will be automatically re-built and published for you!

Let me know what you think in the comments. Or hit me up on Twitter!

Tagged , , , ,

Low Friction

It's been a long time.

...again.

I thought that I had a pretty low-friction setup with my new blog on Octopress. However, that was not the case. This morning I decided I needed to get my blog back up. There have been a few times in the last couple of years that I wished I had it available. However, I didn't have any of the dependencies set up on my new laptop. So I set out to get ruby installed and ready to generate my blog again.

After an hour of fighting rbenv and bundle, I decided it was finally time to take the plunge, and switch to a Python-based tool.

I installed Pelican, and had it generating my new site from the default skeleton in a few minutes. Granted, I've had to take some more time choosing a theme and porting my content over. But grand total it's only taken me an hour or two of tinkering, and should reduce my blogging friction substantially, both on new machines and on existing setups.

I did port over most of the content from my old blog. I may delete some of it going forward, mostly out of embarassment.

I lost my old disqus comments -- since there was only one comment on my old blog, I decided it wasn't worth the potential hassle of making sure it translated cleanly.

Additionally, the RSS feed is new, so you'll have to resubscribe.

So here we are, on the newest edition of blog.basepi.net. Hope you like it.

I'm Back!

Well, at long last I got around to re-installing Ruby on my machine, updated Octopress, and got my blogs settled. I'm back!

So what's been going on in the interim? Let's hit the top two:

  • I graduated Magna Cum Laude from the University of Utah with a BS in Computer Science.
  • I switched jobs -- I now work for Salt Stack, Inc, making awesome open source software.

A lot has changed, and I hope to have much more to blog about now that I'm more involved in the open source community. Feel free to throw me feedback! I don't pretend to be an awesome blogger. =)

Why I switched to Octopress

Update, Nov 2014: Since I wrote this blog post, I have ditched Jekyll and Octopress (mostly because of the pain of setting up Ruby, not because of those pieces of software themselves). This blog is still static, but is now generated using Pelican, a Python project.

The Problem

Last week I received an e-mail from the RSA Anti-Fraud Command Center. It related to my personal blog:

It appears that your website cmyers.net has been hacked by a fraudster. It is now hosting a phishing attack against RBC. Please remove the fraudulent folders/files as soon as possible and secure your website as it has been compromised. Please note that it is possible that the fraudulent content is embedded in your website's legitimate files.

Great.

It turns out the claim was in fact true. There were new files in my wp-admin folder for my wordpress install. When I loaded these files in a browser, it looked like the home page for a bank.

I had been hacked.

Turns out it's actually quite a common thing. WordPress is a common (and apparently quite easy) target for these types of hacks. It comes down to a combination of it's popularity, lack of really security-centric design, and the fact that it's written in PHP.

I considered a few options. Do I take the time to properly harden my PHP5 install and reinstall wordpress? Or do I change systems?

Enter Jekyll

My friend Andrew generates his blog using jekyll. Jekyll is a "simple, blog aware, static site generator." It's super-cool, check it out. However, unlike WordPress, it doesn't have a bunch of built-in themes, or even a theme directory that I could find. You have to write your own CSS and HTML templates, which it uses to generate the site. But it generates an almost completely static site -- the exception would be if you build in functionality for Disqus comments or put your Twitter roll in the sidebar.

If I was going to switch systems, static is what I was looking for. The resulting site is much faster than a WordPress site, and much more secure. But I didn't have the time, knowledge, or creativity to create a theme from scratch, and porting my theme from WordPress would be a many hour project.

Enter Octopress

Then I received a tweet from my friend Julio that said to check out Octopress. It's built on top of Jekyll with built-in support for great syntax highlighting, Disqus comments, social integration -- everything I was looking for. And a great default theme, which I could use as a jumping point for my own. I was sold.

The rest is history. I'll spell out the details in my next post.