jeremykendall.net

Vagrant Synced Folders Permissions

UPDATE: Since writing this post Vagrant has changed the synced folder settings and I’ve come across a new (and better?) way of handling this problem. Scroll down for the updates.

Having trouble getting your Synced Folders permissions just right in your Vagrant + VirtualBox VM? They’ve been giving me some grief lately. Here are the (undocumented) Vagrantfile options that finally got it sorted out.

Permissions Challenges

The issue that got me digging into this was trying to get permissions just so to allow my web apps to write logs. As you probably know, apache (or your web server of choice), sometimes needs write access to certain web application directories. I’ve always take care of that by adding the apache user group to the directories in question and then giving that user full access. Doing that in Ubuntu looks something like:

1
2
chown -R jeremykendall.www-data /path/to/logs
chmod 775 /path/to/logs

If you’ve tried doing something similar in your Vagrant shared folders, you’ve likely failed. This, as it turns out, doesn’t work with VirtualBox shared folders — you have to make the changes in your Vagrantfile.

Setting Permissions via the Vagrantfile

UPDATE: Thanks to Joe Ferguson for pointing out in the comments that Vagrant has been upgraded and my example was no longer current. Below are both examples marked by Vagrant version.

Here’s my new synced_folder setting in my Vagrantfile:

Vagrant v1.1+:

1
2
3
4
5
  # Vagrant v1.1+
  config.vm.synced_folder "./", "/var/sites/dev.query-auth", id: "vagrant-root",
    owner: "vagrant",
    group: "www-data",
    mount_options: ["dmode=775,fmode=664"]

Vagrant 1.0.x:

1
2
3
4
5
  # Vagrant v1.0.x
  config.vm.synced_folder "./", "/var/sites/dev.query-auth", id: "vagrant-root",
    :owner => "vagrant",
    :group => "www-data",
    :extra => "dmode=775,fmode=664"

I’m sure you can immediately see what resolved the issue. Lines 3 and 4 set the owner and group, respectively, and line 5 sets directory and file modes appropriately. That simple fix was frustratingly difficult because I couldn’t find it documented anywhere. After much searching and opening far too many browser tabs, I cobbled together the info above. A quick vagrant reload later and I was off to the races.

UPDATE: Alternate Method

An alternate method that doesn’t include modifying your synced folder permissions is changing the web user to the vagrant user. Bad idea? Security problem? Not on your dev VM it ain’t, and that’s good enough for me. Big thanks to Chris Tankersley for all the help getting this one figured out.

Chris and I both put together gists, and this is how I’m currently doing it in Flaming Archer, but probably the best method for changing the apache user to the vagrant user comes from the Intracto Puppet apache manifest.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Source https://raw.github.com/Intracto/Puppet/master/apache2/manifests/init.pp

# Change user
exec { "ApacheUserChange" :
    command => "sed -i 's/APACHE_RUN_USER=www-data/APACHE_RUN_USER=vagrant/' /etc/apache2/envvars",
    onlyif  => "grep -c 'APACHE_RUN_USER=www-data' /etc/apache2/envvars",
    require => Package["apache2"],
    notify  => Service["apache2"],
}

# Change group
exec { "ApacheGroupChange" :
    command => "sed -i 's/APACHE_RUN_GROUP=www-data/APACHE_RUN_GROUP=vagrant/' /etc/apache2/envvars",
    onlyif  => "grep -c 'APACHE_RUN_GROUP=www-data' /etc/apache2/envvars",
    require => Package["apache2"],
    notify  => Service["apache2"],
}

Additionally, if you’re copying and pasting from anywhere, don’t forget to change the apache lockfile permissions:

1
2
3
4
5
6
7
# Source https://github.com/Intracto/Puppet/blob/master/apache2/manifests/init.pp

exec { "apache_lockfile_permissions" :
    command => "chown -R vagrant:www-data /var/lock/apache2",
    require => Package["apache2"],
    notify  => Service["apache2"],
}

ACL on Shared Folders That Are Not NFS

One of the reasons the above methods are necessary is that you can’t use ACLs on shared directories. If none of the above options appeal to you, it’s possible to use ACLs on your VM as long as the directories aren’t shared. For more information, see Frank Stelzer’s comment regarding setfacl on a Vagrant box.

I Love You Guys

Tuesday was a frustrating day at work, one I spent chasing a bug that I was never able to find. My friends on Twitter made it all better.

Number of the Contributor

My contributions at work, Aug 05 2012 – Aug 05 2013.

Woe to you, o earth and sea, for the devil sends the beast with wrath, because he knows the time is short … Let him who hath understanding reckon the number of the beast: for it is a human number; its number is six hundred and sixty six.

The Composer Kerfuffle

Wednesday night I discovered, much to my shock and dismay, that Composer’s install command now defaults to installing development dependencies along with a project’s required dependencies. That discovery prompted me to start a “small twitter shitstorm” with this tweet:

Before I delve into why I’m shocked and dismayed, I want to say a few things about Composer and the Composer team. In all of my years of programming in PHP, I’m not sure there’s been a more important, more game changing, or more exciting project than Composer. Being able to easily manage project dependencies has revolutionized the way I develop. Composer, and the related packagist.org, have been a larger quality-of-life improvement for me than any other tool I’ve added to my toolkit over the years. I’d like to extend my sincerest thanks to Nils Adermann, Jordi Boggiano and the many community contributors who have worked so hard and so diligently to make Composer a reality.

My Beef with the Change

1. There was never any public discussion about the change

Beyond a few brief asides in a couple of github issues and pull requests, I can’t find anywhere this change discussed publicly. For a project of this size and this importance, removing the community from the decision making process was a terrible mistake. I’d much prefer to have argued all of this before the change than after.

Yesterday, Jordi posted “Composer: Installing require-dev by default” to explain his rationale for the change. One of his points is that he made a note in the 1.0.0-alpha changelog regarding the upcoming change. While this is true, I find it insufficient. I rarely read changelogs (my bad), but I certainly don’t read changelogs to discover what’s coming in the future. That’s what road maps, blog posts, and PRs are for. Putting that note in the changelog was “too little, too early”.

2. Composer philosophy and workflow has always been, “install for production, update for development”

The longstanding Composer rule of thumb has always been “install for production, update for development”. Adam Brett’s post on Composer workflow and the difference between update and install is a good example of this rule of thumb. Humorously enough, Jordi reinforces that rule of thumb (while defending the change that composer update installs dev requirements by default) in his blog post immediately prior to the post defending the composer install change:

“The install command on the hand remains the same. It does not install dev dependencies by default, and it will actually remove them if they were previously installed and you run it without —dev. Again this makes sense since in production you should only run install to get the last verified state (stored in composer.lock) of your dependencies installed.”

That rule of thumb is now turned on its head, and the default “composer install in production” advice now needs updating, careful warnings, and caveats.

3. Tools should never default to dev (unless they’re meant for dev, of course)

This is a philosophical point on my part, but it’s one I don’t think is unique to me and it’s one that I think can be well defended. My point here is that one should always write code and tools in such a way that deployments to production will only ever result in production code being deployed. Clear as mud? Let me try with an example.

I frequently use environment variables to allow my applications to detect which environment they’re running in. If those environment variables don’t exist, then the application should default to production. Why? Because dev environments are the special case, not production, and it’s far too easy to forget to add those environment variables when deploying. I make my life easier by making the production environment as idiot-proof as possible, and not the other way around.

This philosophy was in place in the prior behavior of composer install (and composer update, for that matter). Now that it’s changed, the production environment is far more likely to suffer than the development environment. Forgetting to add the —dev flag in development is a lot less (potentially) costly than forgetting to add the —no-dev flag in production.

In a seeming contradiction, I’ve said that I have no problem with composer update defaulting to installing dev dependencies. I’ve gone back and forth on that a bit when considering my “tools should never default to dev” position, but I don’t think I’m being inconsistent here. Since the rule of thumb encourages using update in development and never in production, then update becomes a dev tool which can safely default to installing development dependencies. Having said that, if consistency between commands is important, then composer update should no longer default to dev and the changes to both install and update should be reverted.

In Closing

Composer has become an integral part of my workflow, and a critical piece of the PHP development process in general. I loved Composer before this change and I’ll love Composer after. That said, changing the Composer command that is intended primarily for production use is extremely disruptive and a very bad call, especially considering how the change came about.

Piedmont Natural Gas: Customer Service WIN

(This is the follow-up to yesterday’s post, “Dear Piedmont Natural Gas”. Start there for the full story.)

As I write this follow-up post, the gas has been turned back on, my hot water heater is working away, and my wife and I find ourselves on the far side of a bad situation turned good.

We last left off with a phone call from Piedmont corporate and a promise to have our gas turned back on by 5 pm CST. Not only did Piedmont come through, they came through big. The technician they sent was early to the appointment and went above-and-beyond to make sure we were taken care of. While I wish this entire situation never happened, the outcome is the very best of a bad situation, and I want to close this out with a big thanks to Piedmont Natural Gas.

Once Piedmont corporate learned about our problem, they went the extra mile to resolve it to our satisfaction as quickly as possible. I don’t know everything they did, but they went as far as reviewing the recordings of both our Friday and Saturday customer service phone calls, calling both my wife and myself to schedule reconnection, and taking the time to explain exactly what happened, why it happened, and then take responsibility for it. Kudos to Piedmont.

Thanks also to all of you for being so supportive. In the grand scheme of things, this was small potatoes, but that didn’t make it any less upsetting. The retweets, supportive comments, and personal commiserations went a long way towards making this a lot easier.

Dear Piedmont Natural Gas: Updated

My wife and I recently moved to a suburb of Nashville, TN. Through no fault of our own, we had our natural gas service shut off yesterday and the provider, Piedmont Natural Gas, is refusing to restore our service until Tuesday, December 4. Here is my letter of complaint to Piedmont requesting that they make this right.

My wife and I moved to Hermitage, TN in late October 2012. She called to have natural gas service transferred into our name the week of October 22. Yesterday, November 30, our landlord got in touch with us to let us know the previous tenants had received a bill and we needed to touch base with you and take care of the problem. Which we did.

  • Here’s the payment confirmation number: 5752712
  • Here’s the line item from my checking account’s online system: 11/30/2012 Sign Debit* PIEDMONTNG/SPEEDPAY $70.15

But guess what? Our gas got cut off.

And guess what else? You won’t turn it back on until Tuesday, December 4th.

And guess what else? The representative my wife talked to yesterday afternoon told us the gas would not be cut off, that there wasn’t an appointment to have it cut off, and that everything was taken care of.

The best part? The gas was already cut off. Before we called. Before we were able to make payment. Through no fault of our own.

This is absolutely, completely and totally, 100% the fault of your company and your representatives at Piedmont Natural Gas.

It is wholly unacceptable that, after explaining our situation to your representative on the telephone this morning, you refuse to turn our gas back on.

You and I both know you have the ability to send a truck out and have our gas turned back on. You and I both know that you’ve done it for other customers in the past, and that you’ll do it for other customers in the future. I respectfully request that you do it for my wife and I now.

This one is on you. We did our part. Now do yours and make this right today.

Best,

Jeremy Kendall

Piedmont, the ball is in your court.

(I informed Piedmont that I would be making this complaint public here on my blog, and will update this post with both sides of the story as the situation unfolds.)

Update: Poor customer service with a positive result

Yesterday

By yesterday at 10 am CST, I had spoken to Piedmont customer service, sent them an email, written this blog post, and pinged them on both their Twitter account and their Facebook page. I kept an eye on my phone, email, and social networks all day, finally giving up around 5 pm. Finally, at 6:41 pm CST, almost three hours after Piedmont customer service closed for the weekend, I received this reply via Twitter:

Piedmont had six hours to touch base with us and resolve the problem. I pinged them in every possible way, making what I felt was a reasonable request for restoration of services. Rather than jumping on the problem and restoring our service, we were contacted after hours and told that customer service has been “made aware”. Thanks, but I’d already covered that one, and they won’t be open until Monday morning anyhow. Not impressed.

This morning

I didn’t sleep well last night, so I went down for a quick nap this morning. When I woke up, I had a missed call and voicemail from Charlotte, NC. The message was from Piedmont Natural Gas asking for a return call. As it turns out, they called Megan as well. After a day-and-a-half without service, Piedmont has promised to roll a truck and have our service turned back on.

I appreciate the extra effort they’ve taken to reach out to us on a Sunday, but I don’t appreciate having to fight for it. We’ll see if we get a truck this evening or not. I’ll let you know how it goes.

Update: Victory!

Our gas is back on and we’re happy with how this thing turned out. Please see my follow-up post, “Piedmont Natural Gas: Customer service WIN”, for the details.

Goofing Off With Unit Tests

[UPDATE: The library and test have been refactored. See the commit for full details.]

Sometime last year I saw a unit test for the song “Ice Cream Paint Job”.  I thought it was hilarious, and I hate I’ve never been able to find it again.  I liked it so much, in fact, I decided to write my own musical unit integration test.  Behold the MelissaTest, a short, simple test covering the main premise of “Melissa”. Bonus points for me: the test passes.  Enjoy.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?php

namespace MercyfulFate\Album\Melissa\Track;

use MercyfulFate\KingDiamond;
use MercyfulFate\Priest;
use MercyfulFate\Witch\Melissa as WitchMelissa;
use MercyfulFate\Album\Melissa\Track\Melissa as TrackMelissa;

class MelissaTest extends \PHPUnit_Framework_TestCase
{

    /**
     * @var MercyfulFate\KingDiamond
     */
    protected $king;

    /**
     * @var MercyfulFate\Priest
     */
    protected $priest;

    /**
     * @var MercyfulFate\Witch\Melissa
     */
    protected $witch;

    /**
     * @var MercyfulFate\Album\Melissa\Track\Melissa
     */
    protected $trackMelissa;

    protected function setUp()
    {
        $this->king = new KingDiamond();
        $this->priest = new Priest();
        $this->priest->attach($this->king);
        $this->witch = new WitchMelissa();
        $this->trackMelissa = new TrackMelissa($this->king, $this->witch, $this->priest);
    }

    protected function tearDown()
    {
        $this->trackMelissa = null;
    }

    public function testBurnMelissa()
    {
        $this->assertFalse($this->witch->isBurned());
        $this->assertFalse($this->king->swearsRevenge());

        $this->trackMelissa->priestBurnsWitch();

        $this->assertTrue($this->witch->isBurned());
        $this->assertTrue($this->king->swearsRevenge());
    }

}

Memphis PHP #3 - Presentation Slides and Example Code Included

We had a great time last night at Memphis PHP.  The turnout was great, it was fun meeting new folks and seeing old friends, and the conversations before and after the meeting were worth the drive to East Memphis.

I had a blast presenting “A Brief Introduction to Zend_Form.”  I love presenting, especially when the audience gets into the act, asking tons of good questions and laughing at my horrible jokes.  Thanks to all who showed up and for making Memphis PHP and last night’s event such a great success.

Slides and Example Code

As promised, I’ve posted “A Brief Introduction to Zend_Form” at SlideShare.  Included below are links to the example code on pastebin.

The best way to run the MVC example is to whip up a Zend Framework project and drop Example.php into /application/forms.  If you’re unfamiliar with how to get a Zend Framework project up and running, please see “From Zero to Zend Framework Project in 10 Minutes.”

Thanks to our Sponsors

Many thanks to Dave Barger of LunaWeb for kindly allowing us to use the LunaWeb offices for our meeting place, providing food, soda, and even beer.  Yup.  Free beer.  Not bad for our third event, eh?

Dave shared some information last night about his company, LunaWeb, some upcoming events, and some of their current and upcoming projects.  Here’s a list of the links that he referred to.

For your radars:

Big thanks to G2 Technology for helping us spread the word about Memphis PHP.  They work hard every month to promote our events, and I’m grateful to them for all they do.

Join Us

If you’re local to the Memphis area, visiting Memphis, or close enough to drive in, and you’re not a member of Memphis PHP, we’d love to have you join us.  Head over to MemphisPHP.org and join the group.  You’ll get announcements from the group, info about meetings, and be able to RSVP for events.  I look forward to meeting you at our next event.

Announcing Memphis PHP

It’s my pleasure to announce the formation of Memphis PHP, a PHP user group serving Memphis, TN and the mid-south.  The goal of Memphis PHP is to grow and nurture an active PHP community in the local area.  It’s going to take a lot of work to get Memphis PHP off the ground, but having an active community of PHP developers in Memphis is long overdue.  The hard work will be more than worth it, and I’m going to need your help to accomplish that goal.

My first exposure to the PHP community at large came when I attended ZendCon in 2008.  After getting a taste of what the PHP community had to offer, I was pretty bummed out that we didn’t have anything going in Memphis.  Attending ZendCon in ‘08 led to attending ZendCon in ‘09, Nashville’s excellent Big LAMP Camp event last November, and I just returned from the tek-X conference in Chicago.

One of my favorite sessions at this year’s tek-X was the Community Roundtable, “an all-star lineup of community members” discussing user groups: what they are, how to start them, and how to keep them going.  It was the Community Roundtable that finally convinced me enough was enough, that it was time to start a user group right here in Memphis, TN.

The Details

  • Memphis PHP will meet on the 4th Thursday of every month at 6:30pm (currently searching for a suitable location).
  • Memphis PHP uses Meetup.com for membership, event and meeting announcements, RSVPs, etc.
  • Our first event will be a road trip to Nashville on June 8th to visit the Nashville PHP user group.
  • Our first official meeting will be on June 24th, location and speaker/agenda TBA.
  • Follow @MemphisPHP on Twitter for community updates and the like.
    • If you’re on Twitter and would like to be added to the memphisPHP-devs list, let me know.
    • Our official hashtag is #memphisPHP.
  • Our general discussion group and mailing list is hosted at Google Groups
  • Employers and recruiters are more than welcome to post opportunities to our discussion list. Please read the guidelines for Posting Employment Opportunities first.

Welcome to Memphis PHP!  I hope you’ll join me in making Memphis PHP a huge success.

Big Thanks

Special thanks go out to the Community Roundtable panel (@DragonBe, @LornaJane, @rdohms, @ramsey, @CaseySoftware) at tek-X for direction and tips, Ben Ramsey of Nashville PHP for his guidance and support, and Chance Garcia for beating me to the punch.

I’d also like to thank Wes Hicks and the team at G2 Technology for offering to help spread the word about Memphis PHP and help find a meeting place.

My Top 5 Favorite Geek T-Shirts (That I Own)

I’m a sucker for t-shirts, have been all my life. My high school sweetheart gave me grief for always wearing t-shirt and jeans. During my college years, credit card companies found me an easy mark by offering free t-shirts in exchange for my John Hancock. When I go out with Charly I still use the old, tired, “I’ll put on my dress t-shirt” joke.

If I had the means, I would be the Imelda Marcos of bad-ass t-shirts. Since I’m not (yet) independently wealthy, I need to be selective, feeding my addiction with nothing but primo stuff. Selecting from the geek category, in no particular order, here are my top 5 favorite geek t-shirts of all time (that I own).

I’m Well Built

Atlassian makes a lot of really sweet software, stuff I use on a daily basis, both at the house and at the day job.  While I’ve never actually used Bamboo (that’s next on the project list), I dig the shirt for a couple of reasons.  First, I’m a fan of all the Atlassian products that I’ve used so far, and I’ve always had good experiences dealing with Atlassian support.  Second, while you can’t tell from the lame graphic, this is actually a really good looking shirt.  Third, not being particularly well built, I love wearing a shirt that says I am.  It reminds me of my old “Who needs hair with a body like this?” shirt I wore when I was 220lbs of out of shape slob.  Oh sweet, sweet juxtaposition.

Get yours here.

Mine

What can I say about this one? It was love at first sight.  The only way I could love it more is if it were an official Office Space Hawaiian shirt, which does not exist and would be another post anyhow.  The thing I can’t understand is how few people recognize the red Swingline stapler for what it is.  Last time I was traveling, the only guy that got the joke was a ticketing agent at the airport.   We both had a good laugh.  Everyone else just looked at us funny.

Get yours here.

fork you

I haven’t ever used Git, I’m not a fan of their marketing strategies (svn sucks! Whaa?), I’m irrationally prejudiced against Rails, but I still love this t-shirt.  Grey is a splash of color in my mostly black wardrobe, it features cool typography, short, punchy copy, and it’s got a spot on the back intended for a little DIY customization, Sharpie style.  Mine says “sucks.”  Take that, Git. Har, har, har. Also, this is the shirt you want if you’re just angsty enough to want the world to fork off every once in a while, but not angsty enough to get yourself an FTW face tattoo (and I don’t mean “for the win”).

Get yours here.

SQL query

I picked this one up when I was working as a technical support rep, taking calls for 8 to 10 hours a day and hating my life.  While the tech support career path doesn’t generally leave one with a working knowledge of SQL, I was doing everything I could to teach myself to program so that I would never have to take another support call as long as I lived.  While that hasn’t quite worked out (I don’t take calls directly, but I live in JIRA), this shirt has remained hilarious and relevant from the first time I put it on.  Making jokes in code is like learning to swear in a foreign language, you can express your frustration about those around you without having to worry about being understood and a) getting punched in the jeans, b) getting fired, or c) getting punched in the jeans and then getting fired.  WARNING: when you start making jokes in code, you’ve crossed the line from earth person to geek.  There is no going back.

Get yours here.

Real Programmers Wear Corpsepaint

I grew up as a metal baby in the late 80s/early 90s, and I’ve never lost my taste for the hard stuff.  The combination of two of my great loves, heavy metal and computer programming, in one of my favorite mediums, the t-shirt, makes this an instant favorite. 

Fun fact: Although not widely known, corpse paint has been worn by computer programmers as early as the late 1960s.  It’s rumored that Kim Petersen, better known as King Diamond, was first exposed to corpse paint by some LISP) developers who were attending a mathematics conference in Denmark in the early 1970s.

Pro-tip: While real programmers wear do wear corpsepaint, real programmers do not wear nail studded gauntlets.  They’re a major contributing factor in repetitive stress injuries.

Get yours here.