Mac + Docker Toolbox + HAProxy

Working with Docker Toolbox on a Mac is great. It makes it very easy to work with Docker continers and setting up interconnected services with Docker Compose. However, since the services are running in a virtual machine, accessing the services from a machine other than the Mac itself is not possible out of the box.

HAProxy

Installing and running HAProxy on the Mac will proxy any traffic from the VM to external hosts looking to access the service. I installed haproxy via homebrew with the command brew install haproxy.

With HAProxy installed, I set it up to proxy HTTPS traffic over to the VM. In my case, the VM was 192.168.99.100 and my Mac’s IP was 192.168.1.200. I saved the configuration below at /usr/local/etc/haproxy/haproxy.cfg.

global
  log  127.0.0.1  local0
  log  127.0.0.1  local1 notice
  maxconn  4096
  chroot   /usr/local/share/haproxy
  uid  99
  gid  99


defaults
  log   global
  mode  tcp
  option  dontlognull
  retries  3
  option  redispatch
  option  http-server-close
  maxconn  2000
  timeout connect  5000
  timeout client  50000
  timeout server  50000


frontend www_fe
  bind 192.168.1.200:443

  use_backend www


backend www
  timeout server 30s
  server www1 192.168.99.100:443

Launch daemon

With haproxy configured, I placed the launchd configuration at /Library/LaunchDaemons/com.zymbit.haproxy.plist and ran the command sudo launchctl load -w /Library/LaunchDaemons/com.zymbit.haproxy.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
 <key>Label</key>
 <string>com.zymbit.haproxy</string>
 <key>ProgramArguments</key>
 <array>
   <string>/usr/local/bin/haproxy</string>
   <string>-db</string>
   <string>-f</string>
   <string>/usr/local/etc/haproxy/haproxy.cfg</string>
 </array>
</dict>
</plist>

Starting and stopping launchd

Now, whenever I want external access to the Docker service I run the command launchctl start com.zymbit.haproxy and when I’m done launchctl stop com.zymbit.haproxy.

Manually booting from a Grub prompt

I installed Ubuntu on a Cisco UCS C250 M2 system with a USB flash drive. The installer attempted installing Grub on the installer drive instead of the system drive. In attempts to have a bootable system, I dropped to a shell and ran:

chroot /target /bin/bash
grub-install /dev/sdb (where sdb is drive you installed on)

The above installed Grub, but didn’t configure it to boot the system. After booting I landed at a grub prompt instead of the system prompt. I was able to boot the system with the steps below.

First, I ran the command below to get the drive’s UUID. Below <tab> is tapping the tab key on the keyboard:

ls (hd0<tab>

This prints out details of the drive; the UUID is needed in the command below.

insmod ext2
set root='hd0,msdos1'
linux /boot/vmlinuz<tab> root=UUID=<insert UUID here>
initrd /boot/initrd<tab>
boot

This properly booted the system. From here, the first thing to do is install Grub properly. Login to the system and run:

update-grub
grub-install /dev/sda

After a reboot the system booted properly.

Transplant commits with git rebase –onto

You are working along and then realize that all the work you did is based off the wrong branch. Instead of working off the branch wrong-branch, you should have been working off the branch right-branch. What to do?

First, as a safety create a fix branch off your current branch:

git checkout -b fix-topic-branch topic-branch

Now, take a look at the commits to find the ref your work is on top of:

git log --oneline --decorate

8cb0c1a (fix-topic-branch) Added artcode urls
1ff8dac Added art form
0670ee7 added django-resourceful requirement
633dda6 Added ArtView class
e64f05f Added models
4186ba8 Added pristine django app artcode
d49ad49 (wrong-branch) Merge branch 'add-test-finder' into baseline
[...]

In the case above the commits we want are on top of d49ad49, which is `wrong-branch`. With this info you can tell git rebase --onto to take all commits “on top of” d49ad49 in fix-topic-branch and plant them on top of right-branch.

git rebase --onto right-branch d49ad49 fix-topic-branch

Once you confirm fix-topic-branch looks as you expect, you can rename it back to topic-branch:

git branch -D topic-branch
git branch -m topic-branch

Fix sync button in GitHub for Windows

My friend Elyse is a chef in Sonoma County. I setup a website for her using Jekyll, GitHub for Windows, and Heroku. When she wants to update her website, she makes changes to Markdown files and clicks the “sync” button in GitHub for Windows to publish her changes. It works magnificently well … until it breaks, and GitHub for Windows is terrible at telling you what the error actually is.

After some searching I discovered the sync button performs two actions:

git pull --rebase
git push

At some point git pull --rebase failed and left behind a .git/rebase-apply directory. In order to fix this, open the shell as the error message suggests and run the command:

del .git/rebase-apply

Confirm that it should remove the entire folder, then close the shell. Retry the sync command and it should work.

Easily escape HTML for a WordPress post

Here’s a one-liner for converting angle brackets and other characters that need escaping. This will work on any system that has Python installed. Run this command:

python -c 'import cgi; import sys; print cgi.escape(sys.stdin.read())' | pbcopy

Once you hit enter on the command above, paste the content to convert and after pasting hit enter followed by ctrl+d.

If you’re not on OS X, remove the pipe to pbcopy. If you are on OS X, your converted text is now in your clipboard!

Auto-starting VirtualBox VMs on OS X


sudo cp \
/Applications/VirtualBox.app/Contents/MacOS/org.virtualbox.vboxautostart.plist \
/Library/LaunchDaemons

Then edit /Library/LaunchDaemons/org.virtualbox.vboxautostart.plist set Disabled to false, set KeepAlive to true, and confirm the last string entry in the command array is set to /etc/vbox/autostart.cfg. The file should look like this:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Disabled</key>
<false/>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>org.virtualbox.vboxautostart</string>
<key>ProgramArguments</key>
<array>
<string>/Applications/VirtualBox.app/Contents/MacOS/VBoxAutostartDarwin.sh</string>
<string>--start</string>
<string>/etc/vbox/autostart.cfg</string>
</array>
</dict>
</plist>

Make the directory /etc/vbox and create the file /etc/vbox/autostart.cfg with the following content:


# Default policy is to "deny" starting a VM, the other option is "allow".
default_policy = deny

berto = {
allow = true
}

Make sure to change berto to the username on your system that the VMs are under.

Next properly set permissions:


sudo chmod +x /Applications/VirtualBox.app/Contents/MacOS/VBoxAutostartDarwin.sh
sudo chown root:wheel /etc/vbox
sudo chown root:wheel /etc/vbox/autostart.cfg
sudo chown root:wheel /Library/LaunchDaemons/org.virtualbox.vboxautostart.plist

Now, configure the VMs that should automatically start and set how they should be stopped:

VBoxManage modifyvm jenkins --autostop-type acpishutdown
VBoxManage modifyvm chefpa-jenkins --autostart-enabled on

Finally, test the configuration by running:

sudo launchctl load /Library/LaunchDaemons/org.virtualbox.vboxautostart.plist

After a reboot, the VMs that have been set with autostart enabled should be running!

https://www.virtualbox.org/manual/ch09.html#autostart-osx
https://forums.virtualbox.org/viewtopic.php?f=8&t=51593&start=15#p240724
https://forums.virtualbox.org/viewtopic.php?f=11&t=51529#p236492

Updating the first commit in a git repo

I started a git repo in a VM without configuring an author and wanted to update all the commits, including the first one, which is a bit elusive.

The StackOverflow post Change first commit of project with git? almost nails it. For my use-case, or git version, I found Step 4 to be slightly incorrect. It states to use <commit after changed>, but I got it to work with the same hash used in Step 2. For example, say you are on the master branch and you want to update the author information for the first commit:


$ git checkout -b rename
$ first_commit=$(git rev-list HEAD | tail -n 1)
$ git reset --hard ${first_commit}
$ git commit --amend --author "Roberto Aguilar " -C HEAD
$ git rebase --onto rename ${first_commit} master

Now that the first commit is correct, I use the trick outlined in my Bulk Updating Author in Git to finish up the job:


$ new_first_commit=$(git rev-list HEAD | tail -n 1)
$ GIT_EDITOR="sed -i -e 's/^pick/edit/'" git rebase -i ${new_first_commit}
$ while [ 1 ]; do git commit --amend -C HEAD --author='Roberto Aguilar <roberto@baremetal.io' && git rebase --continue || break; done;