Reading ubuntu environment variables in elixir production app

I’m unable to get my application to read an environment variable set on Ubuntu. I keep getting the message below:

** (ArgumentError) could not fetch environment variable "VARIABLE" because it is not set

This is what I have in my prod.exs variable: System.get_env("VARIABLE") || "${VARIABLE}"

I then try to run my application as below

RELX_REPLACE_OS_VARS=true /home/app/prod/rel/my_app/bin/my_app start

I’ve looked everywhere but tutorials either seem mostly to lean towards Phoenix which I do not have in my application or using an additional dependency which I am not too inclined to do

Are you using relx to build your releases? Or distillery? Or the new elixir releases?

1 Like

I’m using the new elixir releases, I’m following this documentation. hexdox mix task release

Here’s my compilation script on the server

git pull origin cd ~/deploy/my_app MIX_ENV=prod mix deps.get --only prod && MIX_ENV=prod mix clean && MIX_ENV=prod mix compile && sudo MIX_ENV=prod mix release my_app &&

For a release you should just do System.get_env/1 in the config/release.exs, that’s it.

Or a config provider.

It is not clear what you are doing and in which file.

To be honest, so far I have not seen the error you are citing.

RELX_REPLACE_OS_VARS is a very old environment variable, it was changed to REPLACE_OS_VARS=true a while ago, maybe that will help?

Generally though you want to switch to using a releases.exs file as described here: https://hexdocs.pm/mix/Mix.Tasks.Release.html

1 Like

I tried that and I’m getting a nil which is very strange

Can you reproduce it in a minimal project on GitHub and provide explanation how you build and run it in the README?

Thank you, this is my first elixir project hence the mis-steps. I’ve removed all the references and the rest is per the tutorial suggested.

Okay, let me do it

I realised git will not necessarily illustrate my problem so let me try to be articulate as possible. Here’s my releases.exs

import Config

config :my_app,
  secret_key_base: System.fetch_env!("SECRET_KEY_BASE"),
  variable: System.fetch_env!("VARIABLE") #or System.get_env("VARIABLE")

In my function,

System.get_env("VARIABLE") # Nil
Application.get_env(:my_app, :variable) #NIL
System.fetch_env!("VARIABLE") #{"init terminating in do_boot",{#{'__exception__'=>true,'__struct__'=>'Elixir.ArgumentError',message=><<"could not fetch environment variable \"VARIABLE\" because it is not set">>}

However, printenv in Ubuntu and nano /etc/environment show the environment variable VARIABLE set

Another strange thing is that when I go into the interactive shell iex, System.get_env("VARIABLE") prints out the value

Do you start the app in the very same terminal as you do the printenv? Do you rebuild your app after changing the config?

I do the following:

The application is started by the script as a daemon running as a different user. I switched users and confirmed that the environment variable is also available to them

Nothing here starts your application.

How do you set it?

Systemd? Initrc? Anything else? Depending on your overal system configuration you might set the environment explicitely in the services start script.

1 Like

Sorry for late response. It was midnight as we were talking in my county so had to call it a night from fatigue. My application is setup as a Systemd daemon so when the compilation is done, this is how it looks the line that will start the compiled code

ExecStart=/home/app/my_app/prod/rel/my_app/bin/myapp start

I set the environment variables on the os by simply editing the /etc/environment file
Let me try set it explicitly.

I resolved this. I expected it to work out of the box as it did in my WSL configuration. However, didn’t know that systemd limited access to only variables set on service start. Thanks for your time and pointing me to the right direction with your questions

1 Like