Deploying Elixir/Phoenix applications


Deployment process for Elixir / Phoenix apps a little bit different from Ruby with Ruby on Rails for example.

Notice: this tutorial assumes, that you familiar with Elixir and configuration / structure of Phoenix apps.

Let’s get started.

  def application do
    [...,
     applications: [..., :edeliver]]
  end

  defp deps do
    [...,
     {:edeliver, "~> 1.4.2"},
     {:distillery, "~> 1.4"}]
  end

Run mix deps.get to fetch the dependencies.

Next step - .edeliver/config file:

APP="YOUR_APP_NAME"

BUILD_HOST="YOUR_BUILD_HOST"
BUILD_USER="YOUR_BUILD_USER"
BUILD_AT="/tmp/edeliver/$APP/builds"

RELEASE_DIR="/tmp/edeliver/$APP/builds/_build/prod/rel/$APP"

# prevent re-installing node modules; this defaults to "."
GIT_CLEAN_PATHS="_build rel priv/static"

PRODUCTION_HOSTS="YOUR_PROD_HOST"
PRODUCTION_USER="YOUR_PROD_USER"
DELIVER_TO="/home/YOUR_USER/apps/YOUR_APP_NAME"

# For *Phoenix* projects, symlink prod.secret.exs to our tmp source
pre_erlang_get_and_update_deps() {
  local _prod_secret_path="/home/YOUR_USER/prod.secret.exs"
  if [ "$TARGET_MIX_ENV" = "prod" ]; then
    __sync_remote "
      ln -sfn '$_prod_secret_path' '$BUILD_AT/config/prod.secret.exs'
    "
  fi
}

pre_erlang_clean_compile() {
  status "Running phoenix.digest" # log output prepended with "----->"
  __sync_remote " # runs the commands on the build host
    # [ -f ~/.profile ] && source ~/.profile # load profile (optional)
    source ~/.profile
    # echo \$PATH # check if rbenv is in the path
    set -e # fail if any command fails (recommended)
    cd '$BUILD_AT' # enter the build directory on the build host (required)
    # prepare something
    mkdir -p priv/static # required by the phoenix.digest task
    npm install

    ./node_modules/brunch/bin/brunch build --production

    # run your custom task
    APP='$APP' MIX_ENV='$TARGET_MIX_ENV' $MIX_CMD phoenix.digest $SILENCE
  "
}

Run init for Distillery:

  mix release.init

Let’s build our release with verbose output for debug purposes:

  mix edeliver build release production --verbose

If successfull, we can go ahead. Let’s deploy our release to our production server.

  mix edeliver deploy release to production

And the last step - let’s start our production.

mix edeliver start production
# START DONE!

After that, you need to configure Nginx (for example) and point your upstream directive to correct host and port.