DEV Community

loading...

Deploying Elixir to Render.com

Murphy Randle
Iā€™m a professional software writer specialized in Web technologies and engaged in indie application development. I consider myself to be a man of faith. I pursue honesty, integrity, and compassion.
Originally published at mrmurphy.dev on 惻2 min read

I've deployed a few different Elixir services to the hosting platform https://render.com and found their provided documentation to be lacking for real-world Phoenix apps. Especially if you're using Live View. Here's an augmentation to their guide with the extra steps you might be missing.

Initial Setup

Follow the official guide: https://render.com/docs/deploy-phoenix but don't deploy your service yet. You'll need to make some changes:

Add Evars

Add some new evars:

  • ELIXIR_VERSION = 1.10.3 or whatever version you like. But the default version is older and breaks the build for new Elixir apps
  • DATABASE_URL = The connection string for the database you'll be using

Migrations

After, do these things. MAKE SURE YOU REPLACE WITH YOUR APP NAME :

  • Add a new script for running migrations (./build_and_migrate.sh):
#!/usr/bin/env bash
# exit on error
set -o errexit

./build.sh

# Run migrations
_build/prod/rel/<app_name>/bin/<app_name> eval "Render.Release.migrate"
Enter fullscreen mode Exit fullscreen mode
  • Make that new script executable.
  • Make a module in your application for running migrations (lib/<app_name>_web/render_release.ex):
defmodule Render.Release do
  @moduledoc """
    Responsible for custom release commands
  """
  @app :<app_name>

  def migrate do
    # Allows the migration script to connect to a database using SSL.
    Application.ensure_all_started(:ssl)

    for repo <- repos() do
      {:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true))
    end
  end

  def rollback(repo, version) do
    # Allows the migration script to connect to a database using SSL.
    Application.ensure_all_started(:ssl)

    {:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :down, to: version))
  end

  defp repos do
    Application.load(@app)
    Application.fetch_env!(@app, :ecto_repos)
  end
end
Enter fullscreen mode Exit fullscreen mode
  • Change the deploy command for your render app to be ./build_and_migrate.sh instead of ./build.sh

Using a Database that Requires SSL

Unless you're using a private database on Render, you'll want to connect to your PG instance using SSL. To do that, you've got to

  • Uncomment the line in releases.exs that says ssl: true for your app's repo:
...
config :<app_name>, <AppName>.Repo,
  ssl: true, <-- this line, it's commented by default.
  url: database_url,
Enter fullscreen mode Exit fullscreen mode

And then

  • Add the :ssl application to extra_applications in mix.exs:
def application do
    [
      mod: {<AppName>.Application, []},
      extra_applications: [:logger, :runtime_tools, :ssl] <-- added :ssl to the end of this list.
    ]
  end
Enter fullscreen mode Exit fullscreen mode

Troubleshooting

If you run into an issue with Phoenix Live View breaking and reloading the page every few seconds, you might have enabled force_ssl in your endpoint, and it could be trying to redirect your web socket traffic to an https scheme. Which is strange. I ran into this once, and haven't found a great workaround for it.

PgBouncer

If your database does pooling using pg_bouncer then open up releases.exs and add prepare: :unnamed to your repo config.

config :<app_name>, <AppName>.Repo,
  ssl: true,
  url: database_url,
  pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
  prepare: :unnamed <-- this line!
Enter fullscreen mode Exit fullscreen mode

Discussion (0)