diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..ac74f27
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,44 @@
+source "https://rubygems.org"
+# Hello! This is where you manage which Jekyll version is used to run.
+# When you want to use a different version, change it below, save the
+# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
+#
+# bundle exec jekyll serve
+#
+# This will help ensure the proper Jekyll version is running.
+# Happy Jekylling!
+gem "jekyll", "~> 4.3.2"
+# This is the default theme for new Jekyll sites. You may change this to anything you like.
+gem "minima", "~> 2.5"
+gem "no-style-please", git: "https://github.com/atomaka/no-style-please", branch: "atomaka"
+# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
+# uncomment the line below. To upgrade, run `bundle update github-pages`.
+# gem "github-pages", group: :jekyll_plugins
+# If you have any plugins, put them here!
+group :jekyll_plugins do
+ gem "jekyll-feed", "~> 0.12"
+ gem "jekyll-gist"
+ gem "jekyll-tidy"
+end
+
+group :development do
+ # import for medium
+ gem "jekyll-import", git: "https://github.com/jekyll/jekyll-import"
+ gem "mdl"
+ gem "rss"
+ gem "safe_yaml"
+end
+
+# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
+# and associated library.
+platforms :mingw, :x64_mingw, :mswin, :jruby do
+ gem "tzinfo", ">= 1", "< 3"
+ gem "tzinfo-data"
+end
+
+# Performance-booster for watching directories on Windows
+gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin]
+
+# Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem
+# do not have a Java counterpart.
+gem "http_parser.rb", "~> 0.6.0", :platforms => [:jruby]
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 0000000..5749a92
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,152 @@
+GIT
+ remote: https://github.com/atomaka/no-style-please
+ revision: e281fa0bbecc82e84fe61be9a92baad5a1a46763
+ branch: atomaka
+ specs:
+ no-style-please (0.4.7)
+ jekyll
+ jekyll-feed
+ jekyll-seo-tag
+
+GIT
+ remote: https://github.com/jekyll/jekyll-import
+ revision: 6499317a81aeda119b6ceefb37ab81c9f6219659
+ specs:
+ jekyll-import (0.21.0)
+ jekyll (>= 3.7, < 5.0)
+ nokogiri (~> 1.0)
+ reverse_markdown (~> 2.1)
+
+GEM
+ remote: https://rubygems.org/
+ specs:
+ addressable (2.8.1)
+ public_suffix (>= 2.0.2, < 6.0)
+ chef-utils (18.1.0)
+ concurrent-ruby
+ colorator (1.1.0)
+ concurrent-ruby (1.2.0)
+ em-websocket (0.5.3)
+ eventmachine (>= 0.12.9)
+ http_parser.rb (~> 0)
+ eventmachine (1.2.7)
+ faraday (2.7.4)
+ faraday-net_http (>= 2.0, < 3.1)
+ ruby2_keywords (>= 0.0.4)
+ faraday-net_http (3.0.2)
+ ffi (1.15.5)
+ forwardable-extended (2.6.0)
+ google-protobuf (3.21.12-x86_64-linux)
+ htmlbeautifier (1.4.2)
+ htmlcompressor (0.4.0)
+ http_parser.rb (0.8.0)
+ i18n (1.12.0)
+ concurrent-ruby (~> 1.0)
+ jekyll (4.3.2)
+ addressable (~> 2.4)
+ colorator (~> 1.0)
+ em-websocket (~> 0.5)
+ i18n (~> 1.0)
+ jekyll-sass-converter (>= 2.0, < 4.0)
+ jekyll-watch (~> 2.0)
+ kramdown (~> 2.3, >= 2.3.1)
+ kramdown-parser-gfm (~> 1.0)
+ liquid (~> 4.0)
+ mercenary (>= 0.3.6, < 0.5)
+ pathutil (~> 0.9)
+ rouge (>= 3.0, < 5.0)
+ safe_yaml (~> 1.0)
+ terminal-table (>= 1.8, < 4.0)
+ webrick (~> 1.7)
+ jekyll-feed (0.17.0)
+ jekyll (>= 3.7, < 5.0)
+ jekyll-gist (1.5.0)
+ octokit (~> 4.2)
+ jekyll-sass-converter (3.0.0)
+ sass-embedded (~> 1.54)
+ jekyll-seo-tag (2.8.0)
+ jekyll (>= 3.8, < 5.0)
+ jekyll-tidy (0.2.2)
+ htmlbeautifier
+ htmlcompressor
+ jekyll
+ jekyll-watch (2.2.1)
+ listen (~> 3.0)
+ kramdown (2.4.0)
+ rexml
+ kramdown-parser-gfm (1.1.0)
+ kramdown (~> 2.0)
+ liquid (4.0.4)
+ listen (3.8.0)
+ rb-fsevent (~> 0.10, >= 0.10.3)
+ rb-inotify (~> 0.9, >= 0.9.10)
+ mdl (0.12.0)
+ kramdown (~> 2.3)
+ kramdown-parser-gfm (~> 1.1)
+ mixlib-cli (~> 2.1, >= 2.1.1)
+ mixlib-config (>= 2.2.1, < 4)
+ mixlib-shellout
+ mercenary (0.4.0)
+ minima (2.5.1)
+ jekyll (>= 3.5, < 5.0)
+ jekyll-feed (~> 0.9)
+ jekyll-seo-tag (~> 2.1)
+ mixlib-cli (2.1.8)
+ mixlib-config (3.0.27)
+ tomlrb
+ mixlib-shellout (3.2.7)
+ chef-utils
+ nokogiri (1.14.1-x86_64-linux)
+ racc (~> 1.4)
+ octokit (4.25.1)
+ faraday (>= 1, < 3)
+ sawyer (~> 0.9)
+ pathutil (0.16.2)
+ forwardable-extended (~> 2.6)
+ public_suffix (5.0.1)
+ racc (1.6.2)
+ rake (13.0.6)
+ rb-fsevent (0.11.2)
+ rb-inotify (0.10.1)
+ ffi (~> 1.0)
+ reverse_markdown (2.1.1)
+ nokogiri
+ rexml (3.2.5)
+ rouge (4.0.1)
+ rss (0.2.9)
+ rexml
+ ruby2_keywords (0.0.5)
+ safe_yaml (1.0.5)
+ sass-embedded (1.58.0)
+ google-protobuf (~> 3.21)
+ rake (>= 10.0.0)
+ sawyer (0.9.2)
+ addressable (>= 2.3.5)
+ faraday (>= 0.17.3, < 3)
+ terminal-table (3.0.2)
+ unicode-display_width (>= 1.1.1, < 3)
+ tomlrb (2.0.3)
+ unicode-display_width (2.4.2)
+ webrick (1.8.1)
+
+PLATFORMS
+ x86_64-linux
+
+DEPENDENCIES
+ http_parser.rb (~> 0.6.0)
+ jekyll (~> 4.3.2)
+ jekyll-feed (~> 0.12)
+ jekyll-gist
+ jekyll-import!
+ jekyll-tidy
+ mdl
+ minima (~> 2.5)
+ no-style-please!
+ rss
+ safe_yaml
+ tzinfo (>= 1, < 3)
+ tzinfo-data
+ wdm (~> 0.1.1)
+
+BUNDLED WITH
+ 2.3.26
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c5b76ee
--- /dev/null
+++ b/README.md
@@ -0,0 +1,23 @@
+# atomaka.com
+
+Website managed by jekyll.
+
+## Pre-requisites
+
+* Python
+ * whatever version lets you install `requirements.txt`
+* Ruby
+ * Preferably the version in `.ruby-version`
+
+## Setup
+
+1. `pip install -r requirements.txt`
+2. `bundle install`
+
+## Testing
+
+* `bundle exec jekyll serve`
+
+## Deployment
+
+* `./build.sh`
diff --git a/_config.yml b/_config.yml
new file mode 100644
index 0000000..9e855e9
--- /dev/null
+++ b/_config.yml
@@ -0,0 +1,60 @@
+# Welcome to Jekyll!
+#
+# This config file is meant for settings that affect your whole blog, values
+# which you are expected to set up once and rarely edit after that. If you find
+# yourself editing this file very often, consider using Jekyll's data files
+# feature for the data you need to update frequently.
+#
+# For technical reasons, this file is *NOT* reloaded automatically when you use
+# 'bundle exec jekyll serve'. If you change this file, please restart the server process.
+#
+# If you need help with YAML syntax, here are some quick references for you:
+# https://learn-the-web.algonquindesign.ca/topics/markdown-yaml-cheat-sheet/#yaml
+# https://learnxinyminutes.com/docs/yaml/
+#
+# Site settings
+# These are used to personalize your new site. If you look in the HTML files,
+# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
+# You can create any custom variable you would like, and they will be accessible
+# in the templates via {{ site.myvariable }}.
+
+title: Andrew Tomaka
+email: atomaka@atomaka.com
+description: >- # this means to ignore newlines until "baseurl:"
+ Personal website of Andrew Tomaka
+baseurl: "" # the subpath of your site, e.g. /blog
+url: "https://www.atomaka.com" # the base hostname & protocol for your site, e.g. http://example.com
+github_username: atomaka
+favicon: favicon.ico
+
+# Build settings
+theme: no-style-please
+theme_config:
+ appearance: "auto" # can be "light", "dark" or "auto"
+plugins:
+ - jekyll-feed
+ - jekyll-gist
+
+# Exclude from processing.
+# The following items will not be processed, by default.
+# Any item listed under the `exclude:` key here will be automatically added to
+# the internal "default list".
+#
+# Excluded items can be processed by explicitly listing the directories or
+# their entries' file path in the `include:` list.
+#
+exclude:
+ - .ruby-version
+ - build.sh
+ - old/
+ - README.md
+# - .sass-cache/
+# - .jekyll-cache/
+# - gemfiles/
+# - Gemfile
+# - Gemfile.lock
+# - node_modules/
+# - vendor/bundle/
+# - vendor/cache/
+# - vendor/gems/
+# - vendor/ruby/
diff --git a/_data/menu.yml b/_data/menu.yml
new file mode 100644
index 0000000..f46c3bf
--- /dev/null
+++ b/_data/menu.yml
@@ -0,0 +1,27 @@
+# For documentation on this file, see:
+# https://github.com/riggraz/no-style-please#customize-the-menu
+
+entries:
+ - title: info
+ url: false
+ entries:
+ - title: coding
+ url: https://github.com/atomaka
+ - title: emailing
+ url: mailto:atomaka@atomaka.com
+ - title: speaking
+ url: https://slides.com/atomaka
+ - title: tooting
+ url: https://pub.atomaka.com/@atomaka
+ - title: working
+ url: https://www.linkedin.com/in/atomaka
+
+ - title: all posts
+ post_list:
+ limit: 5
+ show_more: true
+ show_more_text: See archive...
+ show_more_url: archive
+
+ - title: rss
+ url: feed.xml
diff --git a/_posts/2012-10-25-force-print-document-on-11x17-scaled.md b/_posts/2012-10-25-force-print-document-on-11x17-scaled.md
new file mode 100644
index 0000000..2908300
--- /dev/null
+++ b/_posts/2012-10-25-force-print-document-on-11x17-scaled.md
@@ -0,0 +1,61 @@
+---
+layout: post
+title: Force "Print Document on" 11x17 Scaled
+tag:
+ - technical
+---
+
+The Print Spooler API in Windows does not seem to have an option to force
+scaling to another paper size. Formerly, we would install the printer save the
+registry key in `HKCU\Printers\DevModePerUser`. Then, we could check the "Print
+Document On" option, apply the settings, and save the registry key again.
+Performing a diff of between the two sets of roughly 4000 hex values should give
+a subset of values that relate to "Print Document On." Finally, on installation
+we could read in the registry key after everything else had been setup, cycle
+through it changing the appropriate values based on our diff and then save the
+registry key. This stopped working.
+
+No new diffs could be collected that would update the scale to fit functionality
+that we needed. However, if the "Print Document On" option is manually set and
+the registry key is collected, that key can be used as the "diff" and the newly
+added printer would print scaled as desired. This has the unfortunate side
+effect of modifying all other settings on the printer including the name and
+color settings. As a work around, two different registry key "diffs" are used:
+one for color and one for black&white. Then, the first 30 hex characters can be
+chopped off in each key to make sure the printer name is not overwritten.
+
+```
+#include ;
+
+int stf[][2] = {
+ {8, 0},
+ {10, 0},
+ // and more keys
+};
+
+int setPrintDocumentOn(char *printerName) {
+ HKEY hkey;
+
+ // find the tree where the key we need to change resides
+ RegOpenKey(HKEY_CURRENT_USER, "Printers\\DevModePerUser", &hkey);
+
+ DWORD requiredSize = 0;
+ DWORD dataType;
+
+ // read in the key
+ RegQueryValueEx(hkey, printerName, 0, &dataType, NULL, &requiredSize);
+ char *DevModePerUserData = malloc(requiredSize);
+ RegQueryValueEx(hkey, printerName, 0, &dataType, (BYTE *)DevModePerUserData, &requiredSize);
+
+ // update the key
+ int i = 0;
+ for(i = 0; i < sizeof(stf) / 8; i++) {
+ DevModePerUserData[stf[i][0]] = stf[i][1];
+ }
+
+ // and save our updates
+ RegSetValueEx(hkey, printerName, 0, REG_BINARY, (BYTE *)DevModePerUserData, requiredSize);
+ RegFlushKey(hkey);
+ RegCloseKey(hkey);
+}
+```
diff --git a/_posts/2013-02-02-serious-regular-expressions.md b/_posts/2013-02-02-serious-regular-expressions.md
new file mode 100644
index 0000000..59e912e
--- /dev/null
+++ b/_posts/2013-02-02-serious-regular-expressions.md
@@ -0,0 +1,14 @@
+---
+layout: post
+title: Serious Regular Expressions
+tag:
+ - humor
+---
+
+```
+$n = '[0-9]';
+$reg = '/^[AZ]'.$n.$n.$n.$n.$n.$n.$n.$n.'$/';
+if(preg_match($reg, $id)) {
+ // ...
+}
+```
diff --git a/_posts/2013-09-25-password-checking-in-c.md b/_posts/2013-09-25-password-checking-in-c.md
new file mode 100644
index 0000000..7c1745f
--- /dev/null
+++ b/_posts/2013-09-25-password-checking-in-c.md
@@ -0,0 +1,58 @@
+---
+layout: post
+title: Password Checking in C
+tag:
+ - humor
+---
+
+```
+if (strlen(encrytedenteredpassword) != 13) {
+ passwordcorrect=0;
+} else {
+ for (i=0; i<13;i++) {
+ switch (i) {
+ case 0:
+ if (encrytedenteredpassword[i] != 'f') passwordcorrect=0;
+ break;
+ case 1:
+ if (encrytedenteredpassword[i] != 'J') passwordcorrect=0;
+ break;
+ case 2:
+ if (encrytedenteredpassword[i] != 'c') passwordcorrect=0;
+ break;
+ case 3:
+ if (encrytedenteredpassword[i] != 'l') passwordcorrect=0;
+ break;
+ case 4:
+ if (encrytedenteredpassword[i] != 'Q') passwordcorrect=0;
+ break;
+ case 5:
+ if (encrytedenteredpassword[i] != 'v') passwordcorrect=0;
+ break;
+ case 6:
+ if (encrytedenteredpassword[i] != 'P') passwordcorrect=0;
+ break;
+ case 7:
+ if (encrytedenteredpassword[i] != 'i') passwordcorrect=0;
+ break;
+ case 8:
+ if (encrytedenteredpassword[i] != 'l') passwordcorrect=0;
+ break;
+ case 9:
+ if (encrytedenteredpassword[i] != 'N') passwordcorrect=0;
+ break;
+ case 10:
+ if (encrytedenteredpassword[i] != 'A') passwordcorrect=0;
+ break;
+ case 11:
+ if (encrytedenteredpassword[i] != 'z') passwordcorrect=0;
+ break;
+ case 12:
+ if (encrytedenteredpassword[i] != '.') passwordcorrect=0;
+ break;
+ default: passwordcorrect=0; break;
+ }
+ if (!passwordcorrect) break;
+ }
+}
+```
diff --git a/_posts/2014-01-19-intro-to-puppet.md b/_posts/2014-01-19-intro-to-puppet.md
new file mode 100644
index 0000000..8763904
--- /dev/null
+++ b/_posts/2014-01-19-intro-to-puppet.md
@@ -0,0 +1,300 @@
+---
+layout: post
+title: 'Intro to Puppet: The Bare Minimum'
+tag:
+ - puppet
+ - technical
+---
+
+Last month, some of my coworkers were looking for a brief introduction to
+[Puppet](http://www.puppetlabs.com/). Puppet is a type of configuration manager
+for your servers. It allows you to create definitions of your server that can
+then be automatically maintained. Puppet is mostly self documenting so it makes
+it easy to know what your servers are doing while giving you a great way to
+automate setting up large numbers of servers.
+
+This is that brief talk. All code is available on
+[Github in my puppet-walkthru repository](https://github.com/atomaka/puppet-walkthru).
+You will need [Git](http://www.git-scm.com/),
+[Virtual Box](https://www.virtualbox.org/) and
+[Vagrant](http://www.vagrantup.com/) installed. To begin, clone the repository
+and launch the Vagrantfile:
+
+```
+git clone https://github.com/atomaka/puppet-walkthru.git
+cd puppet-walkthru
+vagrant up
+```
+
+This will setup a virtual machine on your computer with Puppet installed. All
+code can be found on the virtual machine in the /vagrant directory.
+
+```
+vagrant ssh
+sudo su cd /vagrant
+```
+
+You are now ready to work through the first example.
+
+## 1. Managing Users
+
+Puppet maintains state on your computer using what are referred to as
+[resources](http://docs.puppetlabs.com/references/latest/type.html). The
+built-in resources provided by Puppet provide a good start. In
+[example one](https://github.com/atomaka/puppet-walkthru/blob/master/manifests/1-user-type.pp),
+you can see how to use a Puppet resource to add and remove a user.
+
+```
+user { 'tm':
+ ensure => present,
+}
+user { 'fowlks':
+ ensure => absent,
+}
+```
+
+You can run this code on your virtual machine with
+`puppet apply manifests/1-user-type.pp`. Afterward, you should notice that the
+user "tm" exists on your system.
+
+The [user resource](http://docs.puppetlabs.com/references/latest/type.html#user)
+type manages local users on your system. This works on a wide variety of
+systems, although some do not support some of the more specific features. In
+this example, we make sure the user "tm" is present on the system and make sure
+the user "fowlks" is not present.
+
+ensure is a keyword for all Puppet resources. present and absent are the most
+common values although some resource types have others. ensure will make sure
+that definition exists on your server and absent will obviously do the opposite.
+
+## 2. Managing Files
+
+Managing files is one of the most common tasks for server administration and
+Puppet offers many ways to handle this. We’ll explore these in the
+[next example](https://github.com/atomaka/puppet-walkthru/blob/master/manifests/2-file-type.pp).
+
+```
+file { '/tmp/test1.txt':
+ ensure => present,
+ content => 'Hello',
+}
+file { '/tmp/test2.txt':
+ ensure => present,
+ source => '/vagrant/files/test2.txt',
+}
+$something = "Hello"
+file { '/tmp/test3.txt':
+ ensure => present,
+ content => template('/vagrant/templates/test3.txt.erb'),
+}
+```
+
+Run this on your virtual machine using `puppet apply manifests/2-file-type.pp`
+and you should be alerted that three files were created. You can verify this by
+viewing the contents of the tmp directory with `ls /tmp`.
+
+The first
+[file resource](http://docs.puppetlabs.com/references/latest/type.html#file)
+simply creates a file at the specified location that says "Hello."
+Unfortunately, this isn’t very useful since we do not want to have to type our
+entire cnfiguration file in our Puppet definition. The second resource is
+slightly more useful. This allows us to copy a file from our Puppet repository
+to a specified location.
+
+Finally, we can also create templates. The last example uses a file from our
+repository and copies it to the specified location. However, we can also include
+variables that can be used in our file. In this case, we set a variable to
+something and it is then displayed in the file: `You said: Hello`. The contents
+of `$something` are used in the file.
+
+## 3. Installing Packages
+
+The last common task we’ll look at is installing packages. Puppet provides a way
+to define which
+[packages](http://docs.puppetlabs.com/references/latest/type.html#package) can
+be installed. By default, this uses your distributions built-in package manager
+although there are ways to specify various providers. Our example
+[shows the most basic usage](https://github.com/atomaka/puppet-walkthru/blob/master/manifests/3-package-type.pp).
+
+```
+package { 'vim':
+ ensure => present,
+}
+package { 'alpine-pico':
+ ensure => absent,
+}
+```
+
+Try to open vim and you will notice it cannot run. Once you run this code with
+`puppet apply manifests/3-package-type.pp`, the vim package will then be
+present.
+
+## 4. Ordering (or lack thereof)
+
+The trickest thing for beginners to Puppet is dealing with its
+[non-deterministic behavior](http://puppetlabs.com/blog/inside-puppet-about-determinism).
+This is easier to
+[show than explain](https://github.com/atomaka/puppet-walkthru/blob/master/manifests/4-order-example.pp).
+
+```
+notify { 'First': }
+notify { 'Second': }
+notify { 'Third': }
+notify { 'Fourth': }
+notify { 'Fifth': }
+notify { 'Sixth': }
+notify { 'Seventh': }
+```
+
+When run, you would expect this to spit out First, Second, …, Seventh in order.
+Invoke this code with `puppet apply manifests/4-order-example.pp` and be
+surprised at the results. The order of the code is much different than what is
+in the file. Furthermore, if you were to add `notify { 'Eighth': }` the ordering
+might change completely.
+
+## 5. But I Need Order
+
+But there are dependencies when setting up systems. Puppet allows for this, you
+just are required to
+[explicitly define them](https://github.com/atomaka/puppet-walkthru/blob/master/manifests/5-ordered-example.pp).
+The biggest advantage here is that if one line of dependencies fails, your
+entire configuration does not. It takes some getting used to and can be
+frustrating, but it is worth it.
+
+```
+notify { 'First': }
+notify { 'Second':
+ require => Notify['First'],
+}
+notify { 'Third':
+ require => Notify['Second'],
+}
+notify { 'Fourth':
+ require => Notify['Third'],
+}
+notify { 'Fifth':
+ require => Notify['Fourth'],
+}
+notify { 'Sixth':
+ require => Notify['Fifth'],
+}
+notify { 'Seventh':
+ require => Notify['Sixth'],
+}
+```
+
+By using the `require` parameter, we have have forced ordering. If you run this
+code with `puppet apply manifests/5-ordered-example.pp`, you will see the order
+you expected in example number four.
+
+## 6. Know Your Environment
+
+Puppet also provides a way for you to know about the system that the Puppet code
+is running on with a system called Facter.
+
+```
+notify { "${::osfamily}": }
+notify { "${::ipaddress}": }
+notify { "${::uptime}": }
+```
+
+When run with `puppet apply manifests/6-facts-example.pp`,
+[this code](https://github.com/atomaka/puppet-walkthru/blob/master/manifests/6-facts-example.pp)
+will display the information about the virtual machine you are running on. We
+will look at why this is useful later.
+
+## 7. Doing Something Useful
+
+Now that we have seen some quick forced examples of how to use Puppet, we now
+have enough knowledge to do something that is actually useful. Using Puppet, we
+can
+[configure an entire service](https://github.com/atomaka/puppet-walkthru/blob/master/manifests/7-full-example.pp).
+If you are not familiar, [NTP](http://www.ntp.org/) is a networking protocol for
+time management. It is useful for mainitaining the same system time across all
+of your servers. And we can use Puppet to install it!
+
+```
+package { 'ntp':
+ ensure => present,
+}
+file { '/etc/ntp.conf':
+ ensure => present,
+ require => Package['ntp'],
+ source => '/vagrant/files/ntp.conf.debian',
+}
+service { 'ntp':
+ ensure => running,
+ enable => true,
+ subscribe => File['/etc/ntp.conf'],
+}
+```
+
+When running this code with `puppet apply manifest/7-full-example.pp`, you
+should notice three things happen. First, the ntp package will be installed.
+Since we are on Ubuntu, this is done using apt-get. Secondly, a configuration
+file was copied from our Puppet repository to the location specified. Finally,
+the ntp service was started.
+
+Install, configure, start is one of the most common patterns in Linux/UNIX
+systems administration and we can easily automate it with Puppet.
+
+Something to note is our use of subscribe when using the
+[service resource](http://docs.puppetlabs.com/references/latest/type.html#service)
+type. This makes sure that the ntp service is restarted only if the
+configuration file has changed.
+
+## 7. Managing Multiple Operating Systems
+
+Before this section, be sure to reset what we did in the previous example by
+running bash support/cleanup7.sh. We just need to uninstall ntp and our config
+file so we can do it all again.
+
+Unfortunately, our environments are never uniform and we are stuck dealing with
+different versions of operating systems. Luckily, we have tools that we can use
+to deal with it. We touched on this in section six, but now we will actually use
+them
+[to install ntp again](https://github.com/atomaka/puppet-walkthru/blob/master/manifests/8-independent-example.pp).
+This time, our code will work on both Debian and RedHat family Linux
+distributions.
+
+```
+case $::osfamily {
+ 'RedHat': {
+ $service = 'ntpd'
+ $conf = 'ntp.conf.redhat'
+ }
+ 'Debian': {
+ $service = 'ntp'
+ $conf = 'ntp.conf.debian'
+ }
+}
+notify { 'OS Information':
+ message => "${::osfamily}: Setting service to ${service} and conf to ${conf}",
+ before => Package['ntp'],
+}
+package { 'ntp':
+ ensure => present,
+}
+file { '/etc/ntp.conf':
+ ensure => present,
+ require => Package['ntp'],
+ source => "/vagrant/files/${conf}",
+}
+service { $service:
+ ensure => running,
+ enable => true,
+ subscribe => File['/etc/ntp.conf'],
+}
+```
+
+When on our Ubuntu virtual machine, running this code with
+`puppet apply manifest/8-independent-example.pp` will setup NTP just as we did
+in example seven. However, this code can also run on RedHat / CentOS machines
+without any adjustments.
+
+This is handled using the facts we discussed in section six. We check to see
+what distribution we are using with `$::osfamily` and make choices based on
+that. Since the service and the config file are different on RedHat, we assign
+variables to these and adjust them as needed.
+
+You now have enough knowledge to get started with Puppet!
diff --git a/_posts/2014-02-11-get-away-from-me-you-creep.md b/_posts/2014-02-11-get-away-from-me-you-creep.md
new file mode 100644
index 0000000..e306789
--- /dev/null
+++ b/_posts/2014-02-11-get-away-from-me-you-creep.md
@@ -0,0 +1,78 @@
+---
+layout: post
+title: Get Away From Me You Creep
+tag:
+ - humor
+---
+
+Almost ten years ago, I took a telecommunication history with course with one of
+the most eccentric people I had ever met. Unfortunately, it was during a time
+where I was attending very few courses and I missed most of my opportunities to
+listen to him speak. Still, I managed to make it to enough classes to have
+distinct memories of him. Dr. Barry Litman passed away a few years ago and these
+are his stories.
+
+I attended the first day of class just as I did the first day of every class I
+took. I sat down and was probably scribbling in the notepad I purchased that I
+knew would never be used or barely staying awake. He began giving a brief
+overview the history of telecommunication in extreme story telling mode with an
+unprecedented excitement. I don’t remember anything from that day except for the
+way he ended class: “And just like that, the entire industry evolved into a star
+just waiting to supernova.”
+
+I explained this to a couple of students I was working with and they immediately
+knew who I was talking about. They warned me about David Sarnoff but would not
+give me any other information. I was forced to attend class for several sessions
+before the story was revealed.
+
+David Sarnoff was a corporate kingpin during the pioneering of radio and
+television serving as an executive for the Radio Corporation of America. Dr.
+Litman was visibly agitated as he explained this and other RCA history to the
+class. And then he began talking about Edwin Armstrong.
+
+Edwin Armstrong was an employee of RCA and eventually credited inventor of FM
+radio. He developed this while working for RCA, but Sarnoff saw it as a threat
+to the AM technology that the company was already producing. Because of this and
+their focus on television, Sarnoff and RCA chose not to purchase the patents for
+the technology. But after hearing the quality and seeing its success, RCA first
+tried to have the FCC ban usage of the wave and eventually claimed the invention
+of the technology and won the patent. Armstrong spent nearly all his time and
+money fighting for the rights to his own technology.
+
+As he was explaining these details, Litman went from agitated to infuriated. His
+face reddened, he began sweating and spoke louder and louder. The entire class
+was looking around at each other and no one knew how to respond.
+
+He eventually came to the close of the story. Armstrong ended up committing
+suicide. And even though he was eventually given the credit he deserved, it came
+too late. The professor was visibly exhausted and saddened but managed to
+literally spit out one final angry yell: “And it was all because of that son of
+a bitch, David Sarnoff.” He then walked out of the room.
+
+I mostly stopped going to class after that. I don’t know why. He was an
+incredible teacher and his enthusiasm kept me interested during most lectures.
+In the few classes I did attend he frequently referenced Vanna White as someone
+who used to be one of his favorite people, but never expanded the story. The
+last day before finals I went to class in hopes of getting some hints for the
+final. Instead, he shared his story.
+
+He explained to us that once a year, he and one of his close friends/colleagues
+would attend a conference related to telecommunication. A few years prior, Vanna
+White was attending something loosely related and he managed to convince his
+friend to attend. Vanna White’s booth was highly trafficked and Litman was
+forced to wait in line for three hours to see her. During this time, he was
+extremely nervous which led to him soaking through his shirt with sweat. When it
+was finally his turn to meet her, he walked up and blurted out about how big of
+a fan he was and how long he had followed her.
+
+And then he paused. I remember it feeling like ten minutes, but it was probably
+closer to one. Finally, he asked the class “And do you know what that bitch said
+to me?” He walked over to the side of the classroom and held the button to
+retract the overhead. Slowly, the words she spoke were revealed having been
+written in chalk on the board before the class had begun:
+
+"Get away from me, you creep."
+
+I wish I had written about these ten years ago. Even then, I wouldn’t have done
+the man justice. Truly great speakers are rare and it’s unfortunate he passed so
+soon.
diff --git a/_posts/2015-11-21-dockerizing-lubot.md b/_posts/2015-11-21-dockerizing-lubot.md
new file mode 100644
index 0000000..70dbc4c
--- /dev/null
+++ b/_posts/2015-11-21-dockerizing-lubot.md
@@ -0,0 +1,143 @@
+---
+layout: post
+title: Dockerizing Lubot
+tag:
+ - docker
+ - technical
+---
+
+Lubot is the [Lansing Codes](http://lansing.codes/) chat bot responsible for
+bringing updates about all local events to chatters everywhere…or just in
+Lansing. Previously, it resided on a Heroku Free instance and was required to
+sleep for six hours out of every twenty-four hours. After some issues with him
+waking up, we began looking for alternatives. Since I already had a server
+hosting several Docker containers, it seemed like the best choice.
+
+Docker is basically a way to create a container that can be easily distributed
+across many operating systems. Using it, we can take the code, runtime, and
+libraries that Lubot requires and put them in a package. You can read more about
+it in the
+[Official “What is Docker” article](https://www.docker.com/what-docker).
+
+To begin, we need to determine the necessary dependencies for our application.
+Lubot is built using NodeJS and uses npm to manage dependencies. Specifically,
+we are using Node v5.0.0 and npm v3.3.9. There’s an official Node Dockerfile to
+use to begin with so it is pretty easy to start.
+
+```
+FROM node
+
+ENV NODE_VERSION 5.0.0
+ENV NPM_VERSION 3.3.9
+```
+
+After that, we want to take care of the dependencies for our application.
+Because of the way Docker works, we want to cache this step so when our
+packages.json file does not change, we do not have to rebuild our dependencies.
+
+```
+ADD package.json /tmp/
+RUN cd /tmp && npm install
+RUN mkdir -p /opt/hubot && cp -a /tmp/node_modules /opt/hubot
+```
+
+Then, we need to add the application code to the container.
+
+```
+ADD . /opt/hubot
+WORKDIR /opt/hubot
+```
+
+Finally, we can start the service.
+
+```
+CMD ["/opt/hubot/bin/hubot", "--adapter", "slack"]
+```
+
+Combine these steps and we end up with a
+[Dockerfile](https://github.com/lansingcodes/lubot/blob/master/Dockerfile). This
+gets added to the repisitory so that we can build the application. Building an
+image is easy.
+
+```
+docker build -t lansingcodes/lubot .
+```
+
+This will download and build the necessary filesystems, caching where necessary
+and giving us a runable container image. Starting the container is also simple.
+
+```
+docker run lansingcodes/lubot
+```
+
+Lubot expects some environment variables to be there. But since we are in a
+container, no environment variables exist on the system and we need to pass them
+in. Our new run command accounts for this.
+
+```
+docker run -d --restart=always --name lubot \
+ -e HUBOT_SLACK_TOKEN=$HUBOT_SLACK_TOKEN \
+ -e TWITTER_LANSINGCODES_CONSUMER_KEY=$TWITTER_LANSINGCODES_CONSUMER_KEY \
+ -e TWITTER_LANSINGCODES_CONSUMER_SECRET=$TWITTER_LANSINGCODES_CONSUMER_SECRET \
+ -e TWITTER_LANSINGCODES_ACCESS_TOKEN=$TWITTER_LANSINGCODES_ACCESS_TOKEN \
+ -e TWITTER_LANSINGCODES_ACCESS_TOKEN_SECRET=$TWITTER_LANSINGCODES_ACCESS_TOKEN_SECRET \
+ -e GOOGLE_API_KEY=$GOOGLE_API_KEY \
+ -e LUBOT_MEETUP_API_KEY=$LUBOT_MEETUP_API_KEY \
+ -e TZ=$TZ \
+ -e REDIS_URL=$REDIS_URL \
+ lansingcodes/lubot
+```
+
+Lubot is now running in a container. However, Heroku also provided easy
+continuous deployment when combined with [Circle CI](https://circleci.com/).
+Being able to have changes deployed when the master branch changes is handy.
+Circle CI allows us to specify post-build commands to run. Typically, we’d want
+to build the container on our CI server and then push to a Docker registry, butI
+didn’t have one of those available. We can still use Circle CI to execute
+commands on a remote server with SSH. This makes our deploy process simple.
+
+- clone the repository on our remote server
+- build the docker image from that repositry
+- run the docker image that was build
+
+Our CI build file will trigger these actions via a script.
+
+```
+scp deploy/deploy.sh lubot@app.atomaka.com:/home/lubot
+ssh lubot@app.atomaka.com "bash /home/lubot/deploy.sh"
+```
+
+And then, deploy.sh will take care of the parts we already discussed.
+
+```
+#!/bin/bash
+
+cd $HOME
+source lubotrc
+
+git clone https://github.com/lansingcodes/lubot.git
+
+cd $HOME/lubot
+sudo docker build -t lansingcodes/lubot .
+cd $HOME
+rm -rf $HOME/lubot
+
+sudo docker rm -f lubot
+sudo docker run -d --restart=always --name lubot \
+ -e HUBOT_SLACK_TOKEN=$HUBOT_SLACK_TOKEN \
+ -e TWITTER_LANSINGCODES_CONSUMER_KEY=$TWITTER_LANSINGCODES_CONSUMER_KEY \
+ -e TWITTER_LANSINGCODES_CONSUMER_SECRET=$TWITTER_LANSINGCODES_CONSUMER_SECRET \
+ -e TWITTER_LANSINGCODES_ACCESS_TOKEN=$TWITTER_LANSINGCODES_ACCESS_TOKEN \
+ -e TWITTER_LANSINGCODES_ACCESS_TOKEN_SECRET=$TWITTER_LANSINGCODES_ACCESS_TOKEN_SECRET \
+ -e GOOGLE_API_KEY=$GOOGLE_API_KEY \
+ -e LUBOT_MEETUP_API_KEY=$LUBOT_MEETUP_API_KEY \
+ -e TZ=$TZ \
+ -e REDIS_URL=$REDIS_URL \
+ lansingcodes/lubot
+```
+
+Deploying Lubot is now just as easy as it was with Heroku and he never has to
+sleep again.
+
+- [Other details surrounding the deployment](https://github.com/lansingcodes/lubot/tree/master/deploy)
+- [Lubot repository](https://github.com/lansingcodes/slackbot)
diff --git a/_posts/2016-11-05-testing-your-docker-images-with-gitlab-ci.md b/_posts/2016-11-05-testing-your-docker-images-with-gitlab-ci.md
new file mode 100644
index 0000000..c77e98c
--- /dev/null
+++ b/_posts/2016-11-05-testing-your-docker-images-with-gitlab-ci.md
@@ -0,0 +1,86 @@
+---
+layout: post
+title: Testing Your Docker Images with GitLab CI
+tag:
+ - continuous-integration
+ - gitlab
+ - docker
+ - devops
+---
+
+I have been using [GitLab](https://about.gitlab.com) for over four years. My
+[first commit](https://github.com/gitlabhq/gitlabhq/commit/0760ba3efb7566b9f56bb066f4b15ba8ea34e1e7)
+to the project came nearly three years ago. And although I was pretty
+disappointed when they began
+[releasing an enterprise edition](https://about.gitlab.com/2013/07/22/announcing-gitlab-enterprise-edition/),
+the community edition of the project remains impressive. More recently, GitLab
+has included a
+[continuous integration software](https://about.gitlab.com/gitlab-ci/) along
+with their code collaboration solution.
+
+Recently, I have been using this to produce [Docker](https://www.docker.com/)
+images for my production environment. Although I had been using Docker for all
+of my build stages, I was never using the image I was producing for validation.
+Since I want to be as sure as I can that my production images are functioning, I
+decided to update my build to use the project Dockerfile to run tests.
+
+I looked around and found a
+[few](http://sirile.github.io/2016/09/29/minimal-go-containers-with-docker-and-gitlab-ci.html)
+[articles](https://www.andrewmunsell.com/blog/ci-cd-with-docker-containers/) on
+using Docker with Gitlab CI. Unfortunately, they all outlined methods that
+[did not test the image](https://www.stefanwienert.de/blog/2015/11/07/gitlab-ci-with-docker-starting-guide/)
+directly or did so in a
+[complicated way](http://blog.lwolf.org/post/How-to-build-and-test-docker-images-in-gitlab-ci/).
+I thought I could do better.
+
+We always want to use Docker for our builds, but running Docker inside of Docker
+is not recommended. To resolve this, we can mount the host system’s Docker
+socket inside the container when creating our test runner for building images.
+
+```
+[[runners]]
+ name = "docker-runner"
+ url = "https://gitlab.example.com/ci"
+ token = "YOUR_TOKEN"
+ executor = "docker"
+ [runners.docker]
+ tls_verify = false
+ image = "docker:latest"
+ privileged = false
+ disable_cache = false
+ volumes = ["/var/run/docker.sock:/var/run/docker.sock"]
+```
+
+Now that we are using the host Docker, we can leverage its image storage and
+caching for our build. We can also use that image in our other build tasks.
+
+```
+stages:
+ - prepare
+ - test
+ - deploy
+
+build-test-container:
+ stage: prepare
+ script:
+ - docker build -t your-image .
+ tags:
+ - your-docker-tag
+
+spec:
+ stage: test
+ script:
+ - bundle exec rake db:create db:migrate
+ - bundle exec rspec
+ image: your-image
+ services:
+ - postgres:latest
+
+# ...
+```
+
+The container built from our project Dockerfile is now being directly tested by
+our continuous integration. As you can see, we can also use any container links
+without writing extra code.
+
+Clean and simple!
diff --git a/_posts/2016-11-18-singular-and-plural-rails-routes-for-the-same-resource.md b/_posts/2016-11-18-singular-and-plural-rails-routes-for-the-same-resource.md
new file mode 100644
index 0000000..877cf14
--- /dev/null
+++ b/_posts/2016-11-18-singular-and-plural-rails-routes-for-the-same-resource.md
@@ -0,0 +1,72 @@
+---
+layout: post
+title: Singular and Plural Rails Routes for the Same Resource
+tag:
+ - api
+ - ruby-on-rails
+ - restful
+---
+
+Sometimes when building your API with Rails,
+[following best practices](http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api)
+may seem difficult. I recently came across one of these cases and was tempted to
+take a shortcut. However, I held strong and eventually came to a quality RESTful
+solution — but not without issue.
+
+I wanted to allow users of my API to quickly access their own user profile. Our
+application had already implemented a route to allow this via
+`GET /profiles/:id` and simply implemented with
+`resources :profiles, only: [:show]` in our routes configuration.
+
+Unfortunately, our API users wanted to be able to access their profile without
+providing their ID. My first pass at resolving this was passed in a "fake
+resource" to accomplish this.
+
+{% gist 1a056f8dca8931d8872c6cfefebb2d1a %}
+
+But I had broken one of the RESTful best practices. /profiles/me is not an
+actual resource but we are pretending it is. So I looked to the
+[Rails routes documentation](http://guides.rubyonrails.org/routing.html) for
+guidance and came across
+[singular resources](http://guides.rubyonrails.org/routing.html#singular-resources).
+
+> Sometimes, you have a resource that clients always look up without referencing
+> an ID. For example, you would like /profile to always show the profile of the
+> currently logged in user.
+
+I should not have been surprised that my exact use case was cited!
+
+Now we are back on track! I get to go back to my simple route declaration with
+`resource :profile, only: :show` and without changing my controller code at all.
+
+But now I needed users to be able to access each other’s profiles. Again, the
+Rails documentation had me covered.
+
+> Because you might want to use the same controller for a singular route
+> (/account) and a plural route (/accounts/45), singular resources map to plural
+> controllers. So that, for example, resource :photo and resources :photos
+> creates both singular and plural routes that map to the same controller
+> (PhotosController).
+
+And our implementation stays clean.
+
+{% gist e8d6641349e4d0ea7e68d22dd3755e9d %}
+
+This was awesome until I needed to use path helpers. With this implementation,
+`profile_path(:id)` works as expected but `profile_path` does not. If the order
+is reversed in the routes configuration, `profile_path` will work and
+`profile_path(:id)` will not. This is the result of a bug in the Rails core that
+touches some pretty intricate code that is linked to other issues.
+[One has even been open for five years](https://github.com/rails/rails/issues/1769)!
+
+And we can work around that one as well by
+[overriding the named helpers](http://guides.rubyonrails.org/routing.html#overriding-the-named-helpers).
+Passing as: to our resource definition creates the helpers with a new name.
+
+Our final code is ready!
+
+{% gist e9dcc4cd4bad89554fb01be6627c7b63 %}
+
+In our application, we can reference a generic profile with `profile_path(:id)`
+while still having `current_profile_path` to direct the user to their
+own profile.
diff --git a/_posts/2017-03-01-a-more-flexible-dockerfile-for-rails.md b/_posts/2017-03-01-a-more-flexible-dockerfile-for-rails.md
new file mode 100644
index 0000000..0fe8e81
--- /dev/null
+++ b/_posts/2017-03-01-a-more-flexible-dockerfile-for-rails.md
@@ -0,0 +1,150 @@
+---
+layout: post
+title: A More Flexible Dockerfile for Rails
+tag:
+ - rails
+ - docker
+ - devops
+---
+
+One of my primary motivations for working with [Docker](https://www.docker.com/)
+was creating a single artifact that I could toss into any environment. It has
+been fantastic at this. I can throw together a simple Dockerfile that will build
+my [Rails](http://rubyonrails.org/) application as an image for production in
+about five minutes.
+
+```
+FROM ruby:2.3-alpine
+
+ADD Gemfile* /app/
+
+RUN apk add --no-cache --virtual .build-deps build-base \
+ && apk add --no-cache postgresql-dev tzdata \
+ && cd /app; bundle install --without test production \
+ && apk del .build-deps
+
+ADD . /app
+RUN chown -R nobody:nogroup /app
+USER nobody
+
+ENV RAILS_ENV production
+
+WORKDIR /app
+CMD ["bundle", "exec", "rails", "s", "-b", "0.0.0.0", "-p", "8080"]
+```
+
+Except now that when I need to run the application’s test suite, I do not have
+the dependencies I need. That Dockerfile might look something like this.
+
+```
+FROM ruby:2.3-alpine
+
+RUN apk add --no-cache build-base postgresql-dev tzdata
+
+ADD Gemfile* /app/
+
+RUN cd /app; bundle install
+
+ADD . /app
+RUN chown -R nobody:nogroup /app
+USER nobody
+
+
+WORKDIR /app
+CMD ["bundle", "exec", "rails", "s", "-b", "0.0.0.0", "-p", "8080"]
+```
+
+Many people decide to include both of these Dockerfiles in their repository as
+Dockerfile and Dockerfile.dev. This works perfectly fine. But now we have a
+production Dockerfile that never gets used during development. Of course, it is
+going through at least one staging environment (hopefully) but it would be nice
+if we had a little more testing against it.
+
+Much like Docker provides us the ability to have a single artifact to move from
+system to system, I wanted to have a single Dockerfile shared between all
+environments. Luckily, Docker provides us with
+[build arguments](https://docs.docker.com/engine/reference/builder/#/arg). A
+build argument allows us to specify a variable when building the image and then
+use that variable inside our Dockerfile.
+
+In our current Rails Dockerfile, we have two primary differences between our
+environments:
+
+- The gem groups that are installed
+- The environment that the application runs as
+
+Bundler’s
+[BUNDLE_WITHOUTBUNDLE_WITHOUT](http://bundler.io/man/bundle-config.1.html#LIST-OF-AVAILABLE-KEYS)
+allows us to specify the gem groups to skip via an environment variable making
+both of these resolvable through environment configuration. Using this, our
+shared Dockerfile could look like this:
+
+```
+FROM ruby:2.3-alpine
+
+ARG BUNDLE_WITHOUT=test:development
+ENV BUNDLE_WITHOUT ${BUNDLE_WITHOUT}
+
+ADD Gemfile* /app/
+
+RUN apk add --no-cache --virtual .build-deps build-base \
+ && apk add --no-cache postgresql-dev tzdata \
+ && cd /app; bundle install \
+ && apk del .build-deps
+
+ADD . /app
+RUN chown -R nobody:nogroup /app
+USER nobody
+
+ARG RAILS_ENV=production
+ENV RAILS_ENV ${RAILS_ENV}
+
+WORKDIR /app
+
+CMD ["bundle", "exec", "rails", "s", "-b", "0.0.0.0", "-p", "8080"]
+```
+
+The secret sauce here is `ARG BUNDLE_WITHOUT=test:development`. Running
+`docker build -t rails-app .` will use the default value provided for the
+`BUNDLE_WITHOUT` build argument, test:development, and a production Docker image
+will be built. And if we specify the appropriate build arguments, we can
+generate an image suitable for development.
+
+```
+docker build -t rails-app --build-arg BUNDLE_WITHOUT= --build-arg RAILS_ENV=development .
+```
+
+will generate our Docker image with all test and development dependencies
+available. Typing this for building in development would get pretty tedious so
+we can use docker-compose to make it easier
+
+```
+version: '2'
+services:
+ app:
+ build:
+ context: .
+ args:
+ - BUNDLE_WITHOUT=
+ - RAILS_ENV=development
+ links:
+ - database
+ ports:
+ - "3000:8080"
+ env_file:
+ - .env
+ volumes:
+ - .:/app
+ tty: true
+ stdin_open: true
+```
+
+Now, `docker-compose up -d` is all we need in development to both build and
+launch our development image.
+
+Finally, we have a single Dockerfile that can be used to build an image for any
+of our application’s needs. Of course, there are some trade-offs. For example,
+build time in development will suffer in some cases. But I have found only
+maintaining a single Dockerfile to be worth these costs.
+
+Have another way to deal with this issue? Please share!
diff --git a/_posts/2017-04-18-write-good-git-commits.md b/_posts/2017-04-18-write-good-git-commits.md
new file mode 100644
index 0000000..cc083ad
--- /dev/null
+++ b/_posts/2017-04-18-write-good-git-commits.md
@@ -0,0 +1,106 @@
+---
+layout: post
+title: Write Good Git Commits
+tag:
+ - git
+ - github
+---
+
+Writing quality Git commits has been written about to death, but it is so
+important that I could not help myself from sharing my thoughts on the subject.
+Mostly, I will be rehashing what
+[Tim Pope has shared](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html),
+but I will also include a few of the things that I have used to improve my
+source histories.
+
+### Limit the subject of your commit to 50 characters
+
+Many people live life as I do: at the command line. Limiting to 50 characters
+allows room for us to use an 80 character width for commands such as git rebase
+--interactive without width concerns. Even for those in a more modern IDE, the
+limit is important.
+
+![My helpful screenshot](/assets/gui-git.webp)
+
+As commit messages get longer, it becomes more difficult for everyone to
+traverse your history.
+
+### Use the commit body for important details
+
+It is very rare that I see people extend their commit histories into the body
+portion of a commit but it is the perfect place to offer extra details. Things
+like what resources you used to make a specific decision are better left in the
+commit history than in code comments most of the time. In a
+[recent commit to my dotfiles](https://github.com/atomaka/dotfiles/commit/28a3897995ff21f63f7893f43582532e4717b8d9),
+I added a quick alias to correct a TouchBar issue I was having.
+
+```
+Fix TouchBar when it (frequently) breaks
+
+From http://osxdaily.com/2017/01/11/manually-refresh-touch-bar-mac/ this
+will reset the control portion of the touch bar which has been
+frequently breaking in New and Interesting Ways™.
+```
+
+Without these details, I might never be able to find the source for why I
+added this.
+
+Also, limit the line length in the body to 72 characters.
+
+### Do not use the --message option
+
+Pretty much everyone I watch make a commit will do so directly at their command
+prompt with git commit -m. Forcing yourself into an editor will encourage you to
+add additional details about a commit message. Additionally, your editor can
+configured to alert you to the 50/72 rule. Simply add au FileType gitcommit set
+t==72 to your vimrc to auto wrap git messages at 72 characters if vim is
+configured as your Git editor. [vim-git](https://github.com/tpope/vim-git) is
+also a fantastic option that will highlight based on these rules.
+
+If you are struggling with breaking your -m habit, try creating a bash function
+to prevent its usage.
+
+```
+function git {
+ if [[ $@ == "commit -m" ]]; then
+ echo "Do not specify -m for commit"
+ else
+ command git "$@"
+ fi
+}
+```
+
+### Commit as if giving a command
+
+[How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/)
+made me consider the subject of my commits a little more. In bullet point 5,
+Chris says "Use the imperative mood in the subject line." Considering Git itself
+follows this rule, it made perfect sense to jump on board.
+
+```
+Merge branch 'bugfix/correct-spacing'
+```
+
+And
+
+```
+Revert "Implement person CRUD"
+```
+
+The best advice I picked up was write your commit as if you are completing the
+following sentence: "If applied, this commit will..."
+
+### Rebase your branches, but leave master alone
+
+Rebasing is a heated topic in the community but the one thing that everyone can
+agree on is leaving master alone. Once your commit has made it there, it is
+history and should never be changed. However, your branch is your story. You get
+to tell it however you want so craft it in a way that is useful to the reader.
+
+For me, this is particularly important because the second thing I do when
+reviewing a new code base is look at the commit history to see to story of the
+application. Unfortunately, most are riddled with messages like "fixed typo" or
+"asdf" and the history becomes unreadable.
+
+Take care in crafting your git messages and you will find much more value in
+your git logs!
diff --git a/archive/index.md b/archive/index.md
new file mode 100644
index 0000000..4989fff
--- /dev/null
+++ b/archive/index.md
@@ -0,0 +1,4 @@
+---
+layout: archive
+title: Archive
+---
diff --git a/assets/gui-git.webp b/assets/gui-git.webp
new file mode 100644
index 0000000..1a84488
Binary files /dev/null and b/assets/gui-git.webp differ
diff --git a/atomaka.jpg b/atomaka.jpg
new file mode 100644
index 0000000..4adc28c
Binary files /dev/null and b/atomaka.jpg differ
diff --git a/build.sh b/build.sh
index c3d4e28..ee65950 100755
--- a/build.sh
+++ b/build.sh
@@ -1,9 +1,8 @@
#!/bin/bash
-rm -rf build/
-mkdir -p build/
+mdformat --wrap 80 _posts/
+bundle exec jekyll build
-cp index.html build/
-cp keybase.txt build/
-
-AWS_DEFAULT_REGION=us-east-2 aws s3 cp --recursive ./build s3://www.atomaka.com/
+aws s3 sync _site s3://www.atomaka.com \
+ --size-only \
+ --storage-class REDUCED_REDUNDANCY
diff --git a/colors.png b/colors.png
deleted file mode 100644
index cd1dcac..0000000
Binary files a/colors.png and /dev/null differ
diff --git a/favicon.ico b/favicon.ico
new file mode 100644
index 0000000..c6664bf
Binary files /dev/null and b/favicon.ico differ
diff --git a/index.html b/index.html
deleted file mode 100644
index 4e7bde6..0000000
--- a/index.html
+++ /dev/null
@@ -1,92 +0,0 @@
-
-
- Personal Website of Andrew Tomaka
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/index.markdown b/index.markdown
new file mode 100644
index 0000000..0671507
--- /dev/null
+++ b/index.markdown
@@ -0,0 +1,6 @@
+---
+# Feel free to add content and custom Front Matter to this file.
+# To modify the layout, see https://jekyllrb.com/docs/themes/#overriding-theme-defaults
+
+layout: home
+---
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..c05569e
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,2 @@
+mdformat
+mdformat-frontmatter