Sam Soffes

Hosting Frustrations

Posted in deployment, development, engine-yard, heroku, and rackspace

Lately I've been struggling with good hosting. Here's three stories about some stuff I've tried. (Skip to the bottom of the post if you just want my conclusion and don't care about the stories.)

Heroku

I love Heroku. I did a screencast on how awesome they are a few months ago. Since then, I've moved all of my personal apps and all of Tasteful Works's apps to Heroku. They've been really great until recently.

I have two big complains (and one small one) with Heroku.

SSL

We were using SNI SSL for the Tasteful Works Store for awhile with great success. We realized that Google Chrome (as well as IE 6, which I don't really care about) don't support SNI SSL.

Chrome really yells at you when you go to a site using SNI SSL.

To get around this, you have to pay $100 a month ($95 more than SNI). This totally sucks. Heroku is awesome because they are affordable and easy. We finally decided to suck it up and pay the extra $95 a month. After paying they told it would take 1-2 business days to set it up. That totally sucks. After paying all of that money, we have to wait. I was pissed to say the least. They got it setup in 8 hours, but still.

The reason for the high price is due to how SSL works. Basically they spin up another $70/month Amazon EC2 instance to filter all of your requests through that into their routing grid. This is necessary because SSL requires that a certificate always uses the same IP. Understandable, but where the extra $30 comes from or why people can't share doesn't make sense to me.

HTTPS

Another recently frustrating thing with Heroku is how SSL environment variables work. rack.url_scheme is set to http or https depending on your request. Lots of Rack pieces rely on this. Heroku sets HTTP_X_FORWARDED_PROTO to https if it's an HTTPS request or omits that variable completely if it's an HTTP request.

This isn't a huge deal, but it caused me quite a few issues. I patched Refraction to work correctly on Heroku and all was happy.

Heroku told me on IRC that this is because requests sent internally are sent using HTTP and only HTTPS is used for the requests coming into the routing grid. That's fine and all, but it wish they informed applications of HTTPS in a more standard way.

Bundler

I know that they are working on better Bundler support, but it's kinda painful right now. You can't use gems from a git repository and whenever it re-bundles your app, it installs all of your gems, not just the ones needed for the current environment. So if you're like me and have a lot of testing gems, this takes forever.

Engine Yard Cloud

Some of the Engine Yard employees saw my frustrated Heroku tweets (which makes me laugh that they search for frustrated Heroku customers). They offered me two free weeks on the Engine Yard Cloud, which I thought was really cool.

After checking it out, I was very disappointed. I tried to get Markdownr setup on their service. After messing with it for over an hour, I gave up. Markdownr is probably one of the simplest Rails apps. (You can see the code on GitHub.) It only uses one gem besides Rails and doesn't use a database.

You have to add all of your gems that you need in their web portal. This seems so dumb. I wish it just used Bundler (especially since the guys that wrote it work at Engine Yard). I never got my app to launch. It kept saying the i18n gem wasn't found. I thought this might be due to using a pre-release version of Rails, so I installed them all separately and it still didn't work.

I emailed them and they said "Sorry that it looks like ey cloud is not for you." If it can't work with the simplest of apps, what can it work with? The price is also a bit high. (I also know a good friend that had a horrible experience with them.)

Rackspace Cloud

A few friends said they liked the Rackspace Cloud, so I thought I'd check it out since I am a little pissed at Heroku for all of the SSL junk and the Engine Yard Cloud just let me down. I checked out their site (which isn't to pretty) to get some more information, but didn't really feel like reading a poorly laid out marketing site. At the top of the page it said "Call Us," so I figured why not? I was curious if someone would answer at 11pm.

A support guy answered after just one ring. I was already impressed. If their support is that easy to contact, (granted it was at 11pm) that's really awesome. I told him I had some general questions about their platform and he was super nice and answered all of my questions.

I would totally go with Rackspace Cloud over any other VPS type service. They seem really awesome.

Final Thoughts

All of that said, Heroku is still hands down the easiest platform for hosting a Rails application. The Engine Yard Cloud is completely worthless. The Rackspace Cloud is really cool, but I don't want to manage a server.

So all of that said, we're staying on Heroku and paying the extra $95 a month for SSL.

Moved To Heroku

Posted in development, heroku, jekyll, rails, and web

I posted a screencast on Heroku a few months ago. Since then, my company has moved all of their stuff to Heroku. It has been working really great for us.

I've had my blog on GitHub pages for awhile. I recently came across a good article on running Jekyll from the Ruby5 podcast. It was really easy to get setup. So far, I'm a fan of my new setup.

I'm still working on my Rails 3 version of my blog when I have time. Lately, I've been playing a lot of music and occasionally dabbling with Markdownr.com due to a recent spike in traffic (thanks to @defunkt).

Running Rails Local Development with Nginx, Postgres, and Passenger with Homebrew

Posted in development, heroku, homebrew, local-development, nginx, passenger, postgres, and rails

Lately I have been playing with Homebrew, an awesome package manager for Mac OS X. I really like not having to worry about dependencies and such when installing. The "rarely sudo" mentality is also pretty great.

When I noticed the Nginx (a sweet open source web server that is way better than Apache) had a --with-passenger option (which is also way awesome), I figured I'd give it a shot. I was using the built-in Apache with Passenger Preference Pane, which was pretty cool, but I really like Nginx, so I switched. I also really wanted to start using PostgreSQL instead of SQLite since all of my stuff is hosted on Heroku and that's what they're running. (I do plan on writing a Preference Pane for doing for this setup eventually.)

Here are the steps to get all of this going. I tried to keep it as simple and clear as possible with lots of examples. It looks like a lot, but it's really quite simple.

This probably goes without saying, but you'll need Xcode installed to do all of this.

Installation

  1. Install Homebrew and follow the steps in the wiki about not sudoing when installing RubyGems.

    If you don't want to do it that way (I highly recommend doing it the above way), you can just run this command to install homebrew.

     $ sudo chown -R $USER /usr/local
     $ curl -Lsf http://github.com/mxcl/homebrew/tarball/master | tar xvz -C/usr/local --strip 1
    

    You'll need to sudo install gems if you do it this way.

  2. Install the Passenger gem

     $ gem install passenger
    

    I also had to install the fastthread gem to get Passenger to play nice later. You might not have to do this. If you need to, all you have to do is gem install fastthread.

  3. Install Nginx with the Passenger module

     $ brew install nginx --with-passenger
    

    You can start Nginx with sudo nginx and stop it with sudo nginx -s stop.

  4. Install PostgreSQL

     $ brew install postgresql
    

    After the installation completes, there will be instructions on how to initialize the database, start the server, start the server at login, and install the pg gem. Do all of this.

Server Configuration

  1. Modify your Nginx configuration for Passenger. It will be located at /usr/local/Cellar/nginx/0.7.62/conf/nginx.conf (obviously you will need to replace the version number with whatever version you installed). Here is what mine looks like.

    There are a few things to note:

    1. I run it as my user (staff is my group). You don't have to do this, but I like to have the processes running as me. (If there are more of me, I'm more productive, right?) You'll need to comment this line out or change to your user.

    2. I am pointing the passenger_root directive to the passenger root. This will change with whatever version of Passenger you have installed. You can get the current path by running passenger-config --root (you'll probably need to do this since the version is in the path).

    3. I also have passenger_ruby set to gem_ruby. I had a horrible time getting Passenger to see my custom GEM_PATH (that I setup by following the Homebrew wiki). I created this little shell script to fix the environment variables. It would be great if Passenger had a way to do this. I know you can in the Apache version, but I couldn't figure it out for Nginx. Here is what my gem_ruby looks like:

  2. I like to keep all of my virtual hosts in separate files in the conf directory and then include them into nginx.conf, but you can do it however you want. Here is what samsoffes.conf looks like:

  3. You will need to edit your /etc/hosts for any virtual hosts you add. Mine looks like this:

Database Configuration

  1. If you haven't already, edit your application's database.yml file to use PostgreSQL. Here is an example:

    Notice that the username is samsoffes and not root. Using the root user is considered bad practice by most. (We'll create that user in the next step.)

  2. Enter the PostgreSQL prompt to create your user and databases:

     $ psql  postgres
     # CREATE USER samsoffes SUPERUSER;
     # CREATE DATABASE samsoffes_development OWNER samsoffes;
     # CREATE DATABASE samsoffes_test OWNER samsoffes;
     # \q
    

    Note: you need to make your user a superuser for your tests to run correctly. More on this here.

Let's get started already!

So, to review, you have just installed and configured Nginx, Passenger, and PostgreSQL. Now, all you have to do is type sudo nginx to start Nginx and point your browser to your virtual host (so for me it would be http://samsoffes.local). That's it! You're done!

If you forgot to copy the commands out of the PostgreSQL install, here's how to start and stop PostgreSQL:

# Start
$ pg_ctl -D /usr/local/var/postgres -l /usr/local/var/postgres/server.log start

# Stop
$ pg_ctl -D /usr/local/var/postgres stop -s -m fast

Before, I found myself typing sudo apachectl restart a lot to reload my application. Now, you would run sudo nginx -s reload to reload the server configuration and restart the app. (You can of course do the touch tmp/restart.txt method as well.)

That probably seemed a bit tedious, but now all you have to do is create a virtual host in Nginx, add it your your hosts file, and create your database. I really like developing locally like this. Homebrew makes this entire process very easy.

If you have any issues, feel free to send me an email and I'll see what I can do. (I really need to get comments going on here don't I)