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?
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.
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?
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.
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
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!
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
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!
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.