Repo.init not running

I’m using edeliver and distillery to deploy a phoenix app. It starts up fine but any database calls makes it crash.
The logs tell me that there is a missing key in my Repo config. And sure enough, if I attach iex and run Repo.config(), database, host, etc. is missing. The way I set them up is through the Repo.init callback like this:
module App.Repo do
use Ecto.Repo, otp_app: :app

    def init(_, opts) do
        opts = 
          opts
          |> set_from_env_var(:hostname, "DB_HOST")
          |> set_from_env_var(:username, "DB_USER")
          |> set_from_env_var(:password, "DB_PASS")
          |> set_from_env_var(:database, "DB_NAME")

        {:ok, opts}
      end

      defp set_from_env_var(opts, key, env_var) do
        if var = System.get_env(env_var) do
          Keyword.put(opts, key, var)
        else
          opts
        end
      end

Now the env variables are definitively set on the system, because if I run the application through mix everything works as intended and the config is set correctly. I can do that because my build server and staging server are the same at the moment. So I guess something makes the release behave differently. Anyone else encountered this problem or know what it could be?

1 Like

Where have you defined this function? Which Ecto version are you using? Is the Repo started at all? What is the exception message and stacktrace? The more information you can give about a problem, the easiest it will be for others to help you.

2 Likes

How do you start your release?

Are you starting it from the same shell, as you do with mix, or are you using something like systemd to start it? If so, hough does your service description look like?

1 Like

I start it through edeliver, using
mix edeliver start staging

which does start the server, I can watch pages from the app. It’s just when they call out to the database that I get an internal error.

1 Like

The function is defined inside App.Repo as was generated by phx.new.
Ecto version is 2.2.10

The exception from the log files is:
GenServer #PID<0.20288.8> terminating
** (RuntimeError) Connect raised a KeyError error. The exception details are hidden, as
they may contain sensitive data such as database credentials.

(elixir) lib/keyword.ex:377: Keyword.fetch!/2
(postgrex) lib/postgrex/protocol.ex:98: Postgrex.Protocol.connect/1
(db_connection) lib/db_connection/connection.ex:135: DBConnection.Connection.connect/2
(connection) lib/connection.ex:622: Connection.enter_connect/5
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3

I tried to find out if the Repo was started but since I’m pretty new to Elixir I couldn’t figure out how. Since this is on a server I don’t have access to :observer

1 Like

How are you setting up the env variables? ~/.profile? Are you using the same system user to start the app as you do when running mix?

1 Like

I set them in /etc/profile.d/app.sh
I’m not sure how that works with edeliver actually. In the config I set a user which is used for building etc, which is the same one I use when I ssh into the server. But maybe it uses another user to actually run the app. That’s a good lead though. I’m a windows developer so I just used the ubuntu docs to find what I assumed was the way to set global environments but seeing as it’s located under profile.d that might not be the best assumption.
I’ll see if I can find a better way to set them to test.
I do appreciate all of you helping out so far!

1 Like

So @amnu3387 's leading question helped me solve this. I moved my env vars to /etc/environment and everything works!
So now I feel like a total noob :slight_smile:
Again, I appreciate all of you helping even though it was not elixir related in the end. Next time I’ll aim to have a more fitting question!

2 Likes

I guess you run this locally, while it then connects to a server and runs your application there?

On your local computer or on the host where you want your application to be run?

If the latter, is this even sourced for the user you are running to use the application?

Maybe you need to manually source it in your start scripts. But I do not know enough about edeliver to tell how to do so.

1 Like

Yeah, the edeliver command is run locally.
The env vars are all on the staging server. So I’m guessing it was that they were not loaded correctly for whatever user was running the application.

Usually having then accessible to the user responsible for building is what you need, as long as you’re setting them in the config scripts, if on runtime it has to be on the user running the app.

Glad it helped!

Btw, I am glad to say this error message will also be a bit better in future postgrex releases!

2 Likes