Using Puma with Rails application - ruby-on-rails

My configuration:
Rails 5.2.3
Ruby 2.6.3
rbenv
puma
capistrano
nginx
Ubuntu 18.04
I've been reading up on how to get all this setup and configured for deployment, but I don't seem to be able to find one place, that's got a clear and complete guide.
One of the things that confuse me the most is Puma. Some of the guides, do not mention anything about configuring Puma on the server, and all the instructions, reference the Puma Gem. A couple of other guides, discuss setting up and configuring Puma on the server, and modifications in the /etc/init folder.
Do I need to setup and configure Puma on the server, separately, before I can start using it for my Rails application?

No you do not need to set up and configure Puma on the server. Puma is a gem. So if you list it in your application's Gemfile, when you run bundle install for your Rails application, Puma will be installed automatically.
Any configuration for puma should go in your application, under config/puma.rb.
Does this answer your question?

When running Rails locally, just use config/puma.rb for your Puma config, and run Puma similar to the following:
RAILS_LOG_TO_STDOUT=1 bin/pumactl -F config/puma.rb start
The above will run Puma in the foreground. I personally use Overmind in development to run Puma, Webpacker, Sidekiq, and sometimes ngrok. That means I only need one iTerm tab for all of those.
To get bin/pumactl, run bin/bundle binstubs puma.
You could also run Puma using bin/rails server, but Puma recommends not doing that because not all of Puma's configuration options are available through that method.
A sample Puma config (based on what the capistrano3-puma gem produces [https://github.com/seuros/capistrano-puma/blob/v4.0.0/lib/capistrano/templates/puma.rb.erb]):
# frozen_string_literal: true
# config/puma.rb
require 'dotenv/load' # load a .env file for environment variables; gem 'dotenv-rails'
require 'nenv' # nicer ENV handling; gem 'nenv'
directory(File.expand_path('..', __dir__))
rackup(File.expand_path('../config.ru', __dir__))
environment(Nenv.rack_env || Nenv.rails_env || 'development')
# or without nenv
#environment(ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development')
threads(0, (Nenv.max_threads || 16).to_i)
# or without nenv
#threads(0, (ENV['MAX_THREADS'] || 16).to_i)
port((Nenv.port || 3_000).to_i)
# or without nenv
#port((ENV['PORT'] || 3_000).to_i)
workers 0
restart_command 'bundle exec puma'
prune_bundler
on_restart do
puts('Refreshing Gemfile...') # rubocop:disable Rails/Output
Nenv.bundle_gemfile = File.expand_path('../Gemfile', __dir__)
# or without nenv
#ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', __dir__)
end
For handling Puma using Capistrano, I recommend the capistrano3-puma gem (https://github.com/seuros/capistrano-puma). This gem has various tasks, one of which is puma:config which will create a puma.rb file in the shared directory. You would then add puma.rb to the :linked_files Capistrano config option:
# config/deploy.rb
append(:linked_files, 'puma.rb')
As for setting up a server (one you deploy to), you want to install Nginx and set that up to serve your Rails app. Again, the capistrano3-puma gem can come in handy for this, as it includes an Nginx plugin which provides a task to upload a config to your server. If you don't want to use that plugin, then I'd at least recommend looking at the template (https://github.com/seuros/capistrano-puma/blob/v4.0.0/lib/capistrano/templates/nginx_conf.erb) for that config, and then adapting it to your needs.
As #matt-v-from-toronto mentioned, Puma is installed as part of your app, and not separately on the server. Doing a bin/bundle install, or similar, will install Puma along with all of your other gems listed in your Gemfile.

Related

Sinatra app in Rails 4.1 config

I want to fake an API with a little Sinatra app, following this method. Meaning I have a Rails app, and in the spec/support folder, a very simple Sinatra app:
module FakePrograms
class Application < Sinatra::Base
get "/API/V1/programs" do
{
programs: [
...
]
}.to_json
end
end
end
Part of the goal is to launch this app locally, so I can work on my Rails app with a fake API. Problem: when I do ruby spec/support/fake_programs.rb, the app can't boot, and I get a
config/puma.rb:14:in `block in _load_from':
uninitialized constant
#<Class:#<Puma::DSL:0x007fac0b0e0380>>::ActiveRecord (NameError)
Looks like Sinatra is booting using my Rails configuration. I don't need ActiveRecord nor Puma for my fake API.
I've read this question and this other one, but theese are in different context, because they need their Sinatra app to share routes with the Rails app.
Content of config/puma.rb:
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['MAX_THREADS'] || 5)
threads threads_count, threads_count
preload_app!
rackup DefaultRackup
port ENV['PORT'] || 3000
environment ENV['RACK_ENV'] || 'development'
on_worker_boot do
# Worker specific setup for Rails 4.1+
# See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot
ActiveRecord::Base.establish_connection
end
I was looking at the config.ru file, but #max is right, it's not correlated.
The Puma README says:
By default, if no configuration file is specified, Puma will look for a configuration file at config/puma.rb.
Which is why your app is using this config file.
It goes on to say:
If you want to prevent Puma from looking for a configuration file in those locations, provide a dash as the argument to the -C (or --config) flag:
$ puma -C "-"
Since Puma can handle Sinatra apps directly, you could start your app like this:
$ puma -c "-" spec/support/fake_programs.rb
If you want to start your app using ruby with Puma as the built in server (as you are doing now), I think adding this to your Sinatra app should work (neither Sinatra’s :server_settings or Puma’s :config_files are very well documented):
set :server, 'puma'
set :server_settings, {:config_files => "-"}

Prevent puma from running in locally (ruby on rails)

I'm recently started to use Puma for my production server with nginx, however, when I now try to run my app locally, it tries to run Puma with all my production settings and fails. How can I prevent Puma from running locally?
AFAIK all I've done was added the puma gem to my gemfile, so I don't know how it's accessing my server config (I'm just not too knowledgeable in this area). I have it in my production group:
group :production do
gem 'pg'
gem 'rails_12factor'
gem 'puma'
end
Error:
→ rails s
=> Booting Puma
=> Rails 4.2.6 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
[8917] Puma starting in cluster mode...
[8917] * Version 3.4.0 (ruby 2.0.0-p645), codename: Owl Bowl Brawl
[8917] * Min threads: 1, max threads: 6
[8917] * Environment: development
[8917] * Process workers: 1
[8917] * Phased restart available
[8917] * Listening on tcp://localhost:3000
[8917] Use Ctrl-C to stop
/rbenv/versions/2.0.0-p645/lib/ruby/gems/2.0.0/gems/puma-3.4.0/lib/puma/runner.rb:103:in `reopen': No such file or directory - /Users/me/mll/shared/log/puma.stdout.log (Errno::ENOENT)
Additionally, though less important to me right now, is it in my benefit to run Puma locally? If so, any tips/resources on how I can do that?
You need to put puma in your production group. Like this:
group :production do
gem 'puma'
end
That way puma will only be used on production and not development.
Update
Make sure that your bin/rails file looks like this:
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
require 'rails/commands'
Having the exact same issue with Ben. I try to use web brick on local while developing and testing, and puma in production.
Gem file is perfectly define as puma only sits in production group. 'bin/rails' and 'config/application' are checked, same as #Răzvan Ciocănel suggested. Still boot with 'puma' on local.
At last, have a look into the 'bundle install' gem list, 'puma' is installed along with other 'production' gem. Run 'bundle install --without production' and now local will boot with web brick as ROR default.
I guess as long as puma is bundle installed, it will be loaded on local unless you config something to force it off. So the solution might be to remove the gem in the bundle list in development and test.
Rails 3 project (it keeps hanging around longer than expected...)
I changed from unicorn to puma in the production group of my gemfile.
group :production do
gem 'puma'
end
Then then when trying to run tests, or a dev server (which should have been thin) I got:
C:\Rails Projects\Rep>rails s
Could not find gem 'puma x86-mingw32' in any of the gem sources listed in your Gemfile or available on this machine.
Run `bundle install` to install missing gems.
After poking around a bit (including finding this question) I gave up and decided to go ahead and use puma in dev. I ran bundle install and tried running server and voila, thin was working again.
Then I realized I still only had it in the production group--I looked back at the bundle install and nothing was installed, puma still isn't installed. But now that bundle install has been run since the edit to the gemfile, everything works again.
C:\Rails Projects\Rep>rails s
=> Booting Thin
=> Rails 3.2.22.2 application starting in development on http://0.0.0.0:3000
So I guess the 'missing gem' error I wasn't because it was trying to actually run puma but rather some kind of bundler generated error due to unattempted gemfile? Just putting this out in case it speed things up for anyone in similar circumstances who ends up here.

Deploying Rails Engine on Heroku

Does anyone know how to deploy a rails engine on heroku? The engine that I am developing is self contained so I am trying to avoid making another wrapper rails application to deploy my engine.
FIXED
I had to add config.ru and Procfile in my engine root directory to so that heroku knows that its a rails application.
Thanks,
Ajay
I guess is more dependant on how you've built your engine. If you can run it standalone locally, it'll run just fine like that on Heroku - there's nothing about Heroku which would make running your code any harder other than the normal constraints
As the edit of the question states, config.ru and Procfile are needed. I just copied config.ru from a Rails app and changed the path:
# This file is used by Rack-based servers to start the application.
require ::File.expand_path('../test/dummy/config/environment', __FILE__)
run Rails.application
As for Procfile, the following will work:
web: bundle exec rackup -p $PORT
You may want to add a gem for web server, as it will default to WEBrick which is not suitable for production.
In order to get proper logs on Heroku, add the following to the Gemfile
gem 'rails_12factor', group: :production
Assets compilation won’t work unless you define the assets:precompile task (according to https://devcenter.heroku.com/articles/ruby-support#rails-4-x-applications-compile-phase).
I just added the following to engine’s Rakefile:
namespace :assets do
desc 'Precompile assets within dummy app'
task :precompile do
Dir.chdir('test/dummy') do
system('bundle exec rake assets:precompile')
end
end
end
I also disabled JS compression (or you can add uglifier gem to the Gemfile).

How to start rails server?

I am developing rails 2.3.2 application.
When I type the command "rails script/server"
I got the following output instead of server starting why?
rails script/server
Usage:
rails new APP_PATH [options]
Options:
-J, [--skip-javascript] # Skip JavaScript files
[--dev] # Setup the application with Gemfile pointing to your Rails checkout
[--edge] # Setup the application with Gemfile pointing to Rails repository
-G, [--skip-git] # Skip Git ignores and keeps
-m, [--template=TEMPLATE] # Path to an application template (can be a filesystem path or URL)
-b, [--builder=BUILDER] # Path to a application builder (can be a filesystem path or URL)
[--old-style-hash] # Force using old style hash (:foo => 'bar') on Ruby >= 1.9
[--skip-gemfile] # Don't create a Gemfile
-d, [--database=DATABASE] # Preconfigure for selected database (options: mysql/oracle/postgresql/sqlite3/frontbase/ibm_db/jdbcmysql/jdbcsqlite3/jdbcpostgresql/jdbc)
# Default: sqlite3
-O, [--skip-active-record] # Skip Active Record files
[--skip-bundle] # Don't run bundle install
-T, [--skip-test-unit] # Skip Test::Unit files
-S, [--skip-sprockets] # Skip Sprockets files
-r, [--ruby=PATH] # Path to the Ruby binary of your choice
# Default: /home/xichen/.rvm/rubies/ruby-1.8.7-p352/bin/ruby
-j, [--javascript=JAVASCRIPT] # Preconfigure for selected JavaScript library
# Default: jquery
Runtime options:
-q, [--quiet] # Supress status output
-s, [--skip] # Skip files that already exist
-f, [--force] # Overwrite files that already exist
-p, [--pretend] # Run but do not make any changes
Rails options:
-h, [--help] # Show this help message and quit
-v, [--version] # Show Rails version number and quit
Description:
The 'rails new' command creates a new Rails application with a default
directory structure and configuration at the path you specify.
Example:
rails new ~/Code/Ruby/weblog
This generates a skeletal Rails installation in ~/Code/Ruby/weblog.
See the README in the newly created application to get going.
When I type linux command "ls" I got the following directories and files showing:
app Capfile config criptq db doc features Gemfile Gemfile.lock generate lib log nbproject public Rakefile README script spec test tmp vendor
my Gemfile is:
source "http://rubygems.org"
gem "rails", "2.3.2"
gem "mysql", "2.8.1"
gem "fastercsv"
gem "will_paginate", "2.3.16"
gem "chronic", "0.6.4"
gem "whenever", "0.4.1"
gem "searchlogic", "2.4.28"
group :development do
gem "mongrel", "1.1.5"
end
group :test do
gem "rspec", "1.3.2"
gem "rspec-rails", "1.3.4"
gem "factory_girl", "1.3.3"
end
In a Rails 2.3 app it is just ./script/server start
For rails 3.2.3 and latest version of rails you can start server by:
First install all gem with command: bundle install or bundle.
Then Configure your database to the database.yml.
Create new database: rake db:create
Then start rails server.
rails server orrails s
For rails 2.3.2 you can start server by:
ruby script/server
In rails 2.3.x application you can start your server by following command:
ruby script/server
In rails 3.x, you need to go for:
rails s
Make sure you're in the right directory when you start the server
sites>yoursite> rails s
On rails 3, the simpliest way is rails s.
In rails 2, you can use ./script/server start.
You can also use another servers, like thin or unicorn, that also provide more performance.
I use unicorn, you can easily start it with unicorn_rails.
BTW, if you use another things, like a worker (sidekiq, resque, etc), I strongly recommend you to use foreman, so you can start all your jobs in one terminal windows with one command and get a unified log.
For rails 4.1.4 you can start server:
$ bin/rails server
Goto root directory of your rails project
In rails 2.x run > ruby script/server
In rails 3.x use > rails s
For newest Rails versions
If you have trouble with rails s, sometimes terminal fails.
And you should try to use:
./bin/rails
To access command.
For the latest version of Rails (Rails 5.1.4 released September 7, 2017), you need to start Rails server like below:
hello_world_rails_project$ ./bin/rails server
=> Booting Puma
=> Rails 5.1.4 application starting in development
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.10.0 (ruby 2.4.2-p198), codename: Russell's Teapot
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
More help information:
hello_world_rails_project$ ./bin/rails --help
The most common rails commands are:
generate Generate new code (short-cut alias: "g")
console Start the Rails console (short-cut alias: "c")
server Start the Rails server (short-cut alias: "s")
test Run tests except system tests (short-cut alias: "t")
test:system Run system tests
dbconsole Start a console for the database specified in
config/database.yml
(short-cut alias: "db")
new Create a new Rails application. "rails new my_app" creates a
new application called MyApp in "./my_app"
If you are in rails2 version then to start the server you have do,
script/server or
./script/server
But if you are in rails3 or above version then to start the server you have do,
rails server or
rails s
in rails 2.3.X,just type following command to start rails server on linux
script/server
and for more help read "README" file which is already created in rails project folder
I also faced the same issue, but my fault was that I was running "rails s" outside of my application directory.
After opening the cmd, just go inside your application and run the commands from their, it worked for me.
You have to cd to your master directory and then rails s command will work without problems.
But do not forget bundle-install command when you didn't do it before.
run with nohup to run process in the background permanently if ssh shell is closed/logged out
nohup ./script/server start > afile.out 2> afile.err < /dev/null &
Rails version < 2
From project root run:
./script/server
I believe this is what happens if "rails new [project]" has not actually executed correctly. If you are doing this on windows and "rails server" just returns the help screen, you may need to restart your command prompt window and likely repeat your setup instructions. This is more likely true if this is your first time setting up the environment.

How define his own server with Rails 3

I want use always thin when I start my rails server in development mode.
By default it webrick to use. So I add thin in my Gemfile
gem 'thin', :group => 'development'
Now If I want use it to launch my server in development mode I mandatory define it.
bundle exec rails s thin
If I don't define it, it's always use webrick. So How define using thin by default ?
Instead of rails s just type :
>> thin start -p 3000
Where 3000 is the number of your port.
You can also specify an enviornment :
>> thin start -e production
Assuming you are using bundler 1.0.x and your gems is vendorized:
bundle exec vendor/ruby/1.9.1/bin/thin start

Resources