St. John JohnsonThe personal website of St. John Johnson - Developer, Gamer, Person, Thingy.
http://stj.me/
Sun, 18 Mar 2018 18:39:41 +0000Sun, 18 Mar 2018 18:39:41 +0000Jekyll v2.5.3OpenVPN and DD-WRT<p>I’m not sure why but there is apparently <em>no</em> simple tutorial on how to get started with an OpenVPN server on DD-WRT.</p>
<p>When I set this up, I followed about 15 different guides and had to steal some configuration from a friend (who doesn’t remember where he found it).</p>
<p>This shouldn’t ever be this difficult, so I decided to write it all down for the next person to have an easier time.</p>
<!--more-->
<h2 id="step-1-install-tunnelblick">Step 1: Install Tunnelblick</h2>
<p>Okay, so the first thing we need is a OpenVPN client. I chose <a href="https://www.tunnelblick.net/">Tunnelblick</a> for OSX because it’s free, open source, and comes bundled with <a href="https://github.com/OpenVPN/easy-rsa">easy-rsa</a> (which will make our life REALLY easy).</p>
<p>Installing is simple, just install via <a href="https://www.tunnelblick.net/downloads.html">their website</a> or via <a href="http://brew.sh/">Homebrew</a>’s <a href="http://caskroom.io/">Cask</a>.</p>
<p><code>
$ brew cask install tunnelblick
</code></p>
<h2 id="step-2-generate-the-ca-certificate">Step 2: Generate the CA Certificate</h2>
<p>Once we have <a href="https://www.tunnelblick.net/">Tunnelblick</a> installed, we can use the built-in copy of <a href="https://github.com/OpenVPN/easy-rsa">easy-rsa</a> to generate all the certs we need. If you chose to install an alternative client in step 1, then you need to get <a href="https://github.com/OpenVPN/easy-rsa">easy-rsa</a> on your own.</p>
<p>Tunnelblick installs easy-rsa in your local home directory:</p>
<pre><code>$ cd "~/Library/Application Support/Tunnelblick/easy-rsa"
</code></pre>
<p>First thing we have to do is export the nice default variables they provide in <code>vars</code> and clean the environment. You can change them, but they are just defaults and you will be prompted for them later.</p>
<pre><code>$ . vars
$ ./clean-all
</code></pre>
<p>This has now created the <code>keys/</code> directory in this folder. This is where all the goodness will go.</p>
<p>Okay, now that everything is setup, we can finally make our global CA, the thing we’re going to use to sign all the device certificates. You can easily make this by running:</p>
<pre><code>$ ./pkitool --initca
</code></pre>
<p>You will now have two very important files:</p>
<pre><code>-rw-r--r-- 1 root wheel 1387 Feb 17 18:49 ca.crt
-rw------- 1 root wheel 890 Feb 17 18:49 ca.key
</code></pre>
<p>The <code>ca.crt</code> needs to be made available to all the devices you want to connect with (and serve from), but the <code>ca.key</code> should be kept secret (as it can be used to sign new device certificates).</p>
<h2 id="step-3-generate-the-servers-certificate">Step 3: Generate the Server’s Certificate</h2>
<p>Now that you have a CA, you can start creating some device certificates! Start by making one for the server:</p>
<pre><code>$ ./build-key-server server
</code></pre>
<p><strong><em>NOTE: It’s very important NOT to pick a password for this certificate, otherwise DD-WRT is not going to be able to decrypt it</em></strong></p>
<p>This process will generate some new files which will be needed for the server:</p>
<pre><code>-rw-r--r-- 1 root wheel 4174 Feb 17 18:50 server.crt
-rw------- 1 root wheel 890 Feb 17 18:50 server.key
</code></pre>
<p>These two will be used later in the DD-WRT configuration, so hang on to them.</p>
<h2 id="step-4-generate-diffie-hellman-parameters">Step 4: Generate Diffie-Hellman Parameters</h2>
<p>Now that we have a server certificate, we can make the Diffie-Hellman parameters for the SSL/TLS connection.</p>
<p>Easily done by running:</p>
<pre><code>$ ./build-dh
</code></pre>
<p>And you’ll get a fantastic pem file like this one:</p>
<pre><code>-rw-r--r-- 1 root wheel 244 Feb 17 18:50 dh1024.pem
</code></pre>
<p>We’ll use this later when configuring DD-WRT.</p>
<h2 id="step-5-generate-your-device-certificates">Step 5: Generate your Device Certificates</h2>
<p>We’re going to make two devices here, an iPhone and Laptop. I’m going to call the devices by those names in this tutorial, but your names should be more unique to the devices themselves (like hostnames for example).</p>
<pre><code>$ ./build-key iphone
$ ./build-key laptop
</code></pre>
<p><strong><em>NOTE: I recommend creating passwords for these, but you don’t HAVE to.</em></strong></p>
<p>This will generate us similar files as the previous steps:</p>
<pre><code>-rw-r--r-- 1 root wheel 4001 Feb 17 18:50 iphone.crt
-rw------- 1 root wheel 883 Feb 17 18:50 iphone.key
-rw-r--r-- 1 root wheel 4014 Feb 17 18:50 laptop.crt
-rw------- 1 root wheel 882 Feb 17 18:50 laptop.key
</code></pre>
<p>Hang on to them for your individual device setup.</p>
<h2 id="step-6-configure-dd-wrt-vpn-settings">Step 6: Configure DD-WRT VPN Settings</h2>
<p>Now go to your router’s VPN tab under Services and let’s start flipping some settings! All of these are under “OpenVPN Server/Daemon”.</p>
<h3 id="basic-settings">Basic Settings</h3>
<ul>
<li>OpenVPN: <code>Enable</code></li>
<li>Start Type: <code>WAN Up</code> (we want to have internet before starting)</li>
<li>Config as: <code>Server</code> (we’re a server, yeah?)</li>
<li>Server Mode: <code>Router (TUN)</code> (I don’t know)</li>
<li>Network: <code>10.0.2.0</code> (I chose this as it’s a dedicated segment of my network, my normal routing is <code>10.0.0.0</code> in this network)</li>
<li>Netmask: <code>255.255.255.0</code></li>
<li>Port: <code>1194</code> (I like to leave the default here)</li>
<li>Tunnel Protocol: <code>UDP</code> (and here)</li>
<li>Encryption Cipher: <code>Blowfish CBC</code></li>
<li>Hash Algoritm: <code>SHA1</code></li>
<li>Advanced Options <code>Disable</code> (don’t need any of that)</li>
</ul>
<p>Now for the big text fields, we’re going to go through them one by one.</p>
<h3 id="public-server-cert">Public Server Cert</h3>
<p>Take the <code>server.crt</code> and find where <code>-----BEGIN CERTIFICATE-----</code> starts. Copy from there until the end of the file, including the line <code>-----END CERTIFICATE-----</code>. Put this in that field.</p>
<h3 id="ca-cert">CA Cert</h3>
<p>Just stick the contents of <code>ca.crt</code> in here.</p>
<h3 id="private-server-key">Private Server Key</h3>
<p>The contents of <code>server.key</code> go in here.</p>
<h3 id="dh-pem">DH PEM</h3>
<p>This is where we put the <code>dh1024.pem</code> contents.</p>
<h3 id="additional-config">Additional Config</h3>
<p>For here, we don’t need to do much. I just have a couple basic tweaks I add:</p>
<pre><code># Route traffic from this new network into my existing network
push "route 10.0.0.0 255.255.255.0"
# DNS server is 10.0.0.1, a.k.a. my router.
push "dhcp-option DNS 10.0.0.1"
# Use the tun0 device (so we can refer to it later)
dev tun0
# Ping every 10 seconds, and restart after 120 seconds of inactivity
keepalive 10 120
</code></pre>
<p>Okay, that’s it for this page. Save and Apply changes!</p>
<h2 id="step-7-configure-the-firewall">Step 7: Configure the Firewall</h2>
<p>Now that we have the service running, there’s some final configuration required to ensure that the VPNed traffic can talk to the internet AND the intranet (inside your network). Go to <code>Administration</code> and then <code>Commands</code>.</p>
<p>This part may look a little scary, but it’s very simple when you break down each command.</p>
<p>We’re going to put the following Firewall configuration into the <code>Command Shell</code> / <code>Commands</code> section.</p>
<pre><code># Accepts incoming traffic via port 1194 UDP
iptables -I INPUT 1 -p udp --dport 1194 -j ACCEPT
# Allows the VPN client access to router internal
# processes, e.g. Web admin, SSH etc
iptables -I INPUT 3 -i tun0 -j ACCEPT
# Allows connections between VPN clients, if
# client-to-client is enabled in OpenVPN server
iptables -I FORWARD 3 -i tun0 -o tun0 -j ACCEPT
# Allows connection from local VPN to the internet
iptables -I FORWARD 1 --source 10.0.2.0/24 -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.0.2.0/24 -j MASQUERADE
# Allows connections from local network to VPN network
# and other way around (br0 is LAN and WIFI)
iptables -I FORWARD -i br0 -o tun0 -j ACCEPT
iptables -I FORWARD -i tun0 -o br0 -j ACCEPT
</code></pre>
<p>Great, now hit <code>Save Firewall</code> and your server is done!</p>
<h2 id="step-8-configure-your-devices">Step 8: Configure your devices</h2>
<p>Now that you have a server, you need to setup your different devices. Like I said before, we’re going to stick to the <code>laptop</code> and <code>iphone</code> device types we made before.</p>
<h3 id="iphone">iPhone</h3>
<ul>
<li>Install OpenVPN Client (free on AppStore)</li>
<li>Create a folder to store stuff in locally (let’s call it <code>iphone/</code>)</li>
<li>Put the <code>iphone.key</code>, <code>iphone.crt</code>, and <code>ca.crt</code> in this directory</li>
<li>
<p>Create a new file called <code>config.ovpn</code> with the contents:</p>
<pre><code> # Specify that we are a client and that we
# will be pulling certain config file directives
# from the server.
client
# Use the same setting as you are using on
# the server.
dev tun0
# Are we connecting to a TCP or
# UDP server? Use the same setting as
# on the server.
proto udp
# The hostname/IP and port of the server.
remote YOURHOSTNAMEHERE 1194
# Keep trying indefinitely to resolve the
# host name of the OpenVPN server. Very useful
# on machines which are not permanently connected
# to the internet such as laptops.
resolv-retry infinite
# Most clients don't need to bind to
# a specific local port number.
nobind
# Try to preserve some state across restarts.
persist-key
persist-tun
# SSL/TLS parms.
ca ca.crt
cert iphone.crt
key iphone.key
# Verify server certificate by checking
# that the certicate has the nsCertType
# field set to "server". This is an
# important precaution to protect against
# a potential attack discussed here:
# http://openvpn.net/howto.html#mitm
ns-cert-type server
# Enable compression on the VPN link.
comp-lzo
# Allow me to change my IP address
# and/or port number (if I get a new
# local IP address at Starbucks).
float
</code></pre>
</li>
<li>Open iTunes, go to your device, then Applications. At the very bottom you will see <code>OpenVPN</code>, click on it. Drag all four files you created in the <code>iphone/</code> folder into the box on the right. This uploads them into the device. Click <code>sync</code>.</li>
<li>Open up the app on your phone, it will allow you to create a new profile based on this input.</li>
<li>Done! Connect to your network!</li>
</ul>
<h1 id="laptop">Laptop</h1>
<p>Okay, the reason I said to do the iPhone first, was that the Laptop is basically the same thing!</p>
<ul>
<li>Create a folder to store stuff in locally (let’s call it <code>HomeVPN/</code>)</li>
<li>Put the <code>laptop.key</code>, <code>laptop.crt</code>, and <code>ca.crt</code> in this directory</li>
<li>Create a new file called <code>config.ovpn</code> with similar contents as before (but replace <code>iphone</code> with <code>laptop</code>)</li>
<li>Rename the folder to <code>HomeVPN.tblk/</code></li>
<li>Double-click it and import into Tunnelblick</li>
</ul>
Wed, 17 Feb 2016 00:00:00 +0000http://stj.me/2016/02/17/openvpn-ddwrt.html
http://stj.me/2016/02/17/openvpn-ddwrt.htmlRaspberry Pi Streamsaver<p>Personally, I’m a huge fan of home automation. Ever since my wife and I bought
our house, I’ve been trying to find ways to secure and automate it. This obviously
included the basic toys like the <a href="http://amzn.to/1Hcdb4r">Amazon Echo</a> and <a href="http://amzn.to/1Hcde00">Nest Thermostat</a>.</p>
<p>But one of the other areas I’m poking around in is security cameras, specifically
monitoring the entrances of the house. I live in a quiet neighborhood, but I do
hear a lot of complaints on <a href="https://nextdoor.com/amazon/?r=nrhndd">NextDoor</a> of people stealing packages.</p>
<p>This always made me uncomfortable, so I consider the cameras as a method to
<a href="https://en.wikipedia.org/wiki/List_of_HTTP_status_codes">enhance my calm.</a></p>
<p>Anwyway, so the problem I seem to have now is that the two cameras I purchased
(<a href="http://amzn.to/1Hcd6h4">D-Link DCS-932LB1</a> and a <a href="http://amzn.to/1HccZCb">Foscam FI8910W</a>) will only perform two
operations on motion/sound detection:
- Send email of 1 picture per second for 6 seconds
- Upload same pictures to FTP server</p>
<p>It works, kinda. It’s just not ideal.</p>
<p>So how can I make this better? Bam, spare Raspberry Pi!</p>
<!--more-->
<h1 id="motion-alerts">Motion Alerts</h1>
<p>I wanted to trigger recording of the ASF or MJPEG stream from the cameras if
motion is detected. The first idea I had was to run a fake FTP server and
get notifications that way.</p>
<p>I was super excited to see someone else had the same idea and wrote up a
<a href="http://wrice.blogspot.com/2013/07/how-to-setup-foscam-ip-camera-for.html">blog post about it</a>. Now this was 3 years ago and they wrote everything
in shell (yuck). Apparently he came back and decided to do this in C++
<a href="http://raspberrypiprogramming.blogspot.com/2014/09/foscam-video-capture-server-at-motion.html">a year later</a>. For some insane reason, he didn’t provide links to
any of his source code, only screenshots of it in vim.</p>
<p>I’m not a C programmer and I don’t want to visually copy/paste this guy’s code.
But at least I felt I was on the right track.</p>
<p>His approach was to use GStreamer (so have others in the past) on the Raspberry Pi
so you can leverage the H264 support. So I got started with a vanilla
<a href="http://raspbian.org">Raspbian</a> installation and some basic instructions.</p>
<h1 id="gstreamer-troubles">GStreamer Troubles</h1>
<p>Most blogs/guides were around installing/compiling 1.0 as 0.10 was the only version
available on Raspbian at the time. Luckily it’s now available as part of their
latest release.</p>
<p>A quick installation of the extra plugins and I was ready to start (I think).</p>
<noscript><pre>sudo apt-get install gstreamer1.0-alsa gstreamer1.0-clutter gstreamer1.0-doc gstreamer1.0-fluendo-mp3 \
gstreamer1.0-gnonlin gstreamer1.0-libav gstreamer1.0-nice gstreamer1.0-omx \
gstreamer1.0-packagekit gstreamer1.0-plugins-bad gstreamer1.0-plugins-base-apps \
gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly \
gstreamer1.0-pulseaudio gstreamer1.0-tools gstreamer1.0-vaapi gstreamer1.0-x \
libgstreamer1.0-0 libgstreamer1.0-0-dbg libgstreamer1.0-dev </pre></noscript>
<script src="https://gist.github.com/stjohnjohnson/763d6799ce573e8113d8.js?file=apt-get"> </script>
<p>Understanding GStreamer and its pipeline is extremely confusing. Documentation
is quite sparse. But this is what I hobbled together:</p>
<noscript><pre>$ gst-launch-1.0 \
# Pull from foscam ASF stream
souphttpsrc location=&quot;http://username\@ipcamera1/videostream.asf\?user=username\&amp;pwd=password&quot; \
# Pick the right decoder for the stream
! decodebin name=decoder decoder. \
# Add a basic clock
! clockoverlay \
# Convert into a new format
! videoconvert \
# Encode with hardware H264
! omxh264enc \
# Using the high profile
! &quot;video/x-h264,profile=high&quot; \
# Parse!?
! h264parse \
# Prepare to combine into to .mkv file
! matroskamux name=mux \
# Put it into the /tmp directory
! filesink location=/tmp/foo.mkv decoder. \
# Convert the incoming audo
! audioconvert \
# Using MP3 format
! lamemp3enc \
# Combine!
! mux.</pre></noscript>
<script src="https://gist.github.com/stjohnjohnson/763d6799ce573e8113d8.js?file=recommended"> </script>
<p>This, kinda worked. But the quality was absolutely impossible:
<img src="/assets/posts/raspberry-pi-streamsaver/badimage.png" alt="Bad Image" /></p>
<p>At this point, I gave up and moved onto another project (hoping to pick this up later).</p>
Wed, 28 Oct 2015 00:00:00 +0000http://stj.me/2015/10/28/raspberry-pi-streamsaver.html
http://stj.me/2015/10/28/raspberry-pi-streamsaver.htmlHosting Woes<p>Now that I can build my blog via continuous integration, I want to push the
digital envelope and go to full continuous deployment.</p>
<h3 id="github-pages">GitHub Pages</h3>
<p>Apparently, the <a href="https://help.github.com/articles/using-jekyll-with-pages/">most</a> <a href="http://jekyllrb.com/docs/github-pages/">common</a> <a href="http://www.smashingmagazine.com/2014/08/build-blog-jekyll-github-pages/">way</a> to deploy
Jekyll applications is via <a href="https://pages.github.com/">GitHub Pages</a>. Put your Jekyll configuration
in GitHub and magically you can have your own blog complete with subdomain and
automated deployment.</p>
<p>Well that <strong>sounds perfect!</strong> It’s simple. Lots of people are doing it. Why
shouldn’t I?</p>
<p>And then I ran across <em>this</em> article:</p>
<blockquote>
<p><a href="http://gon.to/2015/03/03/f-percent-number-ck-github-pages-for-jekyll-why-i-decided-to-use-digital-ocean/">F%#ck Github Pages for my Jekyll blog. Why I decided to use Digital Ocean
instead?</a></p>
</blockquote>
<!--more-->
<p>Welp, looks like I’m going to probably run into just as many problems as this
poor folk had. Better look for an alternative.</p>
<h3 id="digital-ocean">Digital Ocean</h3>
<p>This wasn’t the first time I heard of <a href="https://www.digitalocean.com/?refcode=eba200569184">Digital Ocean</a>. A bunch
of my friends use it for things like <a href="http://wiki.mumble.info/wiki/Main_Page">Mumble servers</a>,
<a href="http://francesanddavid.com/">Wedding websites</a>, and more. Honestly, I’ve been looking for a good
reason to try something other than <a href="http://www.rackspace.com/">Rackspace</a> (which I’ve been using
for the last 5+ years).</p>
<p>Using Digital Ocean, I can get my own server (aka “droplet”), run a web service
on it, deploy my “built” html to it, and then be able to browse my new blog.</p>
<p><strong>Felt straight forward and very familiar.</strong></p>
<p>But as I perused the distributions and applications made available to me,
each of the options felt far too complex for my simple static HTML.</p>
<p>Do I pick the comfortable Ubuntu server where I still need to manage the
accounts, security, updates, etc? What about the Docker application? I could
build all my sites as simple Docker containers, deploy them to this server, and
use some fancy Nginx configuration to route between them.</p>
<p>All of this made me very uncomfortable. I felt like nothing has changed since
I last did this 5+ years ago.</p>
Mon, 31 Aug 2015 00:00:00 +0000http://stj.me/2015/08/31/hosting-woes.html
http://stj.me/2015/08/31/hosting-woes.htmlWercker It<p>I work on the central Continuous Delivery team at Yahoo. So it goes without
saying that I want my personal website to have the same awesomeness.</p>
<p>My first thought was, this is <a href="http://jekyllrb.com">Jekyll</a>, so it should be pretty easy to just build
the static HTML and host it somewhere. So I jumped to my go-to CD tool,
<a href="http://wercker.com">Wercker</a>.</p>
<!--more-->
<p>It has been a while since I used them. Apparently, they got rid of their custom
boxes in favor of Docker images direct from the registry. So after a bit of
fiddling, I pulled the ruby image, installed my dependencies, and ran a Jekyll
build.</p>
<noscript><pre>box: ruby
build:
steps:
# Install gem dependencies
- bundle-install
# Run some basic health checks
- script:
name: health check
code: bundle exec jekyll doctor --trace
# Generate site locally
- script:
name: generate site
code: bundle exec jekyll build --trace
</pre></noscript>
<script src="https://gist.github.com/stjohnjohnson/201d8b252eb8f9872e45.js?file=wercker.yml"> </script>
<p>Whoops. Caught by a simple error.</p>
<noscript><pre>/pipeline/cache/bundle-install/ruby/2.2.0/gems/execjs-2.6.0/lib/execjs/runtimes.rb:48:in `autodetect&#39;: Could not find a JavaScript runtime. See https://github.com/rails/execjs for a list of available runtimes. (ExecJS::RuntimeUnavailable)
from /pipeline/cache/bundle-install/ruby/2.2.0/gems/execjs-2.6.0/lib/execjs.rb:5:in `&lt;module:ExecJS&gt;&#39;
from /pipeline/cache/bundle-install/ruby/2.2.0/gems/execjs-2.6.0/lib/execjs.rb:4:in `&lt;top (required)&gt;&#39;
from /pipeline/cache/bundle-install/ruby/2.2.0/gems/coffee-script-2.4.1/lib/coffee_script.rb:1:in `require&#39;
from /pipeline/cache/bundle-install/ruby/2.2.0/gems/coffee-script-2.4.1/lib/coffee_script.rb:1:in `&lt;top (required)&gt;&#39;
from /pipeline/cache/bundle-install/ruby/2.2.0/gems/coffee-script-2.4.1/lib/coffee-script.rb:1:in `require&#39;
from /pipeline/cache/bundle-install/ruby/2.2.0/gems/coffee-script-2.4.1/lib/coffee-script.rb:1:in `&lt;top (required)&gt;&#39;
from /pipeline/cache/bundle-install/ruby/2.2.0/gems/jekyll-coffeescript-1.0.1/lib/jekyll-coffeescript.rb:2:in `require&#39;
from /pipeline/cache/bundle-install/ruby/2.2.0/gems/jekyll-coffeescript-1.0.1/lib/jekyll-coffeescript.rb:2:in `&lt;top (required)&gt;&#39;
from /pipeline/cache/bundle-install/ruby/2.2.0/gems/jekyll-2.5.3/lib/jekyll/deprecator.rb:46:in `require&#39;
from /pipeline/cache/bundle-install/ruby/2.2.0/gems/jekyll-2.5.3/lib/jekyll/deprecator.rb:46:in `block in gracefully_require&#39;
from /pipeline/cache/bundle-install/ruby/2.2.0/gems/jekyll-2.5.3/lib/jekyll/deprecator.rb:44:in `each&#39;
from /pipeline/cache/bundle-install/ruby/2.2.0/gems/jekyll-2.5.3/lib/jekyll/deprecator.rb:44:in `gracefully_require&#39;
from /pipeline/cache/bundle-install/ruby/2.2.0/gems/jekyll-2.5.3/lib/jekyll.rb:166:in `&lt;top (required)&gt;&#39;
from /pipeline/cache/bundle-install/ruby/2.2.0/gems/jekyll-2.5.3/bin/jekyll:6:in `require&#39;
from /pipeline/cache/bundle-install/ruby/2.2.0/gems/jekyll-2.5.3/bin/jekyll:6:in `&lt;top (required)&gt;&#39;
from /pipeline/cache/bundle-install/ruby/2.2.0/bin/jekyll:23:in `load&#39;
from /pipeline/cache/bundle-install/ruby/2.2.0/bin/jekyll:23:in `&lt;main&gt;&#39;</pre></noscript>
<script src="https://gist.github.com/stjohnjohnson/201d8b252eb8f9872e45.js?file=error1.log"> </script>
<p>Hmm, so it appears I need to pull in some sort of JavaScript runtime. On my Mac
I already have Node.JS installed, so obviously I came up with the bad idea of
installing that in the container…</p>
<noscript><pre>box: ruby
build:
steps:
# Install gem dependencies
- bundle-install
# Install node.js
- script:
name: install node
code: |-
curl -sL https://deb.nodesource.com/setup_0.12 | bash -
apt-get install -y nodejs
# Run some basic health checks
- script:
name: health check
code: bundle exec jekyll doctor --trace
# Generate site locally
- script:
name: generate site
code: bundle exec jekyll build --trace
</pre></noscript>
<script src="https://gist.github.com/stjohnjohnson/201d8b252eb8f9872e45.js?file=node_wercker.yml"> </script>
<p>Ugh. That added at least another minute to my build, but at least it passed.</p>
<p>After some discussions with myself, I determined that I was crazy and should
probably just click the link provided in the error message. First item on that page
gave me a solution that just required another gem, <a href="https://github.com/cowboyd/therubyracer">therubyracer</a>,
to be added to my Gemfile.</p>
<noscript><pre>source &#39;https://rubygems.org&#39;
ruby &#39;2.2.3&#39;
# JavaScript Exec tool
gem &#39;therubyracer&#39;
# Jekyll and plugins
gem &#39;jekyll&#39;
gem &#39;jekyll-timeago&#39;
gem &#39;jekyll-gist&#39;
# Markdown renderer
gem &#39;kramdown&#39;
</pre></noscript>
<script src="https://gist.github.com/stjohnjohnson/201d8b252eb8f9872e45.js?file=Gemfile"> </script>
<p><em>Build Passed!</em></p>
<p><a href="https://app.wercker.com/project/bykey/24650efb0fd8d95cf920b12927980244"><img src="https://app.wercker.com/status/24650efb0fd8d95cf920b12927980244/m/master" alt="wercker status" title="wercker status" /></a></p>
<p>Awesome!! And I got my build time to under a minute.</p>
<p>Next I need to figure out deployments.</p>
Sun, 30 Aug 2015 00:00:00 +0000http://stj.me/2015/08/30/wercker-it.html
http://stj.me/2015/08/30/wercker-it.htmlFree from Wordpress<p>Well, here I am. Wordpress-less.</p>
<p>I figured after 5+ years of not updating my Wordpress blog, that maybe it’s a
little overpowered for what I need.</p>
<p>I was also quite sick of the alerts from Rackspace that I my VM had consumed all
the memory again. I’m sure there’s something bad going on, but honestly I really
didn’t want to worry and maintain it anymore.</p>
<!--more-->
<p>So welcome to the start of my new site. Looks the same (mostly), but in fact is
completely flat-file - built entirely with <a href="http://jekyllrb.com/">Jekyll</a>!</p>
<p>That means no more databases, server-side code, security updates, etc. It’s
amazing!</p>
<p>Obviously, I’m significantly lacking content - intentional of course. I was
going through the process of migrating my old blog posts, but it occurred to me
that I don’t think 5-7 year old posts about PHP 5 are really applicable anymore.
Hence the blank slate.</p>
<p>Hopefully as I find any free time, I’ll be populating this with old projects,
new ideas, and fun things I discover in my daily life.</p>
<p>Out of wordpress, into the fire.</p>
Sat, 29 Aug 2015 00:00:00 +0000http://stj.me/2015/08/29/free-from-wordpress.html
http://stj.me/2015/08/29/free-from-wordpress.html