Elastic Beanstalk, Rails 5, and Passenger: Rails.env frustration - ruby-on-rails

I have a stack in Elastic Beanstalk running the "Passenger with Ruby 2.5 running on 64bit Amazon Linux/2.8.3" image. Rails is v5.2.1. The desire is to make it a staging environment i.e., have 'Rails.env' return 'staging' and run off of a staging.rb configuration. The problem is, it seems to be running as 'production' no matter what I do.
I set up RACK_ENV and RAILS_ENV as EB configuration variables, both set to 'staging'. I confirmed their existence on the server with 'printenv' as ec2-user, webapp, and root.
I tried changing passenger_app_env in the Passenger config to 'staging'. I've confirmed that Passenger Standalone is using the correct config by looking at the process with 'ps aux | grep passenger'.
I've tried switching to the root server and manually doing '/etc/init.d/passenger stop' and then 'start', and the printout confirms Passenger is launching with its 'environment' set to 'staging':
=============== Phusion Passenger Standalone web server started ===============
PID file: /var/app/support/pids/passenger.pid
Log file: /var/app/support/logs/passenger.log
Environment: staging
Accessible via: http://0.0.0.0/
Serving in the background as a daemon.
Problems? Check https://www.phusionpassenger.com/documentation/Users%20guide%20Standalone.html#troubleshooting
I put this into environment.rb and added an EB config var for STAGING to be 'true'.:
if ENV['STAGING']
%w(RACK_ENV RAILS_ENV).each do |key|
ENV[key] = 'staging'
end
end
However, the test page I made in my Rails app still says 'Rails.env' is 'production', and is not using values from 'staging.rb'. And yet, that same test page says that 'ENV['RACK_ENV']' and 'ENV['RAILS_ENV'] are both set to 'staging'.
At this point, I'm out of ideas on how to force the environment in any other way.

After much hacking, I discovered that Passenger was launching with a passenger_app_env of 'production' (its default) and then switching over to 'staging'. Rails.env would get the the
'production' env and use 'production.rb', then RACK_ENV and RAILS_ENV would be overwritten to 'staging', creating the confusing duality.
The solution was moving the passenger_app_env directive higher up in the Passenger Standalone template that Passenger uses; we had it inside of a server directive inside of an http directive. Moving it up out of the server directive and into the http directive itself solved the issue.

Related

How to get the passenger_app_env value from shell?

I am currently working on a shell script to manage a service who is part of a Rails App (Nginx + Phusion Passenger) and needs to be launched with systemd after Rails has started.
As a requirement the script needs the Rails environment value and I would like to get it from Passenger (passenger_app_env value).
# /etc/nginx/sites-enabled/webapp.conf:
server {
...
# Ensures that RAILS_ENV, NODE_ENV, etc are set to "staging"
# when your application is started.
passenger_app_env staging;
}
I was trying with passenger-config about OPTION, env, and printenv to get that value but without luck.
Does anybody know a way to get the value of passenger_app_env from the OS shell?

Rails missing SECRET_KEY_BASE in production

I have ubuntu server, Rails 5.0 and apache web server
Also I have many sites on it
When I add new site, I have an error "Incomplete response received from application"
When I check apache log I see message:
App 14561 stderr: [ 2017-01-17 21:01:16.5804 14591/0x0000000064e100(Worker 1) utils.rb:85 ]: *** Exception RuntimeError in Rack application object (Missing `secret_key_base` for 'production' environment, set this value in `config/secrets.yml`) (process 14591, thread 0x0000000064e100(Worker 1)):
My config/secrets.yml contains default value:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
Also I have just setted env variable SECRET_KEY_BASE via writting in a file /etc/profile
I see than via command echo $SECRET_KEY_BASE
How to fix error Incomplete response received from application
First, note that /etc/profile is only sourced when invoking an interactive login shell, so any variables set in this file wouldn't ever get run by a web-server daemon on startup, which is why it didn't work as expected in your attempt.
Since you're using Apache + Phusion Passenger, you can set application-specific environment variables within your Apache configuration files using the SetEnv option of mod_env.
Otherwise, you could set your environment variables from your application code by reading configuration on your application server's filesystem. You could use a gem like dotenv to automate this pattern.
See Phusion Passenger's documentation About Environment Variables: Passenger-Served Apps for a documentation reference.
Try restarting your server, it might need to be restarted to pick up new changes in your config files.
Your config/secrets.yml file should also have:
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
Depending on how you are starting the server the ENV variables may not be visible.
Have you tried:
SECRET_KEY_BASE='foo' rails s
Some discussion on environment variables with Rails servers is discussed at How to start Rails server with environment variables set?
Check you have mod_env
sudo a2enmod env
From your rails app [anywhere, does not matter, it's just a random string] run
rake secret
... outputs a big long string ...
Then add to your Apache Virtual Host definition.
somewhere in /etc/apache2/sites-available/*.conf
<VirtualHost ...>
SetEnv SECRET_KEY_BASE "thebiglongstringgeneratedbyrakesecret"
</VirtualHost>
Check your work
apache2ctl -t
Syntax OK
restart apache
apache2ctl restart
check it from the command line
curl https://my-server-url -I # or http
Leave a comment if that does do the trick.

nginx passenger - issues setting environment to staging

I'm running nginx with passenger on el7
the problem i am facing is when running with staging environment i am getting constant http 500 error.
I tried all the options i could find including:
passenger_app_env staging; / rails_env staging; / rack_env staging;
i am getting constant 500 error, and i can see in the logs that i am not reaching the rails server logic.
when i am switching that configuration to:
rails_env development / rails_env productions
everything works fine.
eventually the problem was in the staging.rb file and since i was using passenger it masked the error and just gave me 500.
eventually i moved from passenger to puma....which allowed me to debug and log rails with ease.

phusion passenger not seeing environment variables?

We are running ubuntu servers with Nginx + Phusion Passenger for our rails 3.0x apps.
I have an environment variable set in /etc/environment on the test machines:
MC_TEST=true
If I run a console (bundle exec rails c) and output ENV["MC_TEST"] I see 'true'.
But, if I put that same code on a page ( <%= ENV["MC_TEST"] %> ) it doesn't see anything. That variable does not exist.
Which leads me to question:
1 - What is the proper way to get environment variables into passenger with nginx (not apache SetEnv)?
2 - Why does Passenger not have a proper environment?
Passenger fusion v4+ enables reading of environment variables directly from bashrc file. Make sure that bashrc lives in the home folder of the user under which passenger process is executed (in my case, it was ubuntu, for ec2 linux and nginx)
Here is the documentation which goes into details of bashrc
I've the same problem with you when use passenger with nginx and nginx init script on ubuntu.
The reason is that I use sudo service nginx restart(installed by init script) to start up nginx and
it was running by root and the root did not get your login user environment variable.
There are two solutions for this.
One is running nginx manually.
sudo service nginx stop
sudo -E /path/to/your/nginx
one is add env to your nginx init script
export MC_TEST=true
The latter solution is somehow ugly, But it works. And I think the better way is found a configuration to tell the init script to preserve the login user env.
I got another ugly solution.
env_file = '/etc/environment'
if File.exist?(env_file)
text = File.open(env_file).read
text.each_line do |line|
key, val = line.split('=', 2)
ENV[key] = val.strip
end
end
With nginx you can use the variable passenger_env_var to it. See an example below
passenger_env_var GEM_HOME /home/foo/.rbenv/rubygems;
passenger_env_var GEM_PATH /home/foo/.rbenv/rubygems/gems;
So for your case
passenger_env_var MC_TEST true;

passenger/nginx - environment variable passing, or passenger variable passing

We have 2 rails environments with the same code. One is staging, the other production. Both run using the same 'production' rails settings.
But, we'd like to know what environment we are on. I thought I could set an environment variable on the servers and read that out inside of rails, but, while that works from the console it doesn't work when running behind passenger.
in the admin users .profile file I have:
export MC_TEST=true
But the nginx's/passengers running don't seem to be inside that same environment, and that variable is not set.
I thought I could then maybe put something in the nginx.conf to get passed back to the rails environment, but obviously I am not doing that right either!
So - can anyone tell me how to properly do this? Under no circumstances do we want this variable in ruby/rails/app code.
If you are using nginx with passenger (i.e passenger included in nginx installation), the configuration is as follows:
server {
server_name www.foo.com;
root /webapps/foo/public;
passenger_enabled on;
passenger_env_var DATABASE_USERNAME foo_db;
passenger_env_var DATABASE_PASSWORD secret;
}
https://www.phusionpassenger.com/library/config/nginx/reference/#passenger_env_var
Try passenger_set_cgi_param MC_TEST true in your nginx configuration
passenger_set_cgi_param docs

Resources