So can we? In short – mostly, but it’s still got some rough edges.
OSMF already has the website and API up and running, obviously, and it needs some pretty specialist hardware for the databases. There are no plans whatsoever to move all that to Heroku, so at first glance it seems rather pointless for me to investigate if it actually works. So why am I spending my time on this?
Firstly, it’s useful for other people to have their own working copies of the website. They can deploy the same code, but use their copy to map historic features that aren’t relevant in OpenStreetMap. Or they can use it to make collaborative fantasy maps, or maps for proposed local developments, or other projects that aren’t suitable for putting in the main database.
Secondly, it’s also useful for developers. We already have a system on the OSMF development server for testing branches, which allows non-developers to check how proposed features work, debug them and provide feedback on them. But if you have a branch to test you need to ask the sysadmins, and wait for them to deploy it for you, and you don’t get full control over the instance if you want to debug it or to dive into the database.
But mainly, I’m doing this because Heroku is a useful yardstick. Even if you aren’t interested in using Heroku itself, it’s perhaps the best example of a modern Rails hosting environment. If we can make it easy to deploy on Heroku, we’ll have made it easy to deploy in all manner of different deployment situations, whether that’s in-house in a controlled corporate environment, or using cloud native builder images for Kubernetes, or something else. So I think it’s worth using Heroku to find out where the kinks are in deploying our code, and then to iron those kinks out.
Some ironing is required
In no particular order, here are some of the problems I came across today:
- Our repository is huge. It’s about 380M and so it takes a long time to push to Heroku for the first time. What’s worse, is that if there’s an error during the first deployment, Heroku doesn’t cache the git repository, and so you need to upload it again (and again). I stumbled across a way to push the code without triggering a build, which saved me heaps of time later on as I fixed other build errors.
libarchive isn’t available on Heroku. We use the ffi-libarchive gem as part of our trace processing, but the underlying library is missing and this stops the build process. I worked around it by removing the gem, but a better approach would involve adding Heroku’s apt builder image.
Missing settings.local.yml file. There’s a bug about this already, and we’ve added a workaround in all of our install notes, travis configs and so on, but it rears its head again here.
No ActiveStorage configuration file. This is the nexus of configuration files, twelve-factor, and deployment-agnostic development. I could write a whole essay on this but simply committing
config/storage.ymlwas a good enough workaround for today.
Needs a Procfile. Heroku introduced the concept of Procfiles, which lists what needs to run to make the whole app work. Here’s a Procfile that works for us:
web: bundle exec rails server -p $PORT worker: bundle exec rake jobs:work
This tells Heroku that we want a webserver, but that we also need a worker process to import traces, and send emails asynchronously. Heroku then runs both processes automatically, along with detecting and configuring a database for us automatically too.
No ActiveStorage for traces. We have our trace import system hardcoded to use local file paths, but on Heroku those are ephemeral. In future we’ll move trace importing to using ActiveStorage, but there’s a couple of blockers on that for now.
So a few minor hiccups, but nothing particularly insurmountable. I was pleasantly surprised! While we work on resolving some of these problems, there’s a whole load of things that already work.
How we got here
I would describe getting to this stage as a useful “side effect” of lots of previous work. The most recent was replacing the compiled database functions with SQL equivalents, which are significantly easier to handle when you don’t control the database server. Previous work on using ActiveJob for trace processing makes the worker dyno setup possible, and moving the quad_tile code to an external gem made this part of the installation seamless.
Did I mention the price?
So how much does deploying your own copy of the OpenStreetMap website on Heroku cost? Nothing. Zero dollars per month. Heroku gives you 1 web and 1 worker dyno for free on each application that you deploy, and that’s all we need. It also offers a free database tier too, which is enough to get started. Of course these have limitations, and you’ll need to pay for some S3 storage if you want user images (and traces, in the future). But I think it’s worth pointing out that you can spin up your own deployment without having to pay, and dive into testing those new features or creating your own OSM data playground. I’m sure that’ll be useful to many people.