i have a sinatra app. when loaded locally via bundler, everything is fine. when i load the app via systemd the app got started, but the config file seems to be not loading. It says that in the logs that its loaded but the values are not available inside the app
The unit file:
[Unit]
Description=PNL: Puppet Node Lister
After=network.target
[Service]
Type=simple
ExecStart=/bin/bundle exec ruby puppetdb_node_lister.rb
KillMode=process
Environment=RACK_ENV="production"
Restart=always
User=pnl
Group=pnl
WorkingDirectory=/opt/puppetdb_node_lister
[Install]
WantedBy=multi-user.target
my sinatra app:
require 'rubygems'
require 'sinatra'
require 'sinatra/config_file'
require 'json'
require 'rest-client'
require 'date'
require 'time'
require 'active_support/time_with_zone'
require 'tilt/erb'
### local methods
require_relative 'lib/methods.rb'
config_file 'config.yaml'
### request area
get '/' do
"#{settings.methods(false).inspect} <br/><br/> #{$:} <br/><br/> #{File.expand_path(File.dirname(__FILE__))}"
end
my yaml:
development:
username: 'test'
password: 'test'
puppetdb: 'puppet.example.com'
puppetsrv: 'puppet.example.com'
production:
username: 'superadmin'
password: 'somes3cret'
puppetdb: 'puppet.example.com'
puppetsrv: 'puppet.example.com'
local bundle output of /
[:app_file=, :app_file, :app_file?, :logging=, :logging, :logging?, :method_override=, :method_override, :method_override?, :run=, :run, :run?, :session_secret=, :session_secret, :session_secret?, :register, :environments=, :environments, :environments?, :username=, :username, :username?, :password=, :password, :password?, :puppetdb=, :puppetdb, :puppetdb?, :puppetsrv=, :puppetsrv, :puppetsrv?, :traps=, :traps, :traps?, :running_server=, :running_server, :running_server?, :handler_name=, :handler_name, :handler_name?]
["/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/sinatra-contrib-1.4.7/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/sinatra-1.4.7/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/tilt-2.0.4/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/rubygems-update-2.6.4/hide_lib_for_update", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/rest-client-1.8.0/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/rack-test-0.6.3/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/rack-protection-1.5.3/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/rack-1.6.4/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/netrc-0.11.0/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/multi_json-1.12.1/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/mime-types-2.99.2/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/http-cookie-1.0.2/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/domain_name-0.5.20160310/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/unf-0.1.4/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/unf_ext-0.0.7.2/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/unf_ext-0.0.7.2/lib", "/usr/share/gems/gems/bundler-1.7.8/lib/gems/bundler-1.7.8/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/backports-3.6.8/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/activesupport-4.2.6/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/tzinfo-1.2.2/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/thread_safe-0.3.5/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/minitest-5.9.0/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/json-1.8.3/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/json-1.8.3/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/i18n-0.7.0/lib", "/usr/share/gems/gems/bundler-1.7.8/lib", "/usr/local/share/ruby/site_ruby", "/usr/local/lib64/ruby/site_ruby", "/usr/share/ruby/vendor_ruby", "/usr/lib64/ruby/vendor_ruby", "/usr/share/rubygems", "/usr/share/ruby", "/usr/lib64/ruby/"]
/opt/puppetdb_node_lister
systemd output of /
[:app_file=, :app_file, :app_file?, :logging=, :logging, :logging?, :method_override=, :method_override, :method_override?, :run=, :run, :run?, :session_secret=, :session_secret, :session_secret?, :register, :environments=, :environments, :environments?, :traps=, :traps, :traps?, :running_server=, :running_server, :running_server?, :handler_name=, :handler_name, :handler_name?]
["/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/sinatra-contrib-1.4.7/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/sinatra-1.4.7/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/tilt-2.0.4/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/rubygems-update-2.6.4/hide_lib_for_update", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/rest-client-1.8.0/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/rack-test-0.6.3/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/rack-protection-1.5.3/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/rack-1.6.4/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/netrc-0.11.0/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/multi_json-1.12.1/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/mime-types-2.99.2/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/http-cookie-1.0.2/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/domain_name-0.5.20160310/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/unf-0.1.4/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/unf_ext-0.0.7.2/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/unf_ext-0.0.7.2/lib", "/usr/share/gems/gems/bundler-1.7.8/lib/gems/bundler-1.7.8/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/backports-3.6.8/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/activesupport-4.2.6/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/tzinfo-1.2.2/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/thread_safe-0.3.5/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/minitest-5.9.0/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/json-1.8.3/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/json-1.8.3/lib", "/opt/puppetdb_node_lister/vendor/bundle/ruby/gems/i18n-0.7.0/lib", "/usr/share/gems/gems/bundler-1.7.8/lib", "/usr/local/share/ruby/site_ruby", "/usr/local/lib64/ruby/site_ruby", "/usr/share/ruby/vendor_ruby", "/usr/lib64/ruby/vendor_ruby", "/usr/share/rubygems", "/usr/share/ruby", "/usr/lib64/ruby/"]
/opt/puppetdb_node_lister
one can see, that if loaded via systemd the values in settings (which would come from the yaml) are missing.
can anybody help me with that? am i doing this right, or is there i'm missing something?
after all it was
Environment=RACK_ENV="production"
which should be more like
Environment=RACK_ENV=production
after this change, everything worked as expected!
Your systemd configuration looks good to me. You set both the environment variables and the WorkingDirectory correctly.
Replace your app that with something that just dumps out the environment and the current directory. Run this test app through bundler, and also via systemd.
You should find there's still some difference between the environment that is being set up by systemd and your alternate method. Resolve the differences. :)
I'm writting a simple web app (sinatra) thats does github authentication.
I have to make a create a link with a callback param, somethig like: https://github.com/login/oauth/authorize?client_id=b5b1a33df1c7b5acccac&redirect_uri=http://localhost:4567/step2callback&scope=public_repo,user,gist,admin:repo_hook,gist, so that when the uses click on it it will authenticate, authorize my application, then send the user back to my web app.
Since i'm using rspec, I would like to make a code that pass on tests and on production, so I would like to get the current host+port to use it on the code I generate the link, something like:
HOST = get_current_host # this is the problem, how to get it?
#authorize_url = #client.authorize_url(#client.client_id,
{
:redirect_uri => "#{HOST}/step2",
:scope => 'public_repo,user,gist,admin:repo_hook,gist'
})
So, my question is how do I get my current running host on heroku, so my code would work on test and production?
You can configure different values for different environments
A simple example given below:
# File: test.rb
require 'sinatra'
# Set the values of various host names based on deployment environment
configure(:production) { set :host, "production-host" }
configure(:development) { set :host, "development-host" }
configure(:test) { set :host, "test-host" }
get '/' do
"Hi #{settings.host}"
end
Set RACK_ENV environment variable to environment value - production, development, or test
>set RACK_ENV=test
Run the Sinatra App
>ruby test.rb
[2015-12-17 20:20:46] INFO WEBrick 1.3.1
[2015-12-17 20:20:46] INFO ruby 2.1.7 (2015-08-18) [x64-mingw32]
== Sinatra (v1.4.6) has taken the stage on 4567 for test with backup from WEBrick
[2015-12-17 20:20:46] INFO WEBrick::HTTPServer#start: pid=11040 port=4567
Access the URL:
>curl http://localhost:4567
Hi test-host
If you are using Rack to run your Sinatra app, you could have following as config.ru
# config.ru
require 'sinatra'
require './test.rb'
configure(:production) { set :host, "production-host" }
configure(:development) { set :host, "development-host" }
configure(:test) { set :host, "test-host" }
run Sinatra::Application
In this case, test.rb will be simplified like below:
# test.rb
require 'sinatra'
get '/' do
"Hi #{settings.host}"
end
You can specify the environment on command line as shown below:
> rackup -E test config.ru
This answer is inspired from Sinatra configuring environments on the fly
I have mounted the Sidekiq panel in my Sinatra app like this:
require 'rubygems'
require 'bundler'
require 'sidekiq/web'
env = ENV['RACK_ENV'].to_sym || :development
Bundler.require(:default, :sinatra, env)
disable :run
Encoding.default_external = Encoding::UTF_8
set :environment, env
use Rack::ShowExceptions
use Rack::Session::Pool
use Rack::MethodOverride
Sidekiq::Web.use Rack::Session::Pool
require File.expand_path '../app/my_app.rb', __FILE__
run Rack::URLMap.new("/" => MyApp.new, "/sidekiq" => Sidekiq::Web.new)
This means my app is accessible through / and the sidekiq web panel through /sidekiq.
Now when I try to delete a job, I always get Forbidden. I read here https://github.com/mperham/sidekiq/issues/1289 and here https://github.com/mperham/sidekiq/issues/2487 but wether upgrading to rack-protection > 1.5.1 nor setting a session for Sidekiq::Web has solved the problem so far.
I'm starting my server with rackup using WEBrick, so I think this shouldn't be a server problem.
I'm using sinatra 1.4.2 with sidekiq 3.5.1. Any ideas on how to solve this?
I've found a solution. First I updated from sidekiq 3.4.2 to 4.0.1 and from sinatra 1.4.2 to 1.4.6. No problems so far.
The problem with the Forbidden message was a missing authenticity token for sidekiq's web panel. By adding the following lines, it worked:
require 'rubygems'
require 'bundler'
require 'sidekiq/web'
#####################################
# added a require for rack/protection
require 'rack/protection'
#####################################
env = ENV['RACK_ENV'].to_sym || :development
Bundler.require(:default, :sinatra, env)
disable :run
Encoding.default_external = Encoding::UTF_8
set :environment, env
use Rack::ShowExceptions
use Rack::Session::Pool
use Rack::MethodOverride
#####################################
# tell sinatra to use rack's protection methods
use Rack::Protection
#####################################
require File.expand_path '../app/my_app.rb', __FILE__
run Rack::URLMap.new("/" => MyApp.new, "/sidekiq" => Sidekiq::Web.new)
Also have a look at https://github.com/sinatra/rack-protection where all the protection methods are listed.
You may need to add this to application.rb (or an initializer like config/initializers/sidekiq.rb):
Sidekiq::Web.instance_variable_get(:#middleware).delete_if do |middleware|
middleware.first == Rack::Protection
end
That comes from a recent commit, but it's only applied to production and staging environments.
Detailed explanation about this problem.
I'm building a Sinatra application that needs to be threadable, as I'm using sucker-punch for jobs, and I want to use the Puma server to do it though I've never used it before.
For some reason, when I start my application it runs Thin.
I uninstalled Thin and it uses Puma, which is good, but how do I stop it from starting with Thin in the future in the case this happens again?
I start my application with rackup and I have in my main app.rb file:
class App < ::Sinatra::Base
configure do
set :show_exceptions, true
set :root, Info[:root]
set :threaded, true
set :server, :puma
Tilt.register Tilt::ERBTemplate, 'html.erb'
enable :logging
use Rack::CommonLogger, Log.file
if ENV['APP_ENVIRONMENT'] == 'PROD'
set :environment, :production
set :bind, '0.0.0.0', HOST
set :show_exceptions, false
end
end
end
You need to set your server in the config.ru rackup file. In this file you can set
Rack::Handler.get('puma').run App.new
Documentation is available in "Module: Rack::Handler".
However an even better way is to just run Puma explicitly:
bundle exec puma config.ru
OR as suggested by #matt:
rackup -s puma
Just run it with bundle exec. That ensures the gems available are only the ones specified on your Gemfile.
So, even if you have thin installed, but you have puma on your Gemfile, it will pick puma.
Is there a way to get information about the current Rack environment in Rake? For example, how can I tell whether Rack is running in development or production mode?
I understand that Rake is not Rack-aware. I'm trying to avoid replicating code in nearly-identical Rake tasks between production and dev environments.
Question is old but never fetched the best practice answer or a satisfying answer at all.
The real question is: How to go sure which environment is used in a Rake task in order to load the correct configuration / hitting into correct if-conditions.
Note: As Rake doesn't give much about Rack (Rake is not using HTTP) to
rely on the RACK_ENV is basically wrong but common and handy if a Rake
task loads your main Sinatra application (the RACK_ENV is required to let
Sinatras development? / test? / production? being set correctly).
The answer: Set the environment with each Rake task call.
Command line call:
/usr/bin/rake namespace:task_name RACK_ENV=production
Cronjob call (in crontab):
cd /into/your/app/root && /usr/bin/rake namespace:task_name RACK_ENV=production --silent
Note: To specify the path of the Rake bin is not necessary if you have it in your global system variables. Your path might differs from mine used in the examples, check on Unix systems with: whereis rake
You can check the RACK_ENV in your tasks via:
puts ENV["RACK_ENV"]
As other environment variable, you can retrieve it using:
ENV['RACK_ENV']
Considering it's a Sinatra application, and that you've set the environment into config/environment.rb, you can add the following to your Rakefile:
task :environment do
require File.expand_path('config/environment', File.dirname(__FILE__))
end
task :your_task => :environment do
# task
end
Then, you can retrieve the environment (depending how you set it up in your environment.rb) with ENV['RACK_ENV'] or Sinatra::Application.environment.
Considering there isn't a config/environment.rb config file, only the application file, for instance hello_world.rb, the following works:
hello_world.rb:
require 'sinatra'
set :environment, :production
get '/' do
'Hello World'
end
Rakefile:
task :environment do
require File.expand_path('hello_world', File.dirname(__FILE__)) # your Sinatra app
end
task :your_task => :environment do
puts Sinatra::Application.environment
end
When doing rake your_task you should obtain:
> rake your_task
production
After 2.5 years, I want to share what I've found to be the best solution.
Create a .env file in the root folder of the application, and add a flag specifying the application environment:
ENVIRONMENT=development
Then use Brandon Keepers' dotenv gem to load all environment variables from this file. Now you can use any environment variables specified in .env within Rake tasks.
Rake will rely on the explicit value set in .env, so you must create separate .env files for each environment you plan on using (e.g. dev, test, staging, production, etc).
Sample Rakefile:
require 'dotenv/tasks'
task :default => :help
desc 'Show this help menu'
task :help do
puts "Available rake tasks:"
system('rake --tasks')
end
# Will run in any environment
desc 'Demo task'
task :demo_task => :dotenv do
puts "Running demo task in '#{ENV['ENVIRONMENT']}' mode"
end
# Will only run if ENVIRONMENT value in .env file is set to 'production'
desc 'Production-only task'
task :production_task => :dotenv do
if ENV['ENVIRONMENT'] == 'production'
puts "Running 'Production-only' task"
else
puts "Won't run, because the environment is not set to PRODUCTION!"
end
end
# Will only run if ENVIRONMENT value in .env file is set to 'development'
desc 'Development-only task'
task :dev_task => :dotenv do
if ENV['ENVIRONMENT'] == 'development'
puts "Running 'Development-only' task"
else
puts "Won't run, because the environment is not set to DEVELOPMENT!"
end
end
If you want to use the environment variables within your Rack or Sinatra app (which you probably do), add the following to the application's config or bootstrap block:
require 'dotenv'
Dotenv.load