UPDATE: Heroku has removed Dropbox Sync support. This technique will not work anymore. Recommend Netlify for easy static site deployments.

At Paravel, we frequently run into issues where we need to share password protected sites with clients. We could setup some complicated post-commit hook/Capistrano system, or pin ourselves to a certain SaaS provider, but none of those have sat well with us and seem overly complicated.

We need a workflow that is flexible, almost disposable, and could even show a different “experimental” branch at a whim. We’ve come across something relatively simple that uses Dropbox to sync a Jekyll site to Heroku.

This example is Jekyll specific but could be modified to fit any static site generator.

Create a new Heroku App

Create a new Heroku App. Let’s pretend we named it my-secret, once created it would be available at my-secret.herokuapp.com.

Screenshot of Heroku Dashboard

Connect Dropbox

Under the Deploy tab, click Dropbox and connect your account. This connection will create a new folder in your Dropbox: ~/Dropbox/Apps/heroku/my-secret (the name of your app).

Symlink to your _site/ folder

Now that we we have a my-secret project folder in our Dropbox, we want to delete it! Instead we want a “symlink” to our Jekyll app’s _site/ folder.

In terminal, type the following two command (substituting the proper directory names):

cd ~/Dropbox/Apps/heroku/ && rm -r my-secret
ln -s ~/path/to/jekyllapp/_site my-secret

You should be able to open ~/Dropbox/Apps/heroku/my-secret/ and see a list of files in your compiled _site/ directory.

Force Heroku to think it’s a Ruby App

Even though it’s just static HTML in your _site/ folder, Heroku needs to know what type of server stack to put it on. We create really tiny web server in Ruby that handles all HTTP requests and uses HTTP Basic Authentication to protect the whole subdomain.

We need 3 files to make that happen: config.ru, Gemfile, and a Gemfile.lock.

# config.ru
use Rack::Auth::Basic, "Restricted Area" do |username, password|
  [username, password] == ['admin', 'admin']
end

use Rack::Static, :urls => [""], :root => '.', :index => 'index.html'

run lambda { |env|
  [
    200,
    {
      'Content-Type'  => 'text/html',
      'Cache-Control' => 'public, max-age=0'
    },
    File.open('index.html', File::RDONLY)
  ]
}

We all know admin/admin is a tried and true security pattern, but be sure to change it to something unique. You also need a Gemfile, you probably already have one because of Jekyll, but at a minimum you need one with the rack gem specified.

# Gemfile
source :rubygems
gem 'rack', '~> 1.6.0'

After creating these files, run bundle install to create your Gemfile.lock

One Click Deploy

Whenever you’re ready to deploy a new version, just click the button in your Heroku admin area. This will siphon the files from your Dropbox “folder” (remember, its not a folder anymore, it’s a symlink) and roll it out to your domain: http://my-secret.herokuapp.com.

Happy secret website sharing! If you stumble across something even more simple, I’d love to hear about it.