I've built a Rails-Api with React SPA frontend following this guide (very helpful, would recommend). I'm having issues getting Heroku to set the environment variables in the .env file that React uses for config vars. The values of the file are just set as literally "ENV[...]" instead of evaluating and setting the value. On the Rails side the Heroku ENV vars are being set correctly because I can see them in the console.
.env file:
REACT_APP_API_KEY=ENV['API_KEY']
REACT_APP_AUTH_DOMAIN=ENV['AUTH_DOMAIN']
App.js (top level Component):
console.log(config,process.env);
// which logs:
{
NODE_ENV: "production"
REACT_APP_API_KEY: "ENV['API_KEY']"
REACT_APP_AUTH_DOMAIN: "ENV['AUTH_DOMAIN']"
...
}
Rails Console:
irb(main):001:0> ENV
=> {"LANG"=>"en_US.UTF-8", "NODE_ENV"=>"production",
"API_KEY"=>"<correct-value>", "AUTH_DOMAIN"=>"<correct-value>",......}
Is there something I need to do in order to alert Heroku that the ENV vars need to also be set in the .env file for the react app? The tutorial has the Heroku deployment use both the nodejs and ruby buildpacks (in that order). The app is built and then copied into the "public" dir for Rails to serve:
package.json
{
//...
"engines": {
"node": "12.9.0",
"yarn": "1.22.4"
},
"scripts": {
"build": "yarn --cwd client install && yarn --cwd client build",
"deploy": "cp -a client/build/. public/",
"heroku-postbuild": "yarn build && yarn deploy"
}
}
I don't know enough about the internal workings with Heroku's env vars swap. From what I understand with Create React App... the .env file's contents are set at build time so it is possible that the js is compiled before Heroku has any chance to inject the env vars. I'm open to suggestion on other ways to do this if this method isn't doable. Thanks!
You can expand environment variables in .env file. When React app is built, it has access to variables in your Heroku dyno, and react-scripts supports referencing them in your .env file. See more in docs.
With this in mind, your .env file would look like:
REACT_APP_API_KEY=$API_KEY
REACT_APP_AUTH_DOMAIN=$AUTH_DOMAIN
Assuming API_KEY and AUTH_DOMAIN variables are set in Heroku.
If you name these variables REACT_APP_API_KEY and REACT_APP_AUTH_DOMAIN in Heroku in the first place, then they will be picked up by react-scripts directly from the environment (no need for .env file then)
NOTE: with the above said, it sounds like you are trying to expose secrets in React app. The Create React App docs strongly warns NOT to do that, because:
Environment variables are embedded into the build, meaning anyone can view them by inspecting your app's files.
Related
I'm using a file named .env.local in dev environment, and all env vars work fine!
When I pushed it to Netlify, they aren't located, is there some specific way of setting them?
I also seted them in Netlify.
But, I keep getting this error log:
What can I do?
If I'm not wrong, it seems like defined with Figaro variables are not available in Docker container.
I have env files to configure Postgresq DB:
POSTGRES_USER=ENV['db_user']
POSTGRES_PASSWORD=ENV['db_password]
POSTGRES_DB=ENV['db_name']
I have application.yml file copied with all the other Rails app files to the container (I could check it with ls in the container shell).
Is it a normal behaviour ?
I also faced this issue when working on a Rails application.
The thing to note here is that for Docker, environment variables are placed in a .env file or an env_file (my_variables.env). Environment files placed in .yml or .yaml files (application.yml) are not often recognized by Docker during runtime. Here's a link to Docker's official documentation that further explains it: The “.env” file
An example of such environment variables are Database connection strings which are required during the application startup process like:
database_name
database_username
database_password
However, you can still use the Figaro gem for defining variables that are not required during application startup, like:
RAILS_MASTER_KEY
That's all.
I hope this helps
I have a Rails 4 app with Dotenv gem to read variables from the file .env.
There are some variables I've set in order to have a mysql user other than "root" for my rails app, for example:
MYSQL_ROOT_USER='rootuser'
MYSQL_ROOT_PASSWORD='rootpassword'
APP_DATABASE_USER='mydbuser'
APP_DATABASE_PASSWORD='userpassword'
I've also created a bash script to create the mysql user under scripts/database_setup.bash
#!/bin/bash
source ../.env
# creates the user
mysql -u${MYSQL_ROOT_USER} --password="${MYSQL_ROOT_PASSWORD}" -e "CREATE USER '${APP_DATABASE_USER}'#'localhost' IDENTIFIED BY '${APP_DATABASE_PASSWORD}';"
# grants permission
mysql -u${MYSQL_ROOT_USER} --password="${MYSQL_ROOT_PASSWORD}" -e "GRANT ALL PRIVILEGES ON \`myapp\_%\`.* TO '${APP_DATABASE_USER}'#'localhost';"
On the server side, Capistrano deploys to `/home/myuser/apps/myapp/
I have three questions:
Where is the best place to put my server-side .env file? Right now I'm putting it in /home/myuser/apps/myapp/ directory.
How can I tell Capistrano to copy it to Rails root directory?
How can I tell Capistrano to execute my bash script before running migrations?
If anyone is still having troubles with this, here is how I got my .env working in production with Capistrano 3.5+:
Add your .env.production to /shared directory in production. Then, inside the deployment script, use Capistrano's append command to load linked files from the /shared directory like so:
append :linked_files, ".env.production"
Run the standard deploy (cap production deploy)
You can test whether env vars were appended by launching the rails console in production mode (rails c p) from inside the /current directory.
In production environment I think you shouldn't use .env at all.
Probably it's better to put the ENV vars in:
/etc/environment
by writing your variables like this:
export ENV_VARIABLE=value
I'm deploying my rails app with Capistrano. I want to save some API keys on the server as an environment variable. Those API keys should be accessible to my rails app that is deployed with Capistrano. Those API keys should also be accessible to a separate ruby file that is run as a daemon.
setting the API keys in environment variables seems like the ideal solution, however, I can't access them in my rails app with ENV["SOME_KEY"].
According to this post, because capistrano runs as non interactive and non login, ~/.bashrc and ~/.bash_profile are not loaded. The flowchart suggests that I should use $BASH_ENV.
Can I just add my api keys in $BASH_ENV and access them in my rails app and in the ruby file that is a daemon with ENV["SOME_KEY"]?
I'm also thinking of just adding the api keys to a file somewhere on the server and symlinking it to the ruby file dir and rails dir and just open and reading it. Would this be possible?
There are a few ways that work well with Capistrano, in my experience.
rbenv-vars
If you use Ruby via Rbenv on your server, then you are in luck. There is a Rbenv plugin called rbenv-vars that automatically injects environment variables into any Ruby process, which would include your Rails app. Just add your variables to ~/.rbenv/vars on the server using KEY=value syntax. That's it.
dotenv
The dotenv gem is a similar solution, but it works as a gem you add to your Rails app and doesn't require Rbenv or any other supporting tools. Add dotenv-rails to your Gemfile and deploy. Dotenv will automatically look for a .env.production file in the root of your Rails app. For Capistrano, create a .env.production file on the server inside Capistrano's shared directory, and then add .env.production to :linked_files. Now every deploy will link to it. Declare your variables using KEY=value syntax.
.bashrc
Declare your variables with export KEY=value syntax at very top of the ~/.bashrc file on the server. On Ubuntu, this file is evaluated even during an non-interactive SSH session. Just make sure you place the declarations on the top, before this case statement:
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
CentOS may be a different story, so YMMV.
I made a Capistrano plugin capistrano-env_config some time ago for managing and syncing environment variables across a Capistrano cluster which works by modifying the /etc/environment file to make environment variables available throughout the system. It's easy to use and is similar to how you can set environment variables with the Heroku toolbelt. Here are some examples:
cap env:list
cap env:get[VARIABLE_NAME, VARIABLE_NAME, ...]
cap env:unset[VARIABLE_NAME, VARIABLE_NAME, ...]
cap env:set[VARIABLE_NAME=VALUE, VARIABLE_NAME=VALUE, ...]
cap env:sync
I need to set up an environment variable for my rails app. Both in my local machine and in the production server. I read some tutorials on the internet but NONE has given the complete instruction on how to set and use these variable in the actual production server. I use digital ocean and linux server to host my rails app.
I have spent days trying to figure this out, but still haven't found a clear and complete instruction from setting the variables on my local machine -> push it to git repo -> set and use the variables in production server. So, hope somebody can help me here, thanks!
UPDATE:
This is how I currently setup the environment variables in my rails app by using figoro gem:
You can set system-wide environment variables in the /etc/rc.local file (which is executed when the system boots). If your Rails app is the sole user of the Linux system, that is a good place to store credentials such as API keys because there is no risk of including this file in a public Git repository, as it is outside the application directory. The secrets will only be vulnerable if the attacker gains shell access to your Linux server.
Set the environment variables within /etc/rc.local (do not include the <> characters):
export SOME_LOGIN=<username>
export SOME_PASS=<password>
To see the value of an environment variable, use one of the following commands in the Linux shell:
printenv MY_VAR
echo $MY_VAR
To access those environment variables within Rails, use the following syntax:
Inside .rb files or at the rails console
ENV['MY_VAR']
Inside .yml files:
<%= ENV['MY_VAR'] %>
For anyone still having this issue, figaro now has an easy method in setting the production variables in heroku. Just run:
$ figaro heroku:set -e production
ryzalyusoff.
For Unix
You can use LINUX ENV in rails application.
# .env
GITHUB_SECRET_KEY=SECRET
TWITTER_ACCESS_KEY=XXXXXXXXXXXX
# in rails code
puts ENV["TWITTER_ACCESS_KEY"] # => SECRET
Create .env files for local machine and your production server. Export environment variables like this(on server with ssh):
export GITHUB_SECRET_KEY="XXXXXXXXXXXXXXXXXX"
Anyway, storing keys in config - bad idea. Just add .env.example, others keys configs add to .gitignore. Goodluck.
Example with Rails
For Windows
Syntax
SET variable
SET variable=string
SET /A "variable=expression"
SET "variable="
SET /P variable=[promptString]
SET "
Key
variable : A new or existing environment variable name e.g. _num
string : A text string to assign to the variable.
expression : Arithmetic expression
Windows CMD
I believe we should not push a secret file on git.
To ignore such file use gitignore file and push other code on the git.
On the server side just copy the secret file and create a symlink for that file.
You can find demo here http://www.elabs.se/blog/57-handle-secret-credentials-in-ruby-on-rails
You can set your environment variables in production in the same way, you do it for local system. However, there are couple of gems, which make it easier to track and push to production. Have a look at figaro. This will help you in setting up and deployment of env vars.
You can do this with figaro gem
or in rails 4 there is a file named secret.yml in config folder where you can define your environment variables this file is by default in .gitignore file.For production you need to manually copy that file to server for security reason so that your sensitive information is not available to any one
First create your variable like:
MY_ENV_VAR="this is my var"
And then make it global:
export MY_ENV_VAR
You can check if the process succeeded with:
printenv
Or:
echo MY_ENV_VAR