DreamHost, rvm, capistrano, fun!

I recently started setting up ktc.hn as a url shortener for my blog. I decided to make it a little Sinatra app, which meant I got to play with my standard box of tools for deploying Ruby applications: rvm, capistrano, and passenger. Since things weren’t super straightforward, I figured I’d write up this post to share what I ended up with, things I ran into, and things I’m hoping to improve upon.

The Setup


I use rvm, if for no other reason than it’s what I’m familiar with. It makes it really easy to install and manage multiple rubies, manage gems with bundler, it’s well maintained, and I can do it locally on my laptop as well as remotely on my deployment targets.


Capistrano is an ssh-based deployment tool, useful for deploying applications to remote servers. I like it because, while it has great integrations for ruby projects, it can also be used to deploy pretty much any software. I’ve used it for PHP as well as golang projects, rails and non-rails ruby projects, whatever. I’ve also used its sshkit library for automating tasks via ssh.


DreamHost supports running ruby applications using Phusion Passenger. The details of how this all works are outside of the scope of this post, but it’s similar to running an application using FCGI. You point passenger at the ‘public’ directory of your application, and it goes looking for your config.ru file, which is the interface defined by rack, which Passenger is an implementation of, fires up the app, and starts sending HTTP requests to it.


After installing rvm locally, I drop a .ruby-version file in my project root, and a .ruby-gemset file as well. This makes my zsh shell integration do the thing it needs to do to select the correct ruby version and gemset. Note that since I’m using Bundler to manage my gem dependencies, I don’t really need to specify a different gemset, but it’s nice to have so I don’t have to constantly re-run bundle install every time I switch between projects.

Since I’m deploying using capistrano, and want to use rvm on the remote side to manage my ruby install, I need to add a couple of gems to my Gemfile: capistrano  rvm1-capistrano3

Then I run cap installto “capify” (that actually used to be the command to run to do this) my project. This installs the following files:

  • Capfile
  • config/deploy.rb
  • config/deploy/production.rb
  • config/deploy/staging.rb

The main purpose of the Capfile is to load in gem-based plugins for capistrano. The config/deploy.rb file is for global configuration of capistrano, such as declaring new tasks, configuring the source control repository, and other things. Overrides or stage-specific settings go into the config/deploy/*.rb files, with each file declaring a different stage capistrano can deploy.


Since I’m using the rvm1-capistrano3 gem, I need to load it by adding a line to the Capfile:

This loads up all of the tasks in the plugin, sets some of them up to be executed, and defines others to be used by the user of the plugin. I’ll be using some of those later.

Note: the gem is called rvm1-capistrano3, but you need to require rvm1/capistrano3, this is because gem names can’t contain slashes, but require is working with filesystem paths and the file being loaded is lib/rvm1/capistrano3.rb. Fun!


In config/deploy.rb I set the name of the application, which is really pretty arbitrary, but should be unique, as this is used in temporary directories and such.

I also need to set the path to the git repo where the code to be deployed is stored.

Capistrano supports several different source control systems, but git is the default, and it’s where my application’s code is stored.

For various historical reasons, I like my application’s tmp directory to be shared amongst all deployments. This also seems to play a little easier with the tmp/restart.txt functionality passenger provides to allow the user to restart the application on demand (such as when new code is deployed).

Two things to note here:

  1. The linked directory will be created by capistrano in the deploy path and symlinked into the release path.
  2. The reason to use fetch() here is to not stomp on :linked_dirs settings declared elsewhere in the capistrano configuration (e.g., a deploy stage configuration file, or by a plugin)

Since ideally I’m installing onto a clean slate, and want to have capistrano managing the entirety of the installation, I set up some of the tasks from rvm1-capistrano3 to be run during deployments automatically:

Here’s where I ran into some trouble. Previously, I was using the capistrano-bundler gem, which will run bundle install to install your gems, among other things. The problem here is that bundler is no longer installed by default alongside ruby, so when the plugin goes to run bundle install, it does so using the system’s /usr/bin/bundle, which on DreamHost (at least my server, a VPS, at time of writing) is running against ruby version 1.8.7. My Gemfile apparently isn’t loved by that version of bundler, so what happened is the bundle install command took a long time, ended up consuming all of the memory on my instance, and caused it to get rebooted by DreamHost. Oops.

The fix here appears to be to not use bundler for deployment and instead use the deploy task provided by rvm1-capistrano3 to install the required gems:

The reason I can’t just gem install bundler is because the capistrano-bundler gem wraps any gem command with bundle exec so there’s a bit of a chicken and egg problem. This approach seems to work, however, so I’m going to stick with it for now.

In the DreamHost control panel, I ticked the boxes next to Passenger and RVM and supplied the path to rvm:

Screen Shot 2016-05-14 at 11.20.56 PM

The ‘ktchn’ in that path is an rvm alias set up for me in capistrano. I do this so I don’t have to hardcode the ruby version and gemset name into the path in DreamHost’s configuration.

Sadly, there appears to be a bug in the rvm1-capistrano3 gem, or perhaps rvm itself, that makes it not alias the version of ruby in the specified path when setting up an alias, so I also had to explicitly set the ruby version here, which I don’t like, as it’s redundant, and buried in a config file.

Since I’m running on a managed DreamHost VPS, I don’t have root, and rvm install fails because it tries to use sudo to check for and install library dependencies. Fortunately, they seem to have installed them already, so I just disable the autolibs functionality:

And finally, to tell Passenger to restart the app after deployment, I touch tmp/restart.txt:


Finally, the deploy stage. Capistrano does a great job of making this pretty straightforward.

The fun part here was the :tmp_dir thing. DreamHost’s VPS product mounts /tmp (which is the default tmp dir in capistrano) as noexec, which capistrano doesn’t like, as it uses that directory for a couple of things and needs to execute at least one of them!


There are 2 major unresolved issues I have with this setup.

First is not being able to use bundler for managing my gems on the remote server. I am not certain if the correct versions are being installed by the rvm1:install:gems task. I feel like this is not an insurmountable task, I just need to poke around a bit in capistrano to see how I can do it!

The other is having to hardcode the ruby version into my config/deploy.rb file for the rvm1:alias:create command to work. The default for :rvm1_ruby_version is ., which is causing it to run rvm alias create ktchn . which rvm isn’t very happy about. I’m sure this is also something fairly easy to fix!

Taking the weekend off

I’ve been trying pretty hard to get out of the house, especially on nice days, and especially on weekends. For the past several weekends, I’ve done a pretty good job of doing it. Two weeks ago I went bike camping with Ted, last weekend I was out at Filmed By Bike and getting my new wheels and a bunch of other stuff.

However, all of this “leaving the house” stuff has left my house in a pretty rough state. I’ve been trying really hard lately to keep up with some basic housekeeping tasks and my busy weekends have been making it difficult to do.

So this weekend I’m taking the weekend off. I am giving myself permission to do absolutely nothing. I have a few small things at home I want to do (and, I do *really* want to do them) but if I stay in all weekend and read, then I’ve accomplished what I set out to do.

This all ties in with some stuff I’m working on around “intent”, and I hope to have some more to say about that soon. This weekend I’m giving myself permission to stay inside. It certainly doesn’t hurt that it’s supposed to rain all weekend!

Kickoff Entries

A thing I’ve been doing in my journal is what I call a “kickoff entry”. If I take on a new thing, or add something to my routine, I’ll write a little blurb about what, why, goals, and some thoughts about what conditions I may decide to end the experiment.

These really help to solidify the intent around the action, and help me be realistic about what I want to get out of it. Also, as someone who frequently jumps from one new thing to the next, it helps me pace myself a bit. If I sit down and write an entry, I get an opportunity to ask “do I really want this?” And “what am I sacrificing to make this happen.

I have a tendency to be very “oh this is going to be awesome!” And 3 weeks later have totally forgotten about things. This has been helping with that, some. It’s definitely fun, at the very least!

Ride Report: Stub Stewart State Park

With the forecast calling for a lovely weekend, Ted and I set out on our bikes toward Stub Stewart State Park, along the Banks-Vernonia State Trail.

(Update: Ted posted his own report!)

We started things off proper with some hills. Heading up NW Thurman to Leif Erikson trail through Forest Park to climb our way up to Skyline.


IMG_4935.jpgFrom there we meandered across some back roads over to Helvetia Tavern, apparently well known for their giant burgers. I was oblivious to this fact (despite it being on our waitress’ shirts) and got the fish and chips. Worth it.

We also bumped into a group of 4 cyclists who were also out and about from Portland. One guy on a fixie, one on a hybrid commuter, and the other 2 on some fancy carbon machines. They made pretty great lunch companions!


Fueled and rested, we plowed on. After many miles of fairly pleasant road, a bit more gravel, and a quick restroom stop, we found ourselves at the Banks end of the Banks-Vernonia State Trail.

Now, I’m not going to lie. I thought we were basically done at this point. “Just a few miles up the path here”. And yea, that’s right. Except those few miles were 10, and were uphill the entire way. Normally, this would be fine, I love hills, but when you’re 40 miles and 2000 feet into a ride already, and pulling 40 pounds of trailer, the last thing you want is a mountain finish!

After a good long while, we made it to the park, and got some proof:

IMG_4945 (1).jpg


There was a little bit of confusion as both Ted and I were operating under the assumption that there was a hiker-biker site that we could just plop down at like so many other campgrounds. There were some “walk-in” sites, which were just sites that didn’t have a dedicated parking space at the site, you had to walk about 50 feet to a shared lot along the road. These were all, unfortunately, reserved.

Ted went off in search of the camp host to see if there was any way we could camp, and they said to check the hike-in sites down by the visitor center. The “hike” in this case was not quite the hike I was expecting, it was a pretty well groomed single lane gravel road leading into a group of campsites.

Sadly, all of the sites there were reserved as well. However, it was starting to get late, and we were definitely well into IDGAF territory, so we picked one of the reserved, but vacant sites and started getting settled. After eating dinner, about 7pm, we decided that the people who had the site reserved were not going to arrive, and set up tents, claiming the site as our own. There will still 2 other sites, so odds were pretty good we could just move to one of the others if our hosts arrived!


After pitching tent and such, I sat down to read for a bit. That lasted about 15 minutes before I decided I was going to bed. It was about 8pm and still very light outside. I was utterly exhausted. I figured I could read in my tent for a bit and be a bit more comfortable than in my camp chair. I think I was out cold by about 8:30.

Woke up Sunday morning, made some coffee, made some eggs, rehydrated one of Ted’s food pouches and broke camp. On the road by 11am.

We continued up the Banks-Vernonia trail until we got to Vernonia, where we met up with some fellow bikers and had lunch.


On the way out of Vernonia, we found that Google Maps was lying to us. The road it wanted us to take was gated off and looked like it hadn’t been traveled in years. So we headed back to the highway and took the long way around.

15 miles and a lot more climbing later, we ended up in the tiny community of Chapman, where we rolled up to a random house where someone was mowing their lawn and asked if we could refill our empty water bottles. He asked us if we were taking the trail, and we had only found it briefly on our way back into town after passing it. I asked where it went east of there and he said it went all the way to Highway 30! He also seemed amazed that we had been on the highway the entire time, as opposed to taking the trail!

We thanked him for the water and the advice, hopped back on our bikes and headed for the trail. It was definitely not well paved, most places it was simply gravel. A couple of places it was extremely loose gravel and impassible, one of those places was on a descent to what looked like a fairly new bridge. These places were pretty easy to pick out as their gravel was very different from the normal gravel, so it was at least manageable.

We came across a landslide which had taken out the trail, but there was a little path off to the side we were able to sneak around.


There were a few additional patches of the extremely loose gravel further down, in areas which also looked like they had been taken out by landslides. They apparently get a lot of landslides up here!

Finally, we made it into Scappoose and onto dreaded Highway 30. We were both in desperate need of ice cream, so we stopped off at a DQ for a couple of blizzards and some AC. The sign on the bank next door read 83F, and there wasn’t a lot of shade to be had.

From there we cruised down Highway 30, dodging glass, rocks, silverware, even a propane tank! Upon reaching the St. John’s Bridge, Ted and I split up, me heading across the bridge and him heading into northwest Portland.


Up and over the bridge and into the worst headwinds I’d experienced the entire ride. All the way east on St. John’s bridge, all the way east on Rosa Parks, all the way east on Broadway, all the way east on Irving, and finally I rounded the corner to home and didn’t care anymore.

All in all, I had a blast. I’m destroyed, and ordering delivery right now. I was a bit worried at the campground, what might happen if there wasn’t anywhere for us to stay, but was feeling pretty YOLO and figured the worst that could happen was we’d have to roll back down hill to Banks and grab a hotel room or call for a ride or something.

I also have to give mad props to Ted for choosing a pretty awesome route. Other than Highway 30, which honestly wasn’t that bad, just loud and lots of debris, the route was pretty low traffic, and extremely lovely.


Screen Shot 2016-04-28 at 10.13.52 PM.png
Each blue square is a day I made at least one entry.
For the past several months I’ve been making a concerted effort to write in my journal every single day. I’d heard lots of great things about it in the past, but never really got into it. One of the big road blocks I ran into in the past was thinking that every journal entry had to be some insightful, well-written, moving piece of prose. This is actually one of the reasons I have never really had a blog take off and be something I do, too.

I’ve been slowly working my way through Search Inside Yourself (SIY) for almost a year at this point, and one of the mindfulness techniques it mentions is journaling. SIY is very much in the camp of “write for the sake of writing.” It even goes as far as to say that even if all you end up writing is “I have no real idea what to write about but this thing says I need to keep writing for 3 minutes regardless of what’s actually coming out”, then it was a valuable exercise. I’d like to add my support for that statement as well. Usually after about 2 sentences of nonsense, something comes to my mind and I end up writing for way longer than the prescribed 3 minutes.

Combined with an app I’ll discuss in another post that aims to aid in habit formation, I now not only write in my journal nearly every day, but it often ends up being my default location for brainstorming or thinking about things, and there are many days where I will write multiple entries. One of the wonderful things about writing every day is discovering what sorts of broader themes crop up in my journal.

One of the most valuable things I’ve gotten out of my journal is seeing the progress I’ve been making in my life. I’ve really been making significant improvements in my life in the past several years, and journaling gives me a way to look back in time at what things used to be like and see the progress I’ve made. I honestly can’t wait for 5 years from now when I look back at entries I’m writing today.

I have lots more I can say on this topic, and will say on this topic in the future. For now, I invite you to join me on this journey, and if you’ve been journaling yourself, I would love to hear the techniques you use and the value you’ve gotten from your own exercises.

Mindset, a book review

Back in September, I started a new job at Stripe. During my onboarding trip, I was having a conversation with one of my coworkers over burritos about “Impostor Syndrome”, something both of us had been experiencing since we started. A couple of nearby coworkers weighed in with their thoughts and experiences and we had a great conversation. Afterward, she and I talked about doing a session on impostor syndrome as part of our onboarding curriculum.

Fast forward a couple of weeks, and I’m trying to put together a talk idea for SCaLE14x. I remembered our conversation and thought it would be a great talk subject, and I could also do a dry-run of it at work during my trip in December. Perfect! I submitted the proposal, it got accepted, and I scheduled a session to give my talk at the office in front of my coworkers!

Upon sending out just the announcement for the talk, I had lots of positive feedback from folks. One conversation in particular that came up was from another of the folks I started with and he linked me to a talk from Allison Kaptur entitled “Effective Learning For Programmers“, a talk he liked to refer people to any time the subject came up.

During her talk, Allison mentions the concept of “mindset” and research done by Carol Dweck. As it turns out, Carol wrote a book about the subject, called “Mindset: The New Psychology of Success” (amazon, goodreads).

I was having a particularly difficult day and remembered this talk. Immediately I went and grabbed a copy of the book and started reading it. I felt like my brain had been sliced open, analyzed, and the results printed on the pages before me.

The general gist of the book is there are 2 basic mindsets: fixed and growth. A person with a fixed mindset does not believe themselves capable of improvement. The skills and abilities they have are what they were born with, and they cannot improve those. Failures draw the boundaries, the edges of skill and ability. A person with a growth mindset believes they can improve through effort, training, learning. Failure isn’t necessarily a lack of skill, knowledge, or ability. Effort, hard work, and learning can improve skills, enhance ability, and improve performance.

The book goes on to describe language that effects a mindset. Rewarding someone by saying how smart they are can place them in a fixed mindset. Talking about how hard they worked can impart a growth mindset. I’ve personally talked with people about this book, and one person in particular described the language as “something you are as opposed to something you do.” You are smart, or you do work hard.

I’ve been trying to apply the lessons from this book to my own life, to much success, and sometimes less than success. I think one of the greatest examples of the success I’ve had is to be able to look at times when I have been in a fixed mindset since reading this book and not feel unworthy because of them. Basically, not having a fixed mindset about my mindset. And to go one more level of meta, being ok with sometimes having a fixed mindset about my mindset!

The first time I saw Allison’s talk, a lot of what she said really resonated with me, but I didn’t translate it into action. Only later did I recognize the value of what I was hearing and seek more information about it. I feel like my mind wasn’t yet ready to receive the wisdom contained in these pages. I am immensely grateful it eventually was, and that this book came into my life when it did. I believe I’ll look back to this book as a major milestone in my life and my development.


Hello, World!

It’s that time again. Time for me to switch blogging platforms and work at getting into blogging! I’m back on WordPress and likely here to stay. Things in WordPress world have gotten to the point where I don’t feel super paranoid that it’s going to get compromised, and if all else fails I can move to WordPress.com and have a super stable blog with all the backups and not have to worry about things at all. Hooray!

Because I want to make my site forward compatible with WordPress.com, and in the interests of not having all of my permalinks broken, I’m going to leave http://blog.kitchen.io/ online indefinitely. I’ll make a post over there redirecting folks to here, but that site will be mostly deprecated.

There are several reasons I’m switching away from Octopress, but the main one is ease of use. WordPress’ post editing interface is pretty neat. I can edit posts from my phone, it’s very WYSIWYG, and once I enable the embed.ly plugin, it will have very nice support for embedding content from third parties. Plus I feel like it can take the place of my photostream with its built-in media support. I may still end up with my own media hosting system, but with the embed.ly plugin, it’s easy to make cards for that, if I ever get there.

Here’s to the future!