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?
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?
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.
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"
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.
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.
Definitely try what @greg and @Alex_Piechowski suggested then:
Connect to your app:
fly ssh console
Echo environment variable:
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.
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
echo “$MS_URL” on local environments prints the url.
I print the url via IO.inspect and then fly logs
nil
.I use plain bash script. so i believe this is ruled out.
Also,
Error No change detected to secrets
when I tried to set secrets via
fly set secrets MS_URL="$MS_URL"
I guess there are two parts where it could be failing:
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).
fly secrets set MS_URL="https://www.example.com"
No change detected is what fly returns.
So the problem is 2)
also, doing fly ssh console
, then echo $MS_URL
→ returns the correct url!
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?
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. and that was an idea from Phase 4
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!
Found examples from your livebeats Repo!
Thank you so much for insights! (on how should I reason above secrets)