Meandering Soul

This day is done, I'm going home.
eFranes Penguin Avatar

Automating vagrant boxes on OS X

06
Jul 2014

A while ago, I said I would be writing about how to automate Laravel Homestead (or any other Vagrant box for that matter). As it turns out, I did not have to reboot my system for a very long stretch of time which in turn meant that I did not feel the need to automate something I wasn’t even doing manually in the first place. But enough already with the non goal-oriented writing. I love to automate tedious everyday or not so everyday tasks in order to

  1. gain more time doing productive work and
  2. worry less about system management.

To tackle the actual problem at hand, I tried to find out what exactly I wanted to automate. There are many parts of a Vagrant setup that can be automated (essentially almost all of them) but once, a few hundred days ago, there was an excellent xkcd that I try to keep in mind whenever I set out to automate some part of my workflow.


Ideally for me, Homestead should…

  • autostart after booting
  • suspend when on battery power and no network signal is available
  • resume once the above holds no longer true
  • halt before a system power down.

The part where I don’t want it running with no network signal and the system on battery is a fail save compensating for my machine being rather old which translates to not having that gorgeous battery life of the newer generation MacBooks. Halting the box before a system power down is not strictly necessary since even if some part of the box gets corrupted Vagrant will just redeploy it and you won’t even notice. But redeploying consumes avoidable time and system resources.

Anyway, that’s a lot of requirements and looking back at the above xkcd, I decided that I would actually be very satisfied with just having my Homestead environment start automagically whenever I have to reboot the system for now.

Fortunately, OS X provides several great instruments for automating workflows. The most powerful one is certainly the system’s launch daemon launchd which is OS X’s replacement for both cron and init.d like programs which you might know from other Unixes or Linuxes. As with most Apple software, launchd reads configuration files in the so-called property list format which is essentially a barebones dictionary representation for XML that feels really really ugly for first-time viewers. (Don’t worry, it will continue to feel strange.)

If you are new to launchd, you might want to go checkout this a little dated but wonderful primer.

Launchd can do all kinds of things based on all kinds of conditions but the most practical one for me is automatically starting software I want to be running in the background. To start Homebrew’s Vagrant box is easily done with something like the following configuration.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//E" http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.meanderingsoul.homestead-up</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/bin/vagrant</string>
      <string>up</string>
    </array>
    <key>WorkingDirectory</key>
    <string>/your/homestead/path</string>
    <key>KeepAlive</key>
    <dict>
      <key>SuccessfulExit</key>
      <false />
    </dict>
  </dict>
</plist>

Save the above at ~/Library/LaunchAgents/com.meanderingsoul.homestead-up but don’t forget to change ‘/your/homestead/path’ to the path to your Homestead configuration. Paths in launchd-configurations should always be absolute unless you specify the EnableGlobbing key. After saving the file, remember that these configurations must be executable, ergo chmod +x ~/Library/LaunchAgents/com.meanderingsoul.homestead-up. This will start Homestead after logging (e.g. rebooting the system.) Thankfully, vagrant will not up an environment if it is already running, thus a lot of security checks to avoid this can be omitted.

A note on starting for the first time

Just saving the Property List in the Launch Agents directory will not load it into the system. Eventhough it should be automatically loaded after the next reboot, you can do so manually with launchctl load ~/Library/LaunchAgents/com.meanderingsoul.homestead-up.plist. This will register the agent with the system. In order to directly run it, just type launchctl start com.meanderingsoul.homestead-up.

  • Published on July 06, 2014
  • 637 words

Setting up Laravel Homestead on OS X

20
May 2014

Laravel Homestead is a pre-configured Vagrant box along with some tooling to simplify administration of said box. For the uninitiated: Vagrant basically boils down to elegant tooling for virtual machines, radically reducing the effort needed to e.g. setup local testing environments like Homestead for Laravel.

Preconfiguration

To get Vagrant running, a virtual machine runner is required. I usually turn to Virtual Box for that. Thus, go ahead and grab the latest version from the downloads section now.

After having installed Virtual Box, your system is ready for Vagrant, the download page for which is here.

Actually setting up

Personally, I like to set up my test servers as projectname.dev, e.g. this website’s dev version is accessable as meanderingsoul.dev on my machine. As long as one is running the websites from OS X’s packaged Apache, everything is great and dandy but as soon as one leaves that comfort zone for something more elaborated like a vagrant box, things get a little bit messy. The above presented URL scheme requires binding a webserver to port 80 which is disallowed by operating systems for user processes. And one simply does not want to run stuff as root all the time. But there’s a fix for that, which I’ll explain in detail below. Right now, it’s time to fire up the terminal and get stuff configured.

1
2
3
4
# Add the homestead box to your vagrant repository
$ vagrant box add laravel/homestead
# Clone the Homestead configuration to a convenient place (you'll need it to start, stop and reconfigure the box)
$ git clone https://github.com/laravel/homestead.git Homestead

To configure Homestead, refer to the official documentation (linked above). What is important for setting up the environment to work with projectname.dev URLs is to adhere to the following URL scheme:

1
2
3
sites:
    - map: projectname.dev
      to: /home/vagrant/Code/ProjectName/public

The official documentation also advises you to add aliases for all mapped hosts into your /etc/hosts file. I usually go about that by typing

1
$ sudo echo "127.0.0.1 projectname.dev" >> /etc/hosts

to amend the added hostname to the list. This is not the most organized way to edit the hosts file and there are more elaborate options like nameservers if you need to manage lot’s of virtual hosts. But it should do for most cases.

At this point, you could just vagrant up the homestead box and access your projects via http://projectname.dev:8000. But nobody likes these port suffixes, right? So let’s get rid of them.

Enter Apache. OS X (even Mavericks) comes with a bundled version of the Apache Foundation’s httpd, much better known as the Apache Webserver or just Apache. Webservers, apart from serving content they have direct access to, are also usually capable of proxying requests to other hosts. This is especially handy in the current situation since the bundled apache runs as a system process and is therefore able to attach to port 80. What’s missing is a proxy configuration that transparently forwards every request to http://projectname.dev to http://projectname.dev:8000. Assuming that you did not mess with your systems’ Apache configuration before you can just paste the following into /etc/apache2/other/homestead.conf. If you messed with the config, you most certainly know how to unmess it such that this works.

1
2
3
4
5
6
<VirtualHost *:80>
    ProxyPreserveHost On
    ProxyRequests Off
    ProxyPass / http://localhost:8000/
    ProxyPassReverse / http://localhost:8000/
</VirtualHost>

Starting Apache is as simple as apachectl start. If everything went fine, you should see your Laravel site at http://projectname.dev in your browser. In a future post, I am going to explain how to automate the start-up process with launchd.

One more thing

Homestead’s machine name is homestead. If you’re using machine name based environment detection in Laravel you may want to add that hostname to the list of your local hostnames.

[Update] Yosemite

Sometimes, when updating to Yosemite, the system replaces Apache’s httpd.conf with it’s default version. You may thus need to include your homestead host config again. (Hint: This only applies to you if opening one of your .dev hosts results in the displayal of “It works!”)

  • Published on May 20, 2014
  • 668 words

Simplifying environment detection in Laravel

29
Apr 2014

Laravels environment detection is a pretty rock solid way of choosing a different configuration based on the current application environment. Currently, Laravel does this by looking up the machine’s hostname and checking into which environment it was sorted. The hash map for that is contained in bootstrap/start.php. Unfortunately, solely relying on the hostname can be a tedious job on two ends of the web app development spectrum.

On the one hand, if multiple people work on an app and want to use their local computer as a testing ground, all of their hostnames (or maybe some clever wildcards) may have to be added to the local environment.

On the other hand, when upscaling an app horizontally, a multitude of hosts running the code might be around. Adding all of their hostnames might cause an even bigger hassle since they might not even all be known at deploy time.

I’ve come up with “One ring to rule them all” kind of solution that reduces my environment selection array to the following:

1
2
3
4
$env = $app->detectEnvironment([
  // set LARAVEL_ENV = production on production systems
  $_SERVER['LARAVEL_ENV'] => [gethostname()]
]);

Now, all you have to do is export the LARAVEL_ENV variable to the user your app is executed with, which for local testing purposes can be as quick and easy as typing export LARAVEL_ENV='local' in your favorite shell.

Update

After some testing in the wild, I discovered a serious flaw with my above approach: It will fail horribly if the environment variable is not set. To fix this I went ahead and dropped in a basic catch-almost-all for local environments. If that one does not evaluate, Laravel will automagically choose the production environment.

1
2
3
4
5
6
7
8
9
if (isset($_SERVER['LARAVEL_ENV']))
{
  $env = $app->detectEnvironment([
    $_SERVER['LARAVEL_ENV'] => [gethostname()]
  ]);
} else
{
  $env = $app->detectEnvironment(['local' => ['*.local', 'local.*', 'localhost']]);
}
  • Published on April 29, 2014
  • 304 words

ImageMagick with WebP Support on Ubuntu

26
Apr 2014

I recently wrote about reinstalling ImageMagick on OS X to get WebP support. A little later I was facing the same problem on an Ubuntu machine. To fix it there is also mainly just a matter of reinstalling. How to do that was explained to me here. It basically boils down to:

1
2
3
4
5
6
7
8
9
cd /tmp
mkdir imagemagick
cd imagemagick
sudo apt-get build-dep imagemagick
sudo apt-get install libwebp-dev devscripts
apt-get source imagemagick
cd imagemagick-*
debuild -uc -us
sudo dpkg -i ../*magick*.deb

Unfortunately, this does not take into consideration that one might run apt-get upgrade at some point in the future again and that this upgrade operation might overwrite the just painfully compiled webp supporting ImageMagick package. Luckily, there is a simple fix for that. Apt allows packages to be blacklisted from future operations. The list of these is contained in /etc/apt/apt.conf.d/01autoremove.conf. In order to keep the compiled version of the package all one needs to do is to add imagemagick* in the Never-MarkAuto-Sections, e.g. something like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
APT
{
...
 Never-MarkAuto-Sections
 {
    "metapackages";
    "restricted/metapackages";
    "universe/metapackages";
    "multiverse/metapackages";
    ...
    "imagemagick*";
 };
};
  • Published on April 26, 2014
  • 181 words

Java

24
Apr 2014

In Java, you can forget about doing it in the cleanest or the best way, because that is impossible. Whatever you do, however hard you try, the code will come out mediocre, verbose, redundant, and bloated, and the only thing you can do is relax and keep turning the crank until the necessary amount of code has come out of the spout. — Why I like Java

  • Published on April 24, 2014
  • 74 words

When reinstalling helps

22
Apr 2014

Today I learned about brew reinstall. This command allows to reinstall the currently installed version of a package. Now, why would that be useful? Because sometimes things go wrong. In my case, the installation of the latest PHP 5.6 release went wrong somewhere. Since I am generally bad at reading log messages, I did not notice that until I actually needed it working.

At first, it threw tons of errors at me of which I thought they originated from the code I was trying to execute - wrong. Then I realized that I might not have updated all the extensions I needed. Also wrong. Then I fooled around a bit and stumbled across homebrews reinstall command. It took a few cups of coffee for

1
brew reinstall php56

to finish but that’s okay. It magically worked again.

Literally only minutes later was it when I discovered that my imagemagick installation was not compiled with webp support. Having learned about reinstall I could solve that problem without a stack overflow marathon.

1
brew reinstall imagemagick --with-webp

Another cup of coffee.

  • Published on April 22, 2014
  • 181 words

Chrome cleanup

30
Nov 2013

Google Chrome’s automatic updating is very much awesome. But it has one big disadvantage for people like me who don’t like unused junk on their hard disks. And old versions of programs belong to unused junk. Fortunately, there is an easy way to remove all old versions of Chrome (works for the default and the beta/dev channels, people using the canary channel simply have to swap out the application name):

Using the Finder

Navigate to Applications and select “Show Package Contents” on Google Chrome. You should be presented with something along the lines of the below picture.

Navigate to the Contents/Versions directory. In there, you can delete all directories except the one with the highest number - that’s the version you’re currently on.

Using the Terminal

On a command prompt, enter

1
2
3
4
[[ $(ls /Applications/Google\ Chrome.app/Contents/Versions \
| wc -l) -gt 1 ]] && \
rm -rf $(ls /Applications/Google\ Chrome.app/Contents/Versions \
| sort | sed \'$ 0\')

If you’re unsure, which version your Chrome is currently running on, simply open a new tab and navigate to

1
chrome://version
  • Published on November 30, 2013
  • 186 words

Code listings

21
Oct 2013

This may be common knowledge to almost everyone but I only recently discovered the nl tool from GNU coreutils. Now, as long as the code listings to be done are to be published online - woah, that was some weird language - there’s plenty of options to get them to have line numberings. GitHub’s Gists do that. Almost all the syntax highlighting plugins for all the publishing platforms do that. So well. But there are situations where there is no such thing. At least not as conveniently available. Let’s say you’re writing a paper in TeX and need to embed a piece of code including line numberings. There is probably some kind of weird tex sorcery around that would do that for you. But there’s also nl available via any* unix-y command line. Give that  a stream of text, get a stream with line endings back. Quick. Easy. Awesome.

  • Published on October 21, 2013
  • 149 words