<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Blog on Technical Blog</title>
    <link>https://nathanielhoag.com/blog/</link>
    <description>Recent content in Blog on Technical Blog</description>
    <image>
      <title>Technical Blog</title>
      <url>https://nathanielhoag.com/images/avatar.jpg</url>
      <link>https://nathanielhoag.com/images/avatar.jpg</link>
    </image>
    <generator>Hugo -- gohugo.io</generator>
    <lastBuildDate>Sat, 02 Apr 2022 16:42:47 -0400</lastBuildDate><atom:link href="https://nathanielhoag.com/blog/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Interactive Runbook</title>
      <link>https://nathanielhoag.com/blog/2022/interactive-runbook/</link>
      <pubDate>Sat, 02 Apr 2022 16:42:47 -0400</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2022/interactive-runbook/</guid>
      <description>Recently, I&amp;rsquo;ve been on a search for interactive runbooks. My team has several use-cases for such a tool including:
repeatable, runnable procedures a REST book that can be used to query and validate APIs to document complex API integrations First, a bit about my team. We&amp;rsquo;re globally-distributed, and maintain a growing number of microservices built mostly using Mulesoft, but with some AWS services, Drupal, and Symfony in the mix. We&amp;rsquo;ve been transitioning to Mulesoft and API-led strategy from a mostly PHP-based fleet of apps.</description>
    </item>
    
    <item>
      <title>Making a Go Command Line Tool from an Open Api Spec</title>
      <link>https://nathanielhoag.com/blog/2022/go-cli-open-api/</link>
      <pubDate>Sun, 06 Mar 2022 13:28:50 -0500</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2022/go-cli-open-api/</guid>
      <description>I recently assembled a CLI app using Go and Open API and wanted to share some of the process.
Summary of Steps Acquire an Open API spec Generate a Go API client using OpenAPI Generator Generate a Go CLI using Cobra Integrate the API Client into the CLI Build Detail I wanted to automate pulling search results from Sumo Logic, and took a look at the Search Job API. Sumo Logic provides a pretty robust Open API spec for most of the APIs they offer, but unfortunately Search Job API is not covered.</description>
    </item>
    
    <item>
      <title>Laracon Online 2018 Recap</title>
      <link>https://nathanielhoag.com/blog/2018/laracon-online-2018-recap/</link>
      <pubDate>Thu, 08 Feb 2018 21:40:37 -0500</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2018/laracon-online-2018-recap/</guid>
      <description>I recently attended Laracon Online 2018 and got a lot out of it! I happened to see a tweet about early bird tickets in January and couldn&amp;rsquo;t pass up the opportunity. I&amp;rsquo;ve admittedly been sheltered in Drupal/Symfony over the last several years, and it was a bit of a shock to see the popularity and rich features of Laravel (like Rails for PHP). The presenters were knowledgable, practiced, and engaging. The format flowed well and was expertly M.</description>
    </item>
    
    <item>
      <title>Saved by Layered Docker Images</title>
      <link>https://nathanielhoag.com/blog/2018/saved-by-layered-docker-images/</link>
      <pubDate>Sun, 04 Feb 2018 22:18:38 -0500</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2018/saved-by-layered-docker-images/</guid>
      <description>Several years ago, I created a fleet of bots that pull data from one API and post to another API. Over the years, the bots have needed various interventions to get them back up and running, but I&amp;rsquo;ve shied away from upgrading underlying technologies. Thankfully, when I put these bots together, I used a system of layered Docker builds. I didn&amp;rsquo;t remember having done this, but after a quick review it became clear that this update was going to be easy.</description>
    </item>
    
    <item>
      <title>New Year, Shiny Dots</title>
      <link>https://nathanielhoag.com/blog/2018/new-year-shiny-dots/</link>
      <pubDate>Sun, 21 Jan 2018 14:52:07 -0500</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2018/new-year-shiny-dots/</guid>
      <description>Over the last few weeks I&amp;rsquo;ve been digging away on my dotfiles and figured I&amp;rsquo;d write up the interesting aspects of the various decisions, methods and changes involved. The high-level overview is that I moved to a bare Git repository structure, added an installer script and some light multi-OS support, and added automated linting and a few basic tests.
After using a symlinked dotfiles system for a couple of years, I got curious as to whether there might be decent alternatives.</description>
    </item>
    
    <item>
      <title>Debugging Drupal With Docker</title>
      <link>https://nathanielhoag.com/blog/2017/debugging-drupal-with-docker/</link>
      <pubDate>Wed, 27 Dec 2017 21:45:55 -0500</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2017/debugging-drupal-with-docker/</guid>
      <description>This week I had occasion to help resolve a customer support case. As part of troubleshooting, I stood up a local copy of the site using Docker4Drupal. This worked out really well, and I&amp;rsquo;d like to take a moment to discuss some of the benefits.
It initially took a little time to configure the site with Docker4Drupal, and to get XDebug linked up. But I&amp;rsquo;m sure that if I were doing this regularly, this would have been no more than a few minutes.</description>
    </item>
    
    <item>
      <title>Defining Tmux Sessions</title>
      <link>https://nathanielhoag.com/blog/2017/defining-tmux-sessions/</link>
      <pubDate>Fri, 22 Dec 2017 22:04:53 -0500</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2017/defining-tmux-sessions/</guid>
      <description>I&amp;rsquo;m still kicking with tmux, and have rounded a few rough edges since the last installment. One area of advancement has been learning about defining default sessions. To be clear, this doesn&amp;rsquo;t entail attaching to indefinitely running background sessions. This is firing up an on-demand pre-defined session.
In researching support for this, I found teamocil and tmuxinator. These look interesting, but ultimately didn&amp;rsquo;t appeal to me since they are Ruby gems that introduce additional dependencies.</description>
    </item>
    
    <item>
      <title>macOS: Simple PHP Switcher</title>
      <link>https://nathanielhoag.com/blog/2017/macos-simple-php-switcher/</link>
      <pubDate>Mon, 11 Dec 2017 22:14:54 -0500</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2017/macos-simple-php-switcher/</guid>
      <description>Recently I&amp;rsquo;ve been working with PHP applications in varying states of modernity/antiquity, and very regularly have to switch the current PHP version to accomodate the PHP flavors of the day. Homebrew un/link commands are super simple and at this point all I want is to be able to switch the PHP version with a single command. With a little bit of searching, I found a script that comes pretty close to what I need:</description>
    </item>
    
    <item>
      <title>Wading Into Tmux</title>
      <link>https://nathanielhoag.com/blog/2017/wading-into-tmux/</link>
      <pubDate>Sat, 02 Dec 2017 13:58:54 -0500</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2017/wading-into-tmux/</guid>
      <description>During a recent group debugging session at work, I was reminded about tmux. I hadn&amp;rsquo;t really used it outside of a couple of brief experiments that were little more than opening the application (and then struggling to kill it), so on this occasion I used screen. Whatever the reason, apparently now is the time for tmux! In this post, I&amp;rsquo;ll cover a few of the impediments and blessings encountered so far, since I seem to have gotten the good kind of tmux bug.</description>
    </item>
    
    <item>
      <title>Hugo Migration</title>
      <link>https://nathanielhoag.com/blog/2017/11/24/hugo-migration/</link>
      <pubDate>Fri, 24 Nov 2017 21:20:14 -0500</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2017/11/24/hugo-migration/</guid>
      <description>I haven&amp;rsquo;t been very active on here lately, but hopefully that will change in the coming months. As a part of reinvigorating my technical writing and removing barriers to writing new blog posts, I converted the generator for this site from Jekyll/Octopress to Hugo.
The conversion process was smooth and now the site is generated in much less than a second. Probably the biggest benefit is that dependency concerns to build and manage the site have dropped off a cliff.</description>
    </item>
    
    <item>
      <title>Protecting Git Branches</title>
      <link>https://nathanielhoag.com/blog/2016/09/15/protecting-git-branches/</link>
      <pubDate>Thu, 15 Sep 2016 20:57:37 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2016/09/15/protecting-git-branches/</guid>
      <description>I&amp;rsquo;ve been thinking about the vulnerability of the primary Git branch for the last several weeks. Mostly out of paranoia about destroying a critical application. I added protective measures to my local clones on important projects and was content in thinking that I was now safe. But today I was reminded that this is only a small part of protecting a collaborative project.
Here&amp;rsquo;s what happened:
User 1 made a commit on master and pushed to origin User 2 fixed a bad merge on branch feature and ran git push --force User 1 made a tag directly on the remote and deployed to Production User 1 saw the new tag in production, but the new commit was missing The problem was introduced with the git push --force.</description>
    </item>
    
    <item>
      <title>Exciting Dotfile Enhancements</title>
      <link>https://nathanielhoag.com/blog/2016/09/11/exciting-dotfile-enhancements/</link>
      <pubDate>Sun, 11 Sep 2016 21:09:53 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2016/09/11/exciting-dotfile-enhancements/</guid>
      <description>Over the weekend, I&amp;rsquo;ve been cleaning up, organizing and improving my dotfiles. Below are a couple of things that I&amp;rsquo;m most excited about.
Zsh in Vim Mode I&amp;rsquo;ve been using zsh for a while, but only recently starting using zsh in Vim mode. One thing that&amp;rsquo;s been sorely missing is moving by word in INSERT mode. I got this working by adding the following to ~/.zshrc:
bindkey &amp;#39;^b&amp;#39; backward-word bindkey &amp;#39;^w&amp;#39; forward-word With this config loaded, I can move forward by word boundaries with Control-w and backward with Control-b.</description>
    </item>
    
    <item>
      <title>Execute Multiple Commands in Vim</title>
      <link>https://nathanielhoag.com/blog/2016/09/08/execute-multiple-commands-in-vim/</link>
      <pubDate>Thu, 08 Sep 2016 21:53:20 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2016/09/08/execute-multiple-commands-in-vim/</guid>
      <description>Today I needed to perform multiple transforms on a chunk of text in a file and found a nice solution in Vim! Initially I was thinking about VISUAL mode in Vim and chaining transforms the way I would do with sed (i.e. s/one/two/g;s/^/ /;s/$/,/). It turns out this doesn&amp;rsquo;t exactly work in Vim, but it&amp;rsquo;s not too far off the mark.
The following syntax works in Vim NORMAL mode:
:%s/^/ / | %s/string/replace/g | %s/$/,/ And in VISUAL mode, the sytax is slightly different.</description>
    </item>
    
    <item>
      <title>Signing Commits in Git</title>
      <link>https://nathanielhoag.com/blog/2016/09/05/signing-commits-in-git/</link>
      <pubDate>Mon, 05 Sep 2016 15:45:22 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2016/09/05/signing-commits-in-git/</guid>
      <description>There are some great resources for getting set up with signing Git commits and tags with a GPG key:
https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work https://help.github.com/articles/signing-commits-using-gpg/ After following instructions, I still got the following error:
error: gpg failed to sign the data fatal: failed to write commit object Below is a sequence of commands that got everything working properly:
# Assumes homebrew and existing key-pair brew install pinentry-mac # Get the secret key value gpg2 --list-secret-keys | grep ^sec git config --global user.</description>
    </item>
    
    <item>
      <title>Helpful Tidbits</title>
      <link>https://nathanielhoag.com/blog/2016/09/04/helpful-tidbits/</link>
      <pubDate>Sun, 04 Sep 2016 13:51:59 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2016/09/04/helpful-tidbits/</guid>
      <description>Below is a smattering of helpful tidbits from the last several months.
less Case-insensitive search: Add -i to your LESS environment variable
Drupal Hide fieldgroups with all child fields: field_group_hide_field_groups($form, array(&#39;field_group_name&#39;));
OS X &amp;ldquo;Disable&amp;rdquo; the dock by setting a long autohide delay: defaults write com.apple.dock autohide-delay -float 5
Clear the clipboard: pbcopy &amp;lt;/dev/null
wc Consider the following:
# &amp;#39;HELLO&amp;#39; + newline echo HELLO | wc -m 6 # Just &amp;#39;HELLO&amp;#39; echo -n HELLO | wc -m 5 Google Hangout Toggle camera: ⌘ + e Toggle microphone: ⌘ + d Much better than using a mouse!</description>
    </item>
    
    <item>
      <title>Repo Bloat: Finding Large Objects</title>
      <link>https://nathanielhoag.com/blog/2015/11/17/repo-bloat-finding-large-objects/</link>
      <pubDate>Tue, 17 Nov 2015 21:26:11 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2015/11/17/repo-bloat-finding-large-objects/</guid>
      <description>I&amp;rsquo;ve written previously about trimming the fat on bloated Git repositories. Here I&amp;rsquo;ll present a convenient method for listing the largest objects in a human-friendly format.
The first step in finding the largest objects is to list all objects. We can do this with verify-pack:
$ git verify-pack -v .git/objects/pack/pack-{HASH}.idx 8306276cde4f3cff8cbe5598fd98bf10146da262 commit 254 170 9725 4677b7c11924cefa62393f0e3e7db6c06787815e tree 30 63 9895 1 08ce30d6550bed7725c399026d91fce24c86a79f 5062bde76952965ff5c473a7de0ae102b4d2c9f3 tree 1122 944 9958 1c1ef555c77ee527c95ca093f251313a6418c158 blob 10 19 10902 non delta: 15175 objects chain length = 1: 1672 objects chain length = 31: 10 objects chain length = 32: 4 objects .</description>
    </item>
    
    <item>
      <title>Wrapping OpenSSL for Simplified Usage</title>
      <link>https://nathanielhoag.com/blog/2015/10/25/wrapping-openssl-for-simplified-usage/</link>
      <pubDate>Sun, 25 Oct 2015 15:26:00 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2015/10/25/wrapping-openssl-for-simplified-usage/</guid>
      <description>I routinely inspect live SSL certificates to validate domain coverage. While working directly with openssl is not necessarily painful, I wanted a tool that could be used to return a simple list of domains without the extra output and without the terminal hang. Below is an example of retrieving the SSL cert for google.com with openssl s_client:
$ openssl s_client -showcerts -connect google.com:443 CONNECTED(00000003) depth=2 /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA verify error:num=20:unable to get local issuer certificate verify return:0 --- Certificate chain 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.</description>
    </item>
    
    <item>
      <title>Getting Complex With Remote Bash</title>
      <link>https://nathanielhoag.com/blog/2015/10/25/getting-complex-with-remote-bash/</link>
      <pubDate>Sun, 25 Oct 2015 13:42:26 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2015/10/25/getting-complex-with-remote-bash/</guid>
      <description>Over the past few months, I&amp;rsquo;ve found and created a bunch of fun new scripting tricks and tools. Below are two somewhat related items that helped to unlock new possibilities for me in remote bash automation. The first is a Perl one-liner that allows filtering access logs by start and end times. The second is a method for executing complex commands remotely via ssh without all those intricate escapes.
As context for the Perl log filter, my team at work regularly performs Load Test Analyses.</description>
    </item>
    
    <item>
      <title>Many and Varied Ramblings From the First Half of 2015</title>
      <link>https://nathanielhoag.com/blog/2015/06/29/many-and-varied-ramblings-from-the-first-half-of-2015/</link>
      <pubDate>Mon, 29 Jun 2015 11:42:27 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2015/06/29/many-and-varied-ramblings-from-the-first-half-of-2015/</guid>
      <description>The last six months have been very full with the arrival of our first baby and all the prep work and new responsibilities that go with being a new parent. Here and there I&amp;rsquo;ve managed to squeeze in little hobby projects. Much to my astonishment, I also won the !!Con attendance lottery(!!), and had an amazing few days in NYC.
!!Con !!Con was an extremely fun conference, and I consider myself so lucky to have won the attendance lottery.</description>
    </item>
    
    <item>
      <title>Hubot With a Redis Brain on Docker</title>
      <link>https://nathanielhoag.com/blog/2015/01/10/hubot-with-a-redis-brain-on-docker/</link>
      <pubDate>Sat, 10 Jan 2015 15:59:18 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2015/01/10/hubot-with-a-redis-brain-on-docker/</guid>
      <description>I&amp;rsquo;ve written previously about deploying Hubot on Docker, deploying patched Hubot scripts, and bechmarking mass inserts with a Redis Docker container. In this post, I&amp;rsquo;ll cover how to link a Hubot Docker container to a Redis Docker container to equip Hubot with persistent memory.
As an overview we&amp;rsquo;re going to:
Spin up a Redis Docker container with a host directory mounted as a data volume Spin up a linked Hubot Docker container that will use Redis as a persistent brain For my most recent post on Redis mass inserts, I created a basic Redis Docker image that satisfies all of the requirements to be used as a Hubot Redis brain.</description>
    </item>
    
    <item>
      <title>Redis Tangent</title>
      <link>https://nathanielhoag.com/blog/2015/01/03/redis-tangent/</link>
      <pubDate>Sat, 03 Jan 2015 18:41:01 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2015/01/03/redis-tangent/</guid>
      <description>A brief odyssey into Redis with mass inserts, sweet bash commands, and intrigue.</description>
    </item>
    
    <item>
      <title>Deploying a Patched Hubot Maps Script</title>
      <link>https://nathanielhoag.com/blog/2015/01/02/deploying-a-patched-hubot-maps-script/</link>
      <pubDate>Fri, 02 Jan 2015 13:40:48 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2015/01/02/deploying-a-patched-hubot-maps-script/</guid>
      <description>In deploying Hubot for the first time, you may encounter the following error:
ERROR ReferenceError: fillAddress is not defined at TextListener.callback (/path/to/bot/node_modules/hubot-maps/src/maps.coffee:58:16, &amp;lt;js&amp;gt;:57:18) &amp;lt;/truncated&amp;gt; At the time of this writing, running a grep in the Hubot Maps source code shows a single instance of the function and no function definition:
grep -rn fillAddress . ./src/maps.coffee:58: location = fillAddress(msg.match[3]) Stepping back a level to grep all of Hubot and scripts yields the same result as above.</description>
    </item>
    
    <item>
      <title>A Dockerized and Slack-integrated Hubot</title>
      <link>https://nathanielhoag.com/blog/2014/12/07/a-dockerized-slack-integrated-hubot/</link>
      <pubDate>Sun, 07 Dec 2014 14:06:01 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2014/12/07/a-dockerized-slack-integrated-hubot/</guid>
      <description>A little over a year ago, I wrote a quick blog post about deploying Hubot with Docker. A lot has changed with Hubot and Docker since that time, so I decided to revisit the build.
The new implementation I whipped up consists of three main components:
Yeoman-generated Hubot Base Docker image Dockerfile for configuring Hubot The Hubot &amp;lsquo;Getting Started&amp;rsquo; instructions walk us through generating a deployable Hubot with Yeoman. Once generated, the code can be stashed away somewhere until we&amp;rsquo;re ready to pull it into a Docker image.</description>
    </item>
    
    <item>
      <title>Moving Away From Evernote</title>
      <link>https://nathanielhoag.com/blog/2014/11/29/moving-away-from-evernote/</link>
      <pubDate>Sat, 29 Nov 2014 21:26:34 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2014/11/29/moving-away-from-evernote/</guid>
      <description>Update: It turns out I have multiple accounts and was reviewing a secondary account I&amp;rsquo;d forgotten about and had barely used. Still, it&amp;rsquo;s a useful exercise to consider the worst case of data loss in a blackbox cloud system. Digging deeper into the topic of efficient and distributed notes, I found that Brett Terpstra has put an incredible amount of time and effort into evolving this space. Nothing yet feels fully baked, but tools such as Popclip (with awesome extensions), nvalt, Bullseye, and GistBox provide a lot of interesting avenues.</description>
    </item>
    
    <item>
      <title>Flame Graphs Show Why Fast 404 Is Important for Drupal Performance</title>
      <link>https://nathanielhoag.com/blog/2014/11/23/flamegraphs-show-why-fast-404-is-important-for-drupal-performance/</link>
      <pubDate>Sun, 23 Nov 2014 18:03:26 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2014/11/23/flamegraphs-show-why-fast-404-is-important-for-drupal-performance/</guid>
      <description>The Fast 404 Drupal contributed module project page provides a lot of context for why 404s are expensive in Drupal:
&amp;hellip; On an &amp;lsquo;average&amp;rsquo; site with an &amp;lsquo;average&amp;rsquo; module load, you can be looking at 60-100MB of memory being consumed on your server to deliver a 404. Consider a page with a bad .gif link and a missing .css file. That page will generate 2 404s along with the actual load of the page.</description>
    </item>
    
    <item>
      <title>Moving (Mostly) From Octopress to Straight Jekyll</title>
      <link>https://nathanielhoag.com/blog/2014/11/16/moving-mostly-from-octopress-to-straight-jekyll/</link>
      <pubDate>Sun, 16 Nov 2014 11:12:41 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2014/11/16/moving-mostly-from-octopress-to-straight-jekyll/</guid>
      <description>Over the last couple of weekends I converted my blog from Octopress to straight Jekyll (still hosting on S3). There wasn&amp;rsquo;t any particular reason behind the move, but I was curious to know more about the differences between the two platforms, wanted to try out a new theme, and just generally enjoy these types of migrations.
Overall, there aren&amp;rsquo;t many differences between the two platforms. As many have stated before, the major difference is that Octopress comes with more functionality out of the box, but at the cost of increased complexity.</description>
    </item>
    
    <item>
      <title>Automate SSH Key Generation and Deployment</title>
      <link>https://nathanielhoag.com/blog/2014/05/26/automate-ssh-key-generation-and-deployment/</link>
      <pubDate>Mon, 26 May 2014 21:14:07 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2014/05/26/automate-ssh-key-generation-and-deployment/</guid>
      <description>I recently pieced together a bash wrapper script to create, add, and delete an ssh key for temporary use in performing remote tasks over ssh. The processes outlined here assume cURL is available, and that the remote service you wish to connect to has API methods for ssh key handling.
Automating the process of generating and deleting a local ssh key is the easy part. Here&amp;rsquo;s one way to create a key:</description>
    </item>
    
    <item>
      <title>Automating Drupal Module Deployment with Ruby</title>
      <link>https://nathanielhoag.com/blog/2014/05/21/automating-drupal-module-deployment-with-ruby/</link>
      <pubDate>Wed, 21 May 2014 20:56:46 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2014/05/21/automating-drupal-module-deployment-with-ruby/</guid>
      <description>After building a bash script to automate Drupal module deployments, I figured it might be worthwhile to convert the script over to Ruby. I decided to spin up the new version as a Ruby gem leveraging the Thor CLI Framework.
Having already worked out many of the mechanics of deploying Drupal contrib modules in the previous bash script, I was able to dive right into coding. I started by fleshing out the command options and then moved into scripting the functionality.</description>
    </item>
    
    <item>
      <title>Automating Drupal Module Deployment with Bash</title>
      <link>https://nathanielhoag.com/blog/2014/04/26/automating-drupal-module-deployment-with-bash/</link>
      <pubDate>Sat, 26 Apr 2014 22:48:53 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2014/04/26/automating-drupal-module-deployment-with-bash/</guid>
      <description>Part of the process of migrating new customers to Acquia Hosting involves adding (or verifying the presence of) three Drupal modules:
Acquia Network Connector: get status and recommendations from Acquia Insight Fast 404: reduce the cost of 404s Memcache API and Integration: improve performance by moving cache data into memory Manual?! Awe shucks&amp;hellip; Verifying, adding, and committing these modules manually generally takes about five to ten minutes and can be error-prone.</description>
    </item>
    
    <item>
      <title>Scripted GitHub GeoJSON Gists</title>
      <link>https://nathanielhoag.com/blog/2014/04/26/scripted-github-geojson-gists/</link>
      <pubDate>Sat, 26 Apr 2014 21:58:34 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2014/04/26/scripted-github-geojson-gists/</guid>
      <description>I put together a GitHub Gist with a generated GeoJSON document, along with the bash command that was used to create the data.
GitHub automatically generates maps for GeoJSON files in Gists and repositories. This is well documented at the following article:
https://help.github.com/articles/mapping-geojson-files-on-github The script pulls data from eBird API, transforms the data structure into GeoJSON format using jq, and then POSTs the result to a GitHub Gist where it is displayed as an interactive map.</description>
    </item>
    
    <item>
      <title>More Fun with &#39;git filter-branch&#39;</title>
      <link>https://nathanielhoag.com/blog/2014/04/01/more-fun-with-git-filter-branch/</link>
      <pubDate>Tue, 01 Apr 2014 14:06:35 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2014/04/01/more-fun-with-git-filter-branch/</guid>
      <description>Previously, I covered the use of the git filter-branch for removing large media assets from a repository&amp;rsquo;s history.
Recently I had a new opportunity to perform this task on whole directories. Here is the command sequence I used to clean up the repo history and to shrink the pack file:
# Remove a directory from history in all branches and tags $ git filter-branch --index-filter &amp;#39;git rm -r --cached --ignore-unmatch path/to/dir&amp;#39; --tag-name-filter cat -- --all # Shrink the local pack $ rm -Rf .</description>
    </item>
    
    <item>
      <title>Switch to Prezto and vim-airline</title>
      <link>https://nathanielhoag.com/blog/2014/03/23/switch-to-prezto-and-vim-airline/</link>
      <pubDate>Sun, 23 Mar 2014 22:14:16 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2014/03/23/switch-to-prezto-and-vim-airline/</guid>
      <description>I&amp;rsquo;ve been using Oh-My-Zsh and Powerline for vim for a while now, but just recently converted to Prezto and vim-airline, repectively, on word of the usability and performance improvements. Already, the benefits have been well worth the minimal effort required to set these up.
Note: anecdotally, the original switch from bash to zsh was quite easy - I understandably hear questions about this often. With Prezto, two improvements stand out markedly:</description>
    </item>
    
    <item>
      <title>Snapshot: My Git Usage</title>
      <link>https://nathanielhoag.com/blog/2014/03/15/snapshot-of-my-git-workflows/</link>
      <pubDate>Sat, 15 Mar 2014 10:57:48 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2014/03/15/snapshot-of-my-git-workflows/</guid>
      <description>Following are the Git commands and Git family of tools that I use in my day-to-day.
Before writing this post, I generated a report of my most-used git sub-commands with the following:
history | awk &amp;#39;$2 == &amp;#34;git&amp;#34; {print $3}&amp;#39; | sort | uniq -c | sort -nr | head -n 20 Most of my Git usage is bread-and-butter Git commands, but I&amp;rsquo;ll highlight some of my favorite Git features below.</description>
    </item>
    
    <item>
      <title>SSL Acrobatics</title>
      <link>https://nathanielhoag.com/blog/2014/01/28/ssl-acrobatics/</link>
      <pubDate>Tue, 28 Jan 2014 22:26:42 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2014/01/28/ssl-acrobatics/</guid>
      <description>I flip a lot of websites around between servers, and often haven to migrate SSL certificates as part of the process. The below openssl commands represent most of what I encounter in terms of validations and encoding conversions.
Primer First, a couple of basics on certificate components. The four SSL components to know are the Certificate Signing Request (CSR), the key, the certificate, and the Certificate Authority (CA) intermediate certificates. When starting fresh, you&amp;rsquo;ll first generate a CSR and a key.</description>
    </item>
    
    <item>
      <title>Another Hodgepodge Update</title>
      <link>https://nathanielhoag.com/blog/2013/12/29/another-hodgepodge-update/</link>
      <pubDate>Sun, 29 Dec 2013 14:18:03 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2013/12/29/another-hodgepodge-update/</guid>
      <description>Recently, a bash script that I&amp;rsquo;ve used many times on lots of different types of servers was giving very strange results. Typically the script is called as ./script.sh info.cfg and proceeds to run through several processes. On this occasion, I was left with : command not found. When I hit the script with bash -x I could see that both the script and the config file were giving strange results and choking on line-breaks and curly braces.</description>
    </item>
    
    <item>
      <title>Tools and Processes</title>
      <link>https://nathanielhoag.com/blog/2013/11/06/tools-and-processes/</link>
      <pubDate>Wed, 06 Nov 2013 00:00:00 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2013/11/06/tools-and-processes/</guid>
      <description>bash tricks accumulated over the last several weeks:
Argument expansion Need to move or copy a file under a long directory tree?
cp /this/is/a/really/long/path/to/{file-01,file-02}.txt Git filter-branch Need to get rid of large media files in your Git repo throughout the entire history of the project?
git filter-branch --index-filter \ &amp;#39;git rm --cached --ignore-unmatch ./path/to/file/*.ext&amp;#39; \ --tag-name-filter cat -- --all Supports wildcard matching!
History Expansion There are several techniques here, but my current favorites are sudo !</description>
    </item>
    
    <item>
      <title>A Simple Docker-hosted Hubot</title>
      <link>https://nathanielhoag.com/blog/2013/09/30/a-simple-docker-hosted-hubot/</link>
      <pubDate>Mon, 30 Sep 2013 00:00:00 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2013/09/30/a-simple-docker-hosted-hubot/</guid>
      <description>I&amp;rsquo;ve been playing with Hubot a bit lately, and decided to up the ante on the endeavor by creating a Hubot Docker container. There were a couple of misadventures before landing on a stable source container from which it will now be crazy easy to extend and deploy.
I set up Docker using the instructions here.
You may notice from reviewing the Dockerfile that line 6 imports a &amp;lsquo;Universe&amp;rsquo; apt source.</description>
    </item>
    
    <item>
      <title>Let&#39;s Skip Preview and Just Use ImageMagick</title>
      <link>https://nathanielhoag.com/blog/2013/09/18/lets-skip-preview-and-just-use-imagemagick/</link>
      <pubDate>Wed, 18 Sep 2013 00:00:00 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2013/09/18/lets-skip-preview-and-just-use-imagemagick/</guid>
      <description>Same problem, one tool&amp;hellip; (this would be a great time to set up an S3 media bucket to show results). In addition to ImageMagick, I installed ghostscript with brew install ghostscript to enable working with eps vector images.
Starting with a square profile photo:
identify nhoag-bw-sq.jpg /path/to/nhoag-bw-sq.jpg JPEG 480x480 480x480+0+0 8-bit sRGB 65.5KB 0.000u 0:00.000 Generate a black rectangle to match the width of the profile photo:
convert -size 480x100 xc:black black.</description>
    </item>
    
    <item>
      <title>Image Manipulation on OSX with Preview and ImageMagick</title>
      <link>https://nathanielhoag.com/blog/2013/09/16/image-manipulation-on-osx-with-preview-and-imagemagick/</link>
      <pubDate>Mon, 16 Sep 2013 00:00:00 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2013/09/16/image-manipulation-on-osx-with-preview-and-imagemagick/</guid>
      <description>I recently modified the Google profile image on my work Google+ account to make it more clear that it&amp;rsquo;s a work profile rather than a personal profile. I added a few layers to my existing profile image including a work logo and a couple of simple transparencies. In the past I would have relied on Photoshop, GIMP, or another heavy image manipulation GUI software to accomplish this task. This time around, I decided to make use of the OSX Preview program in conjunction with the command line tool, ImageMagick.</description>
    </item>
    
    <item>
      <title>A Few Quick Updates</title>
      <link>https://nathanielhoag.com/blog/2013/09/11/a-few-quick-updates/</link>
      <pubDate>Wed, 11 Sep 2013 00:00:00 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2013/09/11/a-few-quick-updates/</guid>
      <description>ncdu for the Win While reading through some internal tool enhancement tickets at work the other day, I happened accross a quick mention of a command line tool that I&amp;rsquo;d not yet seen, but which proved to have immediate value. The tool is ncdu, &amp;lsquo;NCurses Disk Usage&amp;rsquo;, which as the man page states, &amp;ldquo;&amp;hellip;provides a fast way to see what directories are using your disk space.&amp;rdquo;
In the process of onboarding new sites to Acquia Cloud, it&amp;rsquo;s not always clear where the lines have been drawn with regard to separating out code and media assets for a site.</description>
    </item>
    
    <item>
      <title>GoAccess Shell Plugin Revamped</title>
      <link>https://nathanielhoag.com/blog/2013/09/08/goaccess-shell-plugin-revamped/</link>
      <pubDate>Sun, 08 Sep 2013 00:00:00 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2013/09/08/goaccess-shell-plugin-revamped/</guid>
      <description>I made a bunch of big changes to the GoAccess shell plugin including improved argument handling, greater agnosticism, and greater configurability with time filtering. I converted the plugin from sourced script to regular bash script. This meant the script components had to be ordered into a sequential configuration, but this also makes the script more portable and easier to fire up.
The script options now support short and long call values, courtesy of Stack Overflow.</description>
    </item>
    
    <item>
      <title>Home-Grown VPN</title>
      <link>https://nathanielhoag.com/blog/2013/09/05/home-grown-vpn/</link>
      <pubDate>Thu, 05 Sep 2013 00:00:00 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2013/09/05/home-grown-vpn/</guid>
      <description>I just checked off another item on the TODO list - set up VPN. This was so simple and quick, I wish I&amp;rsquo;d done it earlier.
I basically just ran through the instructions at the following 3 links:
Initial Server Setup with Ubuntu 12.04 How To Set Up SSH Keys How to Install OpenVPN Access Server on Ubuntu 12.04 Mostly the same instructions apply for Ubuntu 12.10 and OpenVPN 1.8.5.</description>
    </item>
    
    <item>
      <title>GASP: GoAccess Shell Plugin</title>
      <link>https://nathanielhoag.com/blog/2013/09/03/gasp-goaccess-shell-plugin/</link>
      <pubDate>Tue, 03 Sep 2013 00:00:00 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2013/09/03/gasp-goaccess-shell-plugin/</guid>
      <description>I made some good progress on the GoAccess plugin over the past few days. Many of the kinks have been ironed out and making access.log reports has never been so easy :)
It&amp;rsquo;s a pretty simple plugin, but it does the job well. My favorite parts of the script are a fun bit of regex that&amp;rsquo;s just aesthetically pleasing, the awk date filter, and the overall flow of execution.
yes=&amp;#39;^1$|^([y|Y]([e|E][s|S])?)$&amp;#39; cmDATE=`date -u -v-&amp;#34;$goINTVAL&amp;#34;H +\[%d/%b/%Y:%H:%M:%S` # OSX date command format (-v).</description>
    </item>
    
    <item>
      <title>GoAccess for Log Analysis</title>
      <link>https://nathanielhoag.com/blog/2013/08/31/goaccess-log-analysis/</link>
      <pubDate>Sat, 31 Aug 2013 00:00:00 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2013/08/31/goaccess-log-analysis/</guid>
      <description>An excellent log analysis tool that I picked up recently from a blog post by my colleague, Amin Astaneh, is the GoAccess interactive web log analyzer. Out of the box, you can unleash GoAccess on raw or piped log data to reveal an array of interesting traffic patterns that might otherwise take some serious piping skills to crack - I covered some of these in a recent blog post.</description>
    </item>
    
    <item>
      <title>Puppet Power Up</title>
      <link>https://nathanielhoag.com/blog/2013/08/29/puppet-power-up/</link>
      <pubDate>Thu, 29 Aug 2013 00:00:00 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2013/08/29/puppet-power-up/</guid>
      <description>I&amp;rsquo;ve dabbled with, attended presentations for, and read about configuration management systems for quite a while. For at least the past year, every time I start up a new project I can&amp;rsquo;t help but think about all of the benefits that would ensue from wrapping my work in a managed server configuration. I decided recently to bite the bullet and dive into Puppet head.
In getting started, and to keep things simple, I decided to utilize a Vagrant box running 64-bit Ubuntu 12.</description>
    </item>
    
    <item>
      <title>Fun with access.log</title>
      <link>https://nathanielhoag.com/blog/2013/08/24/fun-with-accesslog/</link>
      <pubDate>Sat, 24 Aug 2013 00:00:00 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2013/08/24/fun-with-accesslog/</guid>
      <description>With analyzing data sets and performing repetitive (and tedious) tasks, piping streams in the terminal can save a ridiculous amount of manual labor and time. Following are a few examples that I use in diagnosing and resolving various types of problems with web applications.
Assuming log entries in the following format:
1.1.1.1 - - [24/Aug/2013:12:55:30 +0000] &amp;#34;GET / HTTP/1.0&amp;#34; 200 2227 &amp;#34;-&amp;#34; &amp;#34;USER AGENT STRING&amp;#34; vhost=vhost.example.com host=example.com hosting_site=docroot request_time=5640229 Number of Requests $ for i in {0.</description>
    </item>
    
    <item>
      <title>Just a Little Bug</title>
      <link>https://nathanielhoag.com/blog/2013/08/20/just-a-little-bug/</link>
      <pubDate>Tue, 20 Aug 2013 00:00:00 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2013/08/20/just-a-little-bug/</guid>
      <description>It&amp;rsquo;s an old bug but a tiny stumbling block for zsh users who are new to Jekyll/Octopress. On submitting the following command I was getting a silly error in response.
Command:
$ rake new_post[&amp;#34;First Post\!&amp;#34;] Error:
zsh: no matches found: new_post[First Post!] I ultimately ended up here.
Escapes are fine, but I decided to go with the &amp;ldquo;noglob&amp;rdquo; alias in .zshrc given that it&amp;rsquo;s difficult enough to write on a regular basis :)</description>
    </item>
    
    <item>
      <title>First Post!</title>
      <link>https://nathanielhoag.com/blog/2013/08/19/first-post/</link>
      <pubDate>Mon, 19 Aug 2013 00:00:00 +0000</pubDate>
      
      <guid>https://nathanielhoag.com/blog/2013/08/19/first-post/</guid>
      <description>First post getting a tech blog together on Octopress and S3. Excited to jot down notes and findings from my daily tech adventures.</description>
    </item>
    
  </channel>
</rss>
