SSL connection can not be established because `:ssl` application is not started

I’m in the process of migrating my phoenix app from Gigalixir to Fly, and I’m getting this error when it tries to start my applicatoin after all the build steps in flyctl deploy.

It prints the generic elixir message to include :ssl in my extra_applications array, which I already do; this exact setup runs fine on Gigalixir’s infrastructure but doesn’t here for some reason.

E: Seems like by default the fly deploy system for phoenix apps tries to connect to the database while bypassing mix…this will definitely never work, is there a straightforward way to undo this behavior? I could try reverse engineering the migrate script which fly adds by default, not sure if that’s the fastest way though.

1 Like

Hi @slondr,

Is the “SSL connection” error message in relation to connecting to the database? Is the database a Fly hosted Postgres DB? If so, it’s running in a private network with your application and should not use SSL.

Since you mentioned bringing over an older/existing app, I’ll assume it was generated pre-Phoenix 1.6. In a newly generated Phoenix app, the config/runtime.exs config for DB connections are handled this way…

  maybe_ipv6 = if System.get_env("ECTO_IPV6"), do: [:inet6], else: []

  config :my_app, MyApp.Repo,
    # ssl: true,
    url: database_url,
    pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
    socket_options: maybe_ipv6

Note the ipv6 settings. Fly’s internal private network is an IPv6 network and needs to be addressed that way. Also note the ssl: true setting is commented out.

This is all assuming it’s a DB connection problem.

Hi @Mark, the database isn’t Fly-hosted, it’s hosted at another cloud service. As it’s crossing network boundaries it wouldn’t be secure to connect without SSL — hence the need for the ssl application at migrate time.

For what it’s worth, my runtime.exs does have the maybe_ipv6/ socket_options: maybe_ipv6 line.

Hi @slondr,

Thanks for the additional detail. I agree that you need/want SSL for connecting to the external DB. While probably unrelated, you may want to disable the ipv6 usage. The app, running on Fly, will detect the IPv6 network and assume that it wants to use IPv6 to connect to the DB. I’m assuming it is an IPv4 address, so if you are having connection issues, you may want to try turning that off.

For the actual problem, you haven’t described how your application is being built. Is it using a Dockerfile? Is it a multi-stage build that creates a release?

On Fly, your app is booted in a very limited way just to run the migrations. If the migrations succeed, then the app is deployed in a rolling deploy.

In the fly.toml file it executes the migration. It is assumed that you are deploying using releases and that Mix is not present.

If you haven’t, I’d suggest going through the experience of creating a new Elixir app and deploying it on Fly. Assuming that all works, then you have a basis of comparison for how the migrations are setup and working as well.

In principle, there are other people using external DBs on Fly and that shouldn’t be a problem.

Hi @Mark,

I was able to resolve this issue by adding :ssl.start() to the beginning of the load_app function defined in release.ex.

For context & posterity:

For the actual problem, you haven’t described how your application is being built. Is it using a Dockerfile? Is it a multi-stage build that creates a release?

My application is being built by the dockerfile/fly.toml automatically generated by fly launch. I haven’t modified either, other than updating the base image the Dockerfile points to, as the default docker image it tries to pull doesn’t exist.

Hi @slondr,

Thank you for sharing your solution! That makes sense now. Yes, if there are special services needed during migrations, they can be started explicitly.

A common approach to this is documented here: Application — Elixir v1.13.4

It would look like this:

{:ok, _} = Application.ensure_all_started(:ssl)