Playing With Fire

Exploring the web one Elixir at a time

Hosting Phoenix Applications on Heroku

Heroku is a natural platform to deploy Phoenix applications to. It builds your application automatically on a code push, uses Postgres as the standard data store and has a stable components ecosystem to expand the services on offer. Best of all, for low capacities, i.e. for development, its free

 

Heroku

First off, you will need an account on Heroku. If you don’t already have one head over to the Heroku Sign up Page, fill in the form and follow the instructions provided.

Heroku provides a suit of command line tools called Heroku CLI that allows you access to all features of your account. Installation of this tool is provided on that page.

Once you are installed, the next thing that you will need to do is create an App on Heroku.

There are two ways of doing this: via the CLI tool or the Heroku website.

For brevity we’ll use the CLI set up, so pull out your handy terminal, navigate to the directory where your nice shiny Phoenix/Elixir app is and enter this:

$ heroku apps:create

Creating app... done, ⬢ example-name-62029
https://example-name-62029.herokuapp.com/ | https://git.heroku.com/example-name-62029.git

The output of this command is the URL of the app created and the URL for the git repo that will be used for deployments.

Next thing then is to set up the git remote.

 

Git

I won’t go through setting up Git or provide usage instructions beyond the necessary to set this up. I am assuming that this directory is already under some form of DVCS control.

If not, then $ git init will sort that out.

To link this to the Heroku remote issue the following (changing the git remote URL to that returned by the apps:create command)

$ git remote add heroku https://git.heroku.com/example-name-62029.git
$ git remote -v
origin  <your git host URL> (fetch)
origin  <your git host URL> (push)
heroku  https://git.heroku.com/example-name-62029.git (fetch)
heroku  https://git.heroku.com/example-name-62029.git (push)

I’m using ‘heroku’ here as the target master as I’m assuming that you’ve already got origin set.

 

Buildpacks

In order to have Heroku build and serve Elixir/Phoenix projects you need to add some build packs and create the relevant configurations.

Phoenix projects require two buildpacks:

$ heroku buildpacks:set https://github.com/HashNuke/heroku-buildpack-elixir
$ heroku buildpacks:add https://github.com/gjaldon/heroku-buildpack-phoenix-static.git

With buildpacks set up the need a little bit of configuration. Create each of the following in root of your application directory (next to your mix.exs file).

elixir_buildpack.config

erlang_version=19.2                       <-- Put the required Erlang version here
elixir_version=1.4.1                      <-- Put the required Elixir version here
always_rebuild=true                       <-- Use this to force a rebuild the application each time

phoenix_static_buildpack.config

clean_cache=true                          <-- clean the phoenix cache
node_version=7.4.0                        <-- an appropriate node version for your code
npm_version=4.1.2                         <-- an appropriate npm version for your code

 

Procfile

Heroku uses the Procfile to run the application server, so you’ll need to add one of those. Add this file in the same directory as the two files above:

Procfile

web: MIX_ENV=prod mix phoenix.server

 

Database

The next thing that you will need to do is set up the database on Heroku. Here I’m setting up a PostgreSQL database in line with a default Phoenix application

$ heroku addons:create heroku-postgresql --app example-name-62029
    Creating postgresql-deep-6913... done, (free)
    Adding postgresql-deep-6913 to my-app... done
    Setting DATABASE_URL and restarting my-app... done, v5
    Database has been created and is available

    $ heroku addons --app my-app
    Add-on                                     Plan       Price
    ─────────────────────────────────────────  ─────────  ─────
    heroku-postgresql (postgresql-deep-6913)   hobby-dev  free
    └─ as DATABASE

This returns an environment variable DATABASE_URL.

When you’ve done this, you will also need to create a secret base key and pool size on Heroku

$ heroku config:set POOL_SIZE=18
$ mix phoenix.gen.secret
<created secret key>
$ heroku config:set SECRET_KEY_BASE="<created secret key>"

 

Update Phoenix prod configuration

You will need to update your config/prod.exs file to use the new environment variables - update the secret_key_base and the database configuration:

use Mix.Config

config :appKey, PhoenixApp.Endpoint,        <-- change :appKey and PhoenixApp to your application
  http: [port: {:system, "PORT"}],
  url: [scheme: "http", host: "appURL"],   <-- change appURL to your site URL
  #force_ssl: [rewrite_on: [:x_forwarded_proto]],
  cache_static_manifest: "priv/static/manifest.json",
  secret_key_base: System.get_env("SECRET_KEY_BASE")

config :logger, level: :info

config :appKey, PhoenixApp.Repo,
  adapter: Ecto.Adapters.Postgres,
  url: System.get_env("DATABASE_URL"),
  pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
  ssl: true

 

Run deployment

Everything should now be in order to be able to deploy code.

$ git commit -am 'Message'
$ git push heroku master           <-- or whatever your branch is called
...                                <-- Loads of output
remote: Verifying deploy.... done.

 

Run Heroku setup scripts

If this is the initial deploy, run the following tasks

$ heroku run "POOL_SIZE=2 mix run priv/repo/seeds.exs"
Running POOL_SIZE=2 mix run priv/repo/seeds.exs on ⬢ example-name-62029... up, run.4778 (Free)
$ heroku run "POOL_SIZE=2 mix phoenix.digest"
Running POOL_SIZE=2 mix phoenix.digest on ⬢ example-name-62029... up, run.3980 (Free)
Check your digested files at "priv/static"
$ heroku run "POOL_SIZE=2 mix ecto.migrate"  
Running POOL_SIZE=2 mix ecto.migrate on ⬢ example-name-62029... up, run.9353 Free)

...

12:47:26.002 [info]  == Migrated in 0.0s

 

Check the site

Navigate to the URL that was created in the apps:create command given above, in the case of this post https://example-name-62029.herokuapp.com

If all has gone well, then you should see your site running.

Until next time.