# Phoenix environment variables not available at runtime

**URL:** <https://community.fly.io/t/phoenix-environment-variables-not-available-at-runtime/4051>\
**Category:** Questions / Help\
**Tags:** phoenix-files\
**Created:** [February 12, 2022, 1:51pm UTC](https://community.fly.io/t/phoenix-environment-variables-not-available-at-runtime/4051 "2022-02-12T13:51:25Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![abeeshake](https://sea1.discourse-cdn.com/fly1/user_avatar/community.fly.io/abeeshake/32/11492_2.png) [@abeeshake](https://community.fly.io/u/abeeshake)\
**Post date:** [February 12, 2022, 1:51pm UTC](https://community.fly.io/t/phoenix-environment-variables-not-available-at-runtime/4051/1 "2022-02-12T13:51:25Z")

</div>

when I use  
` @base_url System.get_env("MS_URL")`  
on localhost, it correctly identifies the variable and sets the endpoint properly.

but after I set my secrets via `fly secrets set MS_URL=$MS_URL" ` my url is only an empty string.

Any idea why?

---

<div class="post-metadata">

**Author:** ![greg](https://sea1.discourse-cdn.com/fly1/user_avatar/community.fly.io/greg/32/2119_2.png) [@greg](https://community.fly.io/u/greg)\
**Post date:** [February 12, 2022, 2:58pm UTC](https://community.fly.io/t/phoenix-environment-variables-not-available-at-runtime/4051/2 "2022-02-12T14:58:26Z")

</div>

Strange. I guess the first thing to check would be to see what value is being sent _to_ Fly. So make sure $MS\_URL is the value you expect (e.g `echo "$MS_URL"`) and not an empty string.

I’ve found using variables is complicated by running commands like `fly secrets set` in a _script_ (like bash) vs directly (like in Terminal, on a Mac). Sometimes the variable you think should be there/accessible (and so being set) isn’t. Debugging with an `echo` can confirm it is. And then proceed accordingly.

---

<div class="post-metadata">

**Author:** ![Alex\_Piechowski](https://sea1.discourse-cdn.com/fly1/user_avatar/community.fly.io/alex_piechowski/32/39888_2.png) [@Alex\_Piechowski](https://community.fly.io/u/Alex_Piechowski)\
**Post date:** [February 12, 2022, 3:04pm UTC](https://community.fly.io/t/phoenix-environment-variables-not-available-at-runtime/4051/3 "2022-02-12T15:04:43Z")

</div>

> [@abeeshake](#):
>
> fly secrets set MS\_URL=$MS\_URL"

Does `echo $MS_URL` output the expected output?  
Perhaps there’s a char that isn’t valid bash, you could try quoting the variable to prevent special char expansion:  
`fly secrets set MS_URL="$MS_URL"`

---

<div class="post-metadata">

**Author:** ![kurt](https://sea1.discourse-cdn.com/fly1/user_avatar/community.fly.io/kurt/32/43757_2.png) [@kurt](https://community.fly.io/u/kurt)\
**Post date:** [February 12, 2022, 3:41pm UTC](https://community.fly.io/t/phoenix-environment-variables-not-available-at-runtime/4051/4 "2022-02-12T15:41:07Z")

</div>

Which file are you using `System.get_env("MS_URL")` in?

The thing that always gets me on Phoenix is compile time environment variables. `config/config.ex`, `config/prod.exs` are executed at compile time, if you use env variables there you won’t see your app secrets. `config/runtime.exs` will see secrets because it’s executed at runtime.

---

<div class="post-metadata">

**Author:** ![abeeshake](https://sea1.discourse-cdn.com/fly1/user_avatar/community.fly.io/abeeshake/32/11492_2.png) [@abeeshake](https://community.fly.io/u/abeeshake)\
**Post date:** [February 12, 2022, 3:43pm UTC](https://community.fly.io/t/phoenix-environment-variables-not-available-at-runtime/4051/5 "2022-02-12T15:43:21Z")

</div>

I am using `System.get_env("MS_URL")` it just before I make http call via `Tesla` to define my base url.

It is in `lib/myapp/api.ex` which handles all the external api calls I need to make.

---

<div class="post-metadata">

**Author:** ![kurt](https://sea1.discourse-cdn.com/fly1/user_avatar/community.fly.io/kurt/32/43757_2.png) [@kurt](https://community.fly.io/u/kurt)\
**Post date:** [February 12, 2022, 3:48pm UTC](https://community.fly.io/t/phoenix-environment-variables-not-available-at-runtime/4051/6 "2022-02-12T15:48:17Z")

</div>

Definitely try what @greg and @Alex_Piechowski suggested then:

Connect to your app:

```auto
fly ssh console

```

Echo environment variable:

```auto
echo "$MS_URL"

```

You can also print all environment variables with `env`.

If the environment variable is not there, it likely means it didn’t get set properly. When an app release breaks after a secret is set, we rollback to the previous version.

---

<div class="post-metadata">

**Author:** ![Alex\_Piechowski](https://sea1.discourse-cdn.com/fly1/user_avatar/community.fly.io/alex_piechowski/32/39888_2.png) [@Alex\_Piechowski](https://community.fly.io/u/Alex_Piechowski)\
**Post date:** [February 12, 2022, 4:01pm UTC](https://community.fly.io/t/phoenix-environment-variables-not-available-at-runtime/4051/7 "2022-02-12T16:01:45Z")

</div>

> [@kurt](#):
>
> ```auto
> echo "$MS_URL"
> 
> ```

I’d like to know the results locally as well.  
If there’s any “dotenv” dependency, that could cause the env to be set inside the local app but not in bash

---

<div class="post-metadata">

**Author:** ![abeeshake](https://sea1.discourse-cdn.com/fly1/user_avatar/community.fly.io/abeeshake/32/11492_2.png) [@abeeshake](https://community.fly.io/u/abeeshake)\
**Post date:** [February 12, 2022, 10:00pm UTC](https://community.fly.io/t/phoenix-environment-variables-not-available-at-runtime/4051/8 "2022-02-12T22:00:22Z")

</div>

echo “$MS\_URL” on local environments prints the url.

I print the url via IO.inspect and then `fly logs`

- and it is printed as `nil`.

---

<div class="post-metadata">

**Author:** ![abeeshake](https://sea1.discourse-cdn.com/fly1/user_avatar/community.fly.io/abeeshake/32/11492_2.png) [@abeeshake](https://community.fly.io/u/abeeshake)\
**Post date:** [February 12, 2022, 10:02pm UTC](https://community.fly.io/t/phoenix-environment-variables-not-available-at-runtime/4051/9 "2022-02-12T22:02:01Z")

</div>

> [@Alex\_Piechowski](#):
>
> If there’s any “dotenv” dependency, that could cause the env to be set inside the local app but not in bash

I use plain bash script. so i believe this is ruled out.

---

<div class="post-metadata">

**Author:** ![abeeshake](https://sea1.discourse-cdn.com/fly1/user_avatar/community.fly.io/abeeshake/32/11492_2.png) [@abeeshake](https://community.fly.io/u/abeeshake)\
**Post date:** [February 12, 2022, 10:27pm UTC](https://community.fly.io/t/phoenix-environment-variables-not-available-at-runtime/4051/10 "2022-02-12T22:27:50Z")

</div>

Also,

```auto
Error No change detected to secrets

```

when I tried to set secrets via

`fly set secrets MS_URL="$MS_URL"`

---

<div class="post-metadata">

**Author:** ![greg](https://sea1.discourse-cdn.com/fly1/user_avatar/community.fly.io/greg/32/2119_2.png) [@greg](https://community.fly.io/u/greg)\
**Post date:** [February 13, 2022, 1:16am UTC](https://community.fly.io/t/phoenix-environment-variables-not-available-at-runtime/4051/11 "2022-02-13T01:16:43Z")

</div>

I guess there are two parts where it could be failing:

1. _setting_ the secret variable (ie, a blank value is sent to Fly)
2. _getting_ the secret variable (ie, a blank value is returned from Fly)

So … how about setting a fixed string, using your terminal, outside of any bash script to something e.g:  
`fly secrets set MS_URL="https://www.example.com"`  
… and what does Fly return?

If Fly says _no change detected_, well you know it has that value _already_ set (and so the issue must be **2** ). But if Fly lets you set the secret and so triggers a new release, well then you know it did _not_ already have it (and so the issue must be **1** ).

---

<div class="post-metadata">

**Author:** ![abeeshake](https://sea1.discourse-cdn.com/fly1/user_avatar/community.fly.io/abeeshake/32/11492_2.png) [@abeeshake](https://community.fly.io/u/abeeshake)\
**Post date:** [February 13, 2022, 4:03am UTC](https://community.fly.io/t/phoenix-environment-variables-not-available-at-runtime/4051/12 "2022-02-13T04:03:18Z")

</div>

> **Debugging problem - 2) is the problem**
>
> `fly secrets set MS_URL="https://www.example.com"`
> 
> _No change detected_ is what fly returns.
> 
> So the problem is **2)**

* * *

> **1) is ok. Verified here.**
>
> also, doing `fly ssh console` , then `echo $MS_URL` → returns the correct url!

> **IO.inspect from my code returns nil**
>
> where I define `System.get_env("MS_URL")` , I IO.inspect and it returns `nil`

---

<div class="post-metadata">

**Author:** ![Alex\_Piechowski](https://sea1.discourse-cdn.com/fly1/user_avatar/community.fly.io/alex_piechowski/32/39888_2.png) [@Alex\_Piechowski](https://community.fly.io/u/Alex_Piechowski)\
**Post date:** [February 13, 2022, 2:41pm UTC](https://community.fly.io/t/phoenix-environment-variables-not-available-at-runtime/4051/13 "2022-02-13T14:41:31Z")

</div>

> [@abeeshake](#):
>
> where I define `System.get_env("MS_URL")` , I IO.inspect and it returns `nil`

Where exactly are you using System.getenv? Could it be using the build ENV to build that value?

---

<div class="post-metadata">

**Author:** ![greg](https://sea1.discourse-cdn.com/fly1/user_avatar/community.fly.io/greg/32/2119_2.png) [@greg](https://community.fly.io/u/greg)\
**Post date:** [February 13, 2022, 4:05pm UTC](https://community.fly.io/t/phoenix-environment-variables-not-available-at-runtime/4051/14 "2022-02-13T16:05:29Z")

</div>

Ah, ok, so you know it’s _set_, it’s definitely the _get_.

Following on from Alex and Kurt’s ideas, it also sounds to me like that variable is not available at runtime. As you get the value _nil_, the default, ie “that’s not set”.

What happens with `Application.get_env` ? Only I was just looking at [Elixir: Runtime vs. compile time configuration | AmberBit Sp. z o. o.](https://www.amberbit.com/blog/2018/9/27/elixir-runtime-vs-compile-time-configuration/) and that was an idea from **Phase 4**

---

<div class="post-metadata">

**Author:** ![chrismccord](https://sea1.discourse-cdn.com/fly1/user_avatar/community.fly.io/chrismccord/32/50976_2.png) [@chrismccord](https://community.fly.io/u/chrismccord)\
**Post date:** [February 14, 2022, 1:31pm UTC](https://community.fly.io/t/phoenix-environment-variables-not-available-at-runtime/4051/15 "2022-02-14T13:31:01Z")

</div>

Baking the value into a module attribute happens at compile-time, so the `System.get_env` is going to return nil at build time. Note that building _can_ happen in a remote builder on fly, but can also be built locally, so your secrets won’t be available to the build env. What you want instead is to set the value in your `runtime.exs` configuration, then read it at runtime in your module. So instead of `@base_url`, you want to reference `base_url()` which can be a private function that does:

```
Application.fetch_env!(:my_app, :base_url)

```

Or similar. Then you’ll be good to go!

---

<div class="post-metadata">

**Author:** ![abeeshake](https://sea1.discourse-cdn.com/fly1/user_avatar/community.fly.io/abeeshake/32/11492_2.png) [@abeeshake](https://community.fly.io/u/abeeshake)\
**Post date:** [February 15, 2022, 4:14am UTC](https://community.fly.io/t/phoenix-environment-variables-not-available-at-runtime/4051/16 "2022-02-15T04:14:01Z")

</div>

Found examples from your livebeats Repo!

Thank you so much for insights! (on how should I reason above secrets)
