Ruby 2.5.1, Rails 5.2.2.1
I'm trying to make nginx get upstream through puma socket.
When I run rails s -e production all is good.
When I run rails s -e production -d Nginx returns 502 Bad Gateway
config/puma.rb
...
app_dir = "/home/user/myapp"
tmp_dir = "#{app_dir}/tmp"
# Set up socket location
bind "unix://#{tmp_dir}/sockets/puma.sock"
# Logging
stdout_redirect "#{app_dir}/log/puma.stdout.log", "#{app_dir}/log/puma.stderr.log", true
...
etc/nginx/sites-enabled/mydomain.com
upstream app {
# Path to Puma SOCK file, as defined previously
server unix:/home/user/myapp/tmp/sockets/puma.sock fail_timeout=0;
}
server {
listen 80;
server_name mydomain.com;
root /home/user/myapp/public;
try_files $uri/index.html $uri #app;
location #app {
proxy_pass http://app;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
var/log/nginx/error.log
2019/07/07 13:45:09 [error] 21609#21609: *11391 connect() to
unix:/home/user/myapp/tmp/sockets/puma.sock failed (111: Connection
refused) while connecting to upstream, client: 172.68.11.91, server:
mydomain.com, request: "GET /pages/one HTTP/1.1", upstream:
"http://unix:/home/user/myapp/tmp/sockets/puma.sock:/pages/one", host: "mydomain.com"
(P.S. change from original domain to mydomain.com)
What difference? How to fix it? Please explain and help
UPDATE
Seems to be running with daemon flag it doesn't create puma.sock in /home/user/myapp/tmp/sockets. Why and where is it?
The earlier answer does not work any more. The deamon option -d is deprecated.
You could use a systemd service:
sudo nano /etc/systemd/system/puma.service
Copy this to the file and fill in your YOUR_APP_PATH and FULLPATH:
[Unit]
Description=Puma HTTP Server
After=network.target
# Uncomment for socket activation (see below)
# Requires=puma.socket
[Service]
# Puma supports systemd's `Type=notify` and watchdog service
# monitoring, if the [sd_notify](https://github.com/agis/ruby-sdnotify) gem is installed,
# as of Puma 5.1 or later.
# On earlier versions of Puma or JRuby, change this to `Type=simple` and remove
# the `WatchdogSec` line.
Type=notify
# If your Puma process locks up, systemd's watchdog will restart it within seconds.
WatchdogSec=10
# Preferably configure a non-privileged user
# User=
# The path to your application code root directory.
# Also replace the "<YOUR_APP_PATH>" placeholders below with this path.
# Example /home/username/myapp
WorkingDirectory=<YOUR_APP_PATH>
# Helpful for debugging socket activation, etc.
# Environment=PUMA_DEBUG=1
# SystemD will not run puma even if it is in your path. You must specify
# an absolute URL to puma. For example /usr/local/bin/puma
# Alternatively, create a binstub with `bundle binstubs puma --path ./sbin` in the WorkingDirectory
ExecStart=/<FULLPATH>/bin/puma -C <YOUR_APP_PATH>/puma.rb
# Variant: Rails start.
# ExecStart=/<FULLPATH>/bin/puma -C <YOUR_APP_PATH>/config/puma.rb ../config.ru
# Variant: Use `bundle exec --keep-file-descriptors puma` instead of binstub
# Variant: Specify directives inline.
# ExecStart=/<FULLPATH>/puma -b tcp://0.0.0.0:9292 -b ssl://0.0.0.0:9293?key=key.pem&cert=cert.pem
Restart=always
[Install]
WantedBy=multi-user.target
Run systemctl daemon-reload to reload your services.
Then you can use sudo systemctl restart puma to restart/start/stop the service
Refer to the puma docs for more information.
Solution
Dont know why, but It works if run puma (not rails server)
RAILS_ENV=production bundle exec puma -C config/puma.rb -d
Related
I want to deploy RoR + React SPA to heroku as one project. As a typical production environment, use Nginx as web server and user Puma as app server.
I tried to follow readme of https://github.com/heroku/heroku-buildpack-nginx.
But after deployment, heroku popup an error
Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
Below are my configs
heroku buildpacks
heroku/nodejs # index 1
heroku/ruby # index 2
https://github.com/heroku/heroku-buildpack-nginx.git # index 3
Procfile
release: bundle exec rails db:migrate
web: bin/start-nginx bundle exec puma -C config/puma.rb
config/puma.rb
max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count
environment ENV.fetch("RAILS_ENV") { "development" }
plugin :tmp_restart
bind ENV.fetch('PUMA_SOCK') { 'unix:///tmp/nginx.socket' }
on_worker_fork do
FileUtils.touch('/tmp/app-initialized')
end
config/nignx.conf.erb => I removed unimportant config for this file because it is too long
http {
upstream app_server {
server unix:/tmp/nginx.socket fail_timeout=0;
}
server {
listen <%= ENV["PORT"] %>;
server_name _;
keepalive_timeout 5;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
}
}
}
EDIT: I think that the procfile should start Nginx too:
web: bin/start-nginx bundle exec puma -C config/puma.rb
Remember that for the nginx build pack you should disable the demon mode in the nginx.conf:
daemon off;
EDIT2: If that line doesn't work, try running Nginx directly (this is a hack, untested)):
web: bin/nginx -p . -c config/nginx.conf & ; bundle exec puma -C config/puma.rb
Also make sure the nginx logs are routed to stdout, placing this in the nginx.conf:
daemon off;
error_log /dev/stdout info;
http {
access_log /dev/stdout;
...
}
ORIGINAL:
As the documentation for the build pack states:
Basically, for webservers that are not designed for efficient, non-blocking I/O, we will benefit from having NGINX to handle all I/O operations
However, Puma is an efficient, non-blocking I/O server. You should be able to use it directly on a Heroku dyno.
The biggest advantage that Nginx could offer a Puma server is dealing with static files - which your configuration doesn't perform.
If you're not using Nginx for static files, you might decide to skip the extra latency added the Nginx proxy. Besides, Heroku's security features should (but might not) cover all the bases Nginx could offer you at this point.
If you need extra speed for static files - some Ruby servers (such as iodine or agoo) provide a fast static file service, allowing you to skip the Nginx layer and reduce latency.
Hi i followed this thread of digitalocean to deploy my RubyOnRails app on digitalocean vps
https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-puma-and-nginx-on-ubuntu-14-04
My Config:
512 MB RAM(with 1 gb swap)
ubuntu 16.04
Ruby2.33(with rbenv)
This tutorial lists usage of upstart but as i searched i found ubuntu 16.04 uses systemd.
I found this thread but still could start Puma Server
https://github.com/puma/puma/issues/1211
when i run which puma it gives
/home/ashish/.rbenv/shims/puma
Also here is my puma.service file
[Unit]
Description=Puma HTTP Server
After=network.target
# Uncomment for socket activation (see below)
# Requires=puma.socket
[Service]
# Foreground process (do not use --daemon in ExecStart or config.rb)
Type=simple
# Preferably configure a non-privileged user
User=www-data
# The path to the puma application root
# Also replace the "<WD>" place holders below with this path.
WorkingDirectory=/var/www/mystore.rentcallcenter.com
# Helpful for debugging socket activation, etc.
Environment=PUMA_DEBUG=1
# The command to start Puma. This variant uses a binstub generated via
# `bundle binstubs puma --path ./sbin` in the WorkingDirectory
# (replace "<WD>" below)
ExecStart=/home/ashish/.rbenv/shims/puma -b tcp://0.0.0.0:9292 -b ssl://0.0.0.0:9293?key=key.pem&cert=cert.pem
# Variant: Use config file with `bind` directives instead:
# ExecStart=<WD>/sbin/puma -C config.rb
# Variant: Use `bundle exec --keep-file-descriptors puma` instead of binstub
Restart=always
[Install]
WantedBy=multi-user.target
and here is my puma.rb in rails config folder
# Puma can serve each request in a thread from an internal thread pool.
# The `threads` method setting takes two numbers: a minimum and maximum.
# Any libraries that use thread pools should be configured to match
# the maximum value specified for Puma. Default is set to 5 threads for minimum
# and maximum; this matches the default thread size of Active Record.
#
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
threads 1, 6
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
#
#port ENV.fetch("PORT") { 3000 }
# Specifies the `environment` that Puma will run in.
#
environment ENV.fetch("RAILS_ENV") { "production" }
# Specifies the number of `workers` to boot in clustered mode.
# Workers are forked webserver processes. If using threads and workers together
# the concurrency of the application would be max `threads` * `workers`.
# Workers do not work on JRuby or Windows (both of which do not support
# processes).
#
workers ENV.fetch("WEB_CONCURRENCY") { 1 }
# Use the `preload_app!` method when specifying a `workers` number.
# This directive tells Puma to first boot the application and load code
# before forking the application. This takes advantage of Copy On Write
# process behavior so workers use less memory. If you use this option
# you need to make sure to reconnect any threads in the `on_worker_boot`
# block.
#
# preload_app!
# If you are preloading your application and using Active Record, it's
# recommended that you close any connections to the database before workers
# are forked to prevent connection leakage.
#
# before_fork do
# ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord)
# end
# The code in the `on_worker_boot` will be called if you are using
# clustered mode by specifying a number of `workers`. After each worker
# process is booted, this block will be run. If you are using the `preload_app!`
# option, you will want to use this block to reconnect to any threads
# or connections that may have been created at application boot, as Ruby
# cannot share connections between processes.
#
# on_worker_boot do
# ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
# end
#
# Allow puma to be restarted by `rails restart` command.
#plugin :tmp_restart
app_dir = File.expand_path("../..", __FILE__)
shared_dir = "#{app_dir}/shared"
# Set up socket location
bind "unix://#{shared_dir}/sockets/puma.sock"
# Logging
stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true
# Set master PID and state locations
pidfile "#{shared_dir}/pids/puma.pid"
state_path "#{shared_dir}/pids/puma.state"
activate_control_app
on_worker_boot do
require "active_record"
ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])
end
I want to start using systemd since its preferred for ubuntu 16.04
I Managed To start Puma but
hi i managed to make puma server run. but now i am getting nginx upstream connection timed out.
here is out put from systemctl status puma
/system.slice/puma.service
├─ 1258 puma: cluster worker 0: 15954 [mystore2.rentcallcenter.com]
└─15954 puma 3.10.0 (unix:///var/www/mystore2.rentcallcenter.com/shared/sockets/puma.sock)
here is my nginx server block file
upstream app {
# Path to Puma SOCK file, as defined previously
server unix:///var/www/mystore2.rentcallcenter.com/shared/sockets/puma.sock fail_timeout=0;
}
server {
listen 80;
listen [::]:80;
server_name mystore2.rentcallcenter.com;
root /var/www/mystore2.rentcallcenter.com/public;
try_files $uri/index.html $uri #app;
location #app {
proxy_pass http://app;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}`
i managed to connect to make my rails app run with puma and nginx
final config
nginx server block file
upstream app {
# Path to Puma SOCK file, as defined previously
server unix:///var/www/mystore2.rentcallcenter.com/shared/sockets/puma.sock fail_timeout=0;
}
server {
listen 80;
listen [::]:80;
server_name mystore2.rentcallcenter.com;
root /var/www/mystore2.rentcallcenter.com/public;
try_files $uri/index.html $uri #app;
location #app {
proxy_pass http://app;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
and puma.service
[Unit]
Description=Puma HTTP Server
After=network.target
# Uncomment for socket activation (see below)
# Requires=puma.socket
[Service]
# Foreground process (do not use --daemon in ExecStart or config.rb)
Type=simple
# Preferably configure a non-privileged user
User=www-data
# The path to the puma application root
# Also replace the "<WD>" place holders below with this path.
WorkingDirectory=/var/www/mystore2.rentcallcenter.com
# Helpful for debugging socket activation, etc.
# Environment=PUMA_DEBUG=1
# The command to start Puma. This variant uses a binstub generated via
# `bundle binstubs puma --path ./sbin` in the WorkingDirectory
# (replace "<WD>" below)
# ExecStart=/home/ashish/.rbenv/shims/puma -b tcp://0.0.0.0:9292 -b ssl://0.0.0.0:9293?key=key.pem&cert=cert.pem
# Variant: Use config file with `bind` directives instead:
ExecStart= /home/ashish/.rbenv/shims/puma -C /var/www/mystore2.rentcallcenter.com/config/puma.rb
# Variant: Use `bundle exec --keep-file-descriptors puma` instead of binstub
Restart=always
[Install]
WantedBy=multi-user.target
right now i have a droplet in DO and experimenting in rails deployment procedures. I have a rails 5 in ubuntu 16 and have done all necessary procedures to be able to deploy my app except that currently stuck in nginx puma and systemd. I've already seen DO's tutorials but the problem is that they use upstart as the script for init. As a complete beginner in nginx and linux systems, i have no idea how to start my app with nginx. the last procedures i made was
install nginx
test nginx, it is running
put some configs on config/puma.rb*
# Change to match your CPU core count
workers 2
# Min and Max threads per worker
threads 1, 6
app_dir = File.expand_path("../..", __FILE__)
shared_dir = "#{app_dir}/shared"
# Default to production
rails_env = ENV['RAILS_ENV'] || "production"
environment rails_env
# Set up socket location
bind "unix://#{shared_dir}/sockets/puma.sock"
# Logging
stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true
# Set master PID and state locations
pidfile "#{shared_dir}/pids/puma.pid"
state_path "#{shared_dir}/pids/puma.state"
activate_control_app
on_worker_boot do
require "active_record"
ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
ActiveRecord::Base.establish_connection(YAML.load_file("# {app_dir}/config/database.yml")[rails_env])
end
edited /etc/nginx/sites-available/default*
upstream app {
# Path to Puma SOCK file, as defined previously
server unix:/home/deploy/appname/shared/sockets/puma.sock fail_timeout=0;
}
server {
listen 80;
server_name localhost;
root /home/deploy/appname/public;
try_files $uri/index.html $uri #app;
location #app {
proxy_pass http://app;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
added /etc/systemd/system/puma.service
*base from https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-puma-and-nginx-on-ubuntu-14-04
this is the code of puma.service
[Unit]
Description=Puma HTTP Server
After=network.target
# Uncomment for socket activation (see below)
# Requires=puma.socket
[Service]
Type=simple
User=(myUser)
WorkingDirectory=/home/(myUser)/apps/(appName)
# ExecStart=<WD>/sbin/puma -b tcp://0.0.0.0:9292 -b ssl://0.0.0.0:9293?key=key.pem&cert=cert.pem
# ExecStart=/usr/local/bin/bundle exec --keep-file-descriptors puma -e production
ExecStart=/usr/local/bin/puma -C /home/(myUser)/apps/(appName)/config/puma.rb
Restart=always
[Install]
WantedBy=multi-user.target
im having exit 203, check some things and found out /usr/local/bin/puma doesnt exist in my linux.
Can someone help my setting up a proper systemd service? i really have no experience in this and im not sure what to put at ExecStart
Install puma if it is not already.
Use which puma to find out where puma is installed, then put that path on ExecStart= line.
I'm deploying my Rails app using nginx, puma, and capistrano. It's deployed by a user called deploy and the deploy location is under the home directory (/home/deploy)
I have Puma configured to create a socket under the shared folder that Capistrano symlinks all it's releases to. Correspondingly, nginx is configured to look at that socket as well (see config files below)
However when I start up the Rails / Puma webserver -
cd /home/deploy/my_app/current
SECRET_KEY_BASE=.... DATABASE_PASSWORD=... rails s -e production
I notice that no socket file is created. When I visit the site in my browser and then look at the Nginx error log, it is also complaining about that socket not existing.
2016/07/17 14:26:19 [crit] 26055#26055: *12 connect() to unix:/home/deploy/my_app/shared/tmp/sockets/puma.sock failed (2: No such file or directory) while connecting to upstream, client: XX.YY.XX.YY, server: localhost, request: "GET http://testp4.pospr.waw.pl/testproxy.php HTTP/1.1", upstream: "http://unix:/home/deploy/my_app/shared/tmp/sockets/puma.sock:/500.html", host: "testp4.pospr.waw.pl"
How do I go about getting puma to create that socket?
Thanks!
Puma Config
# config/puma.rb
...
# `shared_dir` is the symlinked `shared/` directory created
# by Capistrano - `/home/deploy/my_app/shared`
# Set up socket location
bind "unix://#{shared_dir}/tmp/sockets/puma.sock"
# Logging
stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true
# Set master PID and state locations
pidfile "#{shared_dir}/tmp/pids/puma.pid"
state_path "#{shared_dir}/tmp/pids/puma.state"
activate_control_app
...
Nginx sites config
# /etc/nginx/sites-available/default
upstream app {
# Path to Puma SOCK file
server unix:/home/deploy/my_app/shared/tmp/sockets/puma.sock fail_timeout=0;
}
server {
listen 80;
server_name localhost;
root /home/deploy/my_app/public;
try_files $uri/index.html $uri #app;
location #app {
proxy_pass http://app;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
Are you sure you are running Puma with that configuration? I don't think rails server is the proper way to start Puma in a production environment.
I would use this instead:
RACK_ENV=production bundle exec puma -C config/puma.rb
Once you get this working manually, then use the --daemon flag to keep the server running in the background.
Also, where is shared_dir defined in your config/puma.rb? Perhaps you omitted the part of the file, but if not, make sure you insert the correct value.
I had a similar issue, the reason was in the incorrect value of shared_dir. You need to update with following if you want to work it on deploy:
set :puma_bind,-> { "unix://#{shared_path}/tmp/sockets/puma.sock" }
set :puma_state, -> { "#{shared_path}/tmp/pids/puma.state" }
set :puma_pid, -> { "#{shared_path}/tmp/pids/puma.pid" }
Notice: after this changes you may have a problem with manual runcap production puma:start/stop/restart and you will need to remove -> {.
/etc/nginx/nginx.conf looks like:
user deploy;
worker_processes 5;
error_log logs/error.log;
events {
worker_connections 1024;
use epoll;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream foreman4000 {
server x.x.x.x:4000;
server x.x.x.x:4001;
server x.x.x.x:4002;
server x.x.x.x:4003;
server x.x.x.x:4004;
}
server {
listen 80;
server_name x.x.x.x; #server IP
access_log /opt/nginx/foreman4000.access.log;
location / {
proxy_pass http://foreman4000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
}
Here I use gem foreman, which uses upstart to manage all process and start all servers with one command
I created Procfile in the main directory of the project which contains:
redis: redis-server
thin: bundle exec thin start -p $PORT
faye: rackup faye.ru -E production -s thin
Added to Gemfile:
gem 'foreman'
gem 'thin'
gem "foreman-export-daemontools", "~> 0.0.1"
Ran bundle install locally to edit Gemfile.lock
Deployed project on the server.
Started Nginx
deploy#dcards101:/opt/nginx/conf$ sudo /etc/init.d/nginx stop [ OK ]
deploy#dcards101:/opt/nginx/conf$ sudo /etc/init.d/nginx srart [ OK ]
Exported data from Procfile to Upstart
deploy#dcards101:/var/www/cards/current$ rvmsudo foreman export upstart -a cards -u root
Started application
deploy#dcards101:/var/www/cards/current$ rvmsudo start cards
Now everything had to be good but what i see on the server is only
502 Bad Gateway
nginx/1.0.15
Logs say:
2012/07/17 17:22:30 [error] 11593#0: *148 no live upstreams while connecting to upstream, client: x.x.x.x, server: x.x.x.x, request: "GET / HTTP/1.1", upstream: "http://foreman4000/", host: "x.x.x.x"
Please help with anything you can. Server -- Ubuntu 10 LTS.
got the same error solved it this way:
first install nginx_tcp_proxy_module
( I followed this tutorial but changed it to use passenger and thin with nginx)
than add the tcp part to your nginx.conf:
tcp {
upstream websockets {
## node processes
server 12.34.56.78:9292;
check interval=300 rise=2 fall=5 timeout=1000;
}
server {
listen 9200;
server_name domain.org;
tcp_nodelay on;
proxy_pass websockets;
}
}
doesn´t work on port 80 for me
after that I still get empty responses from faye/privat_pub but there was an extremly trivial solution:
RAILS_ENV=production bundle exec rackup private_pub.ru -s thin -E production
look private_pub - Issue #29
Now everything works except chrome how fires 2 times
(and I need an deamon-process for the rackup)
hope it helps you too
I think your problem is that you put your app-server and the faye server in the same upstream!
If I get the method of upstream and foreman right, your first visitor get the app the second faye and so on. ( maybe I`m wrong because I don´t know foreman .. but if foreman shares all available servers to all services, that might be your problem )
I wood say try capistrano instead of foreman .. so you have full control which server starts where .. because at my my host http don`t work for private_pub (because of nginx) so I had to install the nginx_tcp_proxy_module to get the tcp block working in my nginx.conf
or just try server by server via ssh to find the error