I have a rails server on a remote box (debian wheezy, ruby 2.2, rails 4.2) and the server does not respond when I try to connect to it in my local browser or curl. The request times out. However when I ssh into the box and wget localhost:3000 it gets me the root page perfectly. Any suggestions?
Rails 4.2 changed the default IP address that rails server binds to, instead of binding to 0.0.0.0 (ie. all interfaces) it binds only to localhost.
Edit
Sorry, I see now that you made no mention of production, just a remote box. So I removed that bit from above.
To get around this you can do two things, either always start with the -b option:
rails s -b 0.0.0.0
Or, there's a little trick to add that to the default, see https://stackoverflow.com/a/8998401/152786 (note that you only need to merge in the :Port and :Host options, and you can set the :Host to 0.0.0.0 if you want).
To bind the server without using command arguments you can append this to bin/rails after line require_relative '../config/boot' and the code is executed only for the rails server command:
if ARGV.first == 's' || ARGV.first == 'server'
require 'rails/commands/server'
module Rails
class Server
def default_options
super.merge(Host: '0.0.0.0', Port: 3000)
end
end
end
end
The bin/rails file loks like this:
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
# Set default host and port to rails server
if ARGV.first == 's' || ARGV.first == 'server'
require 'rails/commands/server'
module Rails
class Server
def default_options
super.merge(Host: '0.0.0.0', Port: 3000)
end
end
end
end
require 'rails/commands'
Related
I have a rails application in which I use foreman to start my rails and sidekiq servers. Since foreman doesn't interact well with regular byebug (you can't see the prompt as you type), I have set up remote debugging for both my rails and sidekiq servers. This works perfectly for the rails server, but when I connect to the byebug server for the sidekiq server, I get the following:
$ bundle exec byebug -R localhost:58501
Connecting to byebug server localhost:58501...
Connected.
(byebug:ctrl)
And I'm unable to catch any byebug breakpoints.
According to the documentation, the (byebug:ctrl) prompt means that the program has terminated normally (https://github.com/deivid-rodriguez/byebug/blob/master/GUIDE.md), but sidekiq is running jobs just fine.
Is there something incorrect in my configuration, or is sidekiq just not compatible with byebug's remote debugging?
Procfile:
sidekiq: bundle exec sidekiq
rails: rails server
config/initializers/byebug.rb:
if Rails.env.development?
require 'byebug'
def find_available_port
server = TCPServer.new(nil, 0)
server.addr[1]
ensure
server.close if server
end
port = find_available_port
puts "Starting remote debugger..."
Byebug.start_server 'localhost', port
puts "Remote debugger on port #{port}"
end
Note that when I don't use remote debugging, byebug functions fine with sidekiq (although in foreman I can't see the prompt as I type).
Also note that I've tried using Byebug.wait_connection = true before Byebug.start_server, but I have the same issue.
I've tried to replicate this locally, and with sidekiq 3.3.1 and byebug 9.0.5, it seems to work fine with a minor adjustment to the require:
require 'byebug/core'
def find_available_port
server = TCPServer.new(nil, 0)
server.addr[1]
ensure
server.close if server
end
port = find_available_port
puts "Starting remote debugger..."
Byebug.start_server 'localhost', port
puts "Remote debugger on port #{port}"
Job:
class TestJob
include Sidekiq::Worker
def perform
byebug
end
end
After upgrading our team's rails application to 4.2, as the release note mentioned, the default ip rails server binds to is changed to localhost from 0.0.0.0.
We develop with Vagrant, and want the development server to be accessible directly from browser on the host machine.
Instead of typing rails s -b 0.0.0.0 every time from now on, I wonder if there's any more elegant solution, so that we can still use sth as simple as rails s to start the server. Perhaps:
a config file rails s reads where I can modify the default binding ip (without using -c)
port forward with vagrant (tried but failed, see problem encountered below)
a monkey patch to rack, that changes the default binding ip
The real goal behind this is that I want the upgrade to be smooth among our team, avoiding the glitch that people will have to constantly restarting their rails server due to the missing -b 0.0.0.0 part.
I tried vagrant port forwarding, but still get Connection Refused when I visit localhost:3000 on the host machine. The two configuration lines I tried was:
config.vm.network "forwarded_port", guest: 3000, host: 3000
config.vm.network "forwarded_port", guest: 3000, guest_ip: '127.0.0.1', host: 3000
Didn't find any relevant instructions in the official docs. Any help will be appreciated.
I'm having the same issue here and I found today a better solution. Just append this code to your config/boot.rb and it should work with vagrant.
require 'rails/commands/server'
module Rails
class Server
def default_options
super.merge(Host: '0.0.0.0', Port: 3000)
end
end
end
ps: Its based on: this answer
You can use foreman to run a Procfile with your custom commands:
# Procfile in Rails application root
web: bundle exec rails s -b 0.0.0.0
Now start your Rails application with:
foreman start
The good thing about foreman is that you can add other applications to the Procfile (like sidekiq, mailcatcher).
The bad thing about foreman is that you have to train your team to run foreman start instead of rails s.
Met the same problem. Found the blog Make Rails 4.2 server listens to all interfaces.
Add the following to config/boot.rb
require 'rails/commands/server'
module Rails
class Server
alias :default_options_bk :default_options
def default_options
default_options_bk.merge!(Host: '0.0.0.0')
end
end
end
For Rails 5.1.7 with Puma 3.12.1 the selected answer does not work, but I accomplished it by adding the following to my config/puma.rb file:
set_default_host '0.0.0.0' # Note: Must come BEFORE defining the port
port ENV.fetch('PORT') { 3000 }
I determined this by inspecting the dsl file. It uses instance_eval on that file, so there are probably other ways to do it, but this seemed the most reasonable to me.
If you put the default options on config/boot.rb then all command attributes for rake and rails fails (example: rake -T or rails g model user)! So, append this to bin/rails after line require_relative '../config/boot' and the code is executed only for the rails server command:
if ARGV.first == 's' || ARGV.first == 'server'
require 'rails/commands/server'
module Rails
class Server
def default_options
super.merge(Host: '0.0.0.0', Port: 3000)
end
end
end
end
The bin/rails file loks like this:
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
# Set default host and port to rails server
if ARGV.first == 's' || ARGV.first == 'server'
require 'rails/commands/server'
module Rails
class Server
def default_options
super.merge(Host: '0.0.0.0', Port: 3000)
end
end
end
end
require 'rails/commands'
If you use docker or another tool to manage the environment variables, you can set the HOST environment variable to the IP you need to bind.
Example:
HOST=0.0.0.0
Add it to docker.env file if you use Docker or .env if you use foreman.
Here's a simpler solution that I'm using. I already like/need dotenv and puma-heroku, so if using those doesn't work for you then this might not be for you.
/config/puma.rb
plugin :heroku
Gemfile
gem 'dotenv-rails', groups: [:development, :test]
.env
PORT=8080
Now I can start both dev and production with rails s.
For Rails 5 with Puma the selected answer does not work. You may get such error: cannot load such file -- rails/commands/server
For proper solution add following to config/puma.rb:
bind 'tcp://0.0.0.0:3000'
Switch to Puma and specify port in config/puma.rb, e.g.:
port ENV.fetch("PORT") { 3000 }
Apparently it will bind to 0.0.0.0 for the specified port: https://github.com/puma/puma/issues/896
I know that I can start a rails server on another port via -p option. But I'd like to setup another port per application as long as I start webrick.
Any ideas?
Regards
Felix
Append this to config/boot.rb:
require 'rails/commands/server'
module DefaultOptions
def default_options
super.merge!(Port: 3001)
end
end
Rails::Server.send(:prepend, DefaultOptions)
Note: ruby >= 2.0 required.
Quick solution: Append to Rakefile
task :server do
`bundle exec rails s -p 8080`
end
Then run rake server
Option 1:
You can launch WEBrick like so:
rails server -p 8080
Where 8080 is your port. If you like, you can throw this in a bash script for convenience.
Option 2:
You could install $ gem install foreman, and use foreman to start your production webserver (e.g. unicorn) as defined in your Procfile like so: $ foreman run web. If unicorn is your web server you can specify the port in your unicorn config file (as with most server choices). The benefit of this approach is not only can you set the port in the config, but you're using an environment which is closer to production.
If you put the default options on config/boot.rb then all command attributes for rake and rails fails (example: rake -T or rails g model user)! So, append this to bin/rails after line require_relative '../config/boot' and the code is executed only for the rails server command:
if ARGV.first == 's' || ARGV.first == 'server'
require 'rails/commands/server'
module Rails
class Server
def default_options
super.merge(Host: '0.0.0.0', Port: 3000)
end
end
end
end
The bin/rails file loks like this:
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
# Set default host and port to rails server
if ARGV.first == 's' || ARGV.first == 'server'
require 'rails/commands/server'
module Rails
class Server
def default_options
super.merge(Host: '0.0.0.0', Port: 3000)
end
end
end
end
require 'rails/commands'
For Rails 5.1:
# config/boot.rb
# ... existing code
require 'rails/command'
require 'rails/commands/server/server_command'
Rails::Command::ServerCommand.send(:remove_const, 'DEFAULT_PORT')
Rails::Command::ServerCommand.const_set('DEFAULT_PORT', 3333)
A Rails 3.2.6 application running as a 'web' Heroku process is connecting to Redis using the ENV["REDISTOGO_URL"] environment variable:
irb(main):002:0> Redis.current
=> #<Redis client v2.2.2 connected to redis://xxx.redistogo.com:1234/0 (Redis v2.4.11)>
----- /initializers/redis.rb
if Rails.env.development?
Redis.current = Redis.new
elsif Rails.env.test?
Redis.current = Redis.new
elsif Rails.env.production?
uri = URI.parse(ENV["REDISTOGO_URL"])
Redis.current = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
end
A ruby daemon 'streaming' process runs as a secondary worker:
----- Procfile
web: bundle exec rails server thin -p $PORT -e $RACK_ENV
worker: bundle exec rake jobs:work
streaming: RAILS_ENV=production ruby bin/streaming.rb start
However, the streaming process is crashing when it calls methods in the main Rails application that connect with Redis - even though the streaming process supposed to be loading the same redis.rb initializer as the 'web' Rails application process.
----- /bin/streaming_ctl.rb
# encoding: UTF-8
require "rubygems"
require "bundler/setup"
require "daemons"
Daemons.run(File.expand_path("../streaming.rb", __FILE__))
----- /bin/streaming.rb
# encoding: UTF-8
# TODO: set rails env in init script
ENV["RAILS_ENV"] ||= "production"
# load rails environment
require File.expand_path('../../config/environment', __FILE__)
logger = ActiveSupport::BufferedLogger.new(File.expand_path("./../../log/streaming.log", __FILE__))
Streaming.start
logger.info("\nStarting streaming in #{Rails.env.to_s} mode.")
Why is the streaming process/worker using the default Redis host and port?
[streaming.1]: /app/vendor/bundle/ruby/1.9.1/gems/redis-2.2.2/lib/redis/client.rb:236:in `rescue in establish_connection': Connection refused - Unable to connect to Redis on 127.0.0.1:6379 (Errno::ECONNREFUSED)
Switching from "Redis.current" in /initializer/redis.rb and using a "$redis" variable convention instead (as illustrated here http://jimneath.org/2011/03/24/using-redis-with-ruby-on-rails.html) fixed the connection problem.
The app was using redis gem version 2.2.2 at the time. It appears as though the Redis.current in this gem version won't be consistent across 'web' and 'worker' processes because Heroku runs these processes on separate threads. The documentation on the gem repo suggests that updating to gem to >= version 3 will enable Redis.current to run in multi-threaded environments:
https://github.com/redis/redis-rb/blob/master/CHANGELOG.md#300
I am trying to run sunspot on the development port (8982).
I run the following command
$ RAILS_ENV=development rake sunspot:solr:start
Sunspot starts but it does not start on the development port, it starts on port 8983, which is the production port.
I am not using config/sunspot.yml. I have a config/initializers/sunspot.rb file which reads as follows
require File.join(Rails.root, 'lib', 'sunspot', 'rails', 'adapters')
Sunspot::Adapters::InstanceAdapter.register(Sunspot::Rails::Adapters::ActiveRecordInstanceAdapter, ActiveRecord::Base)
Sunspot::Adapters::DataAccessor.register(Sunspot::Rails::Adapters::ActiveRecordDataAccessor, ActiveRecord::Base)
module Sunspot
HIGHLIGHTS = {
:elements => ['span'], :attributes => { 'span' => ['class'] }
}
Additionally in config/environments/development.rb I have a line that reads
Sunspot.config.solr.url = 'http://localhost:8982/solr'
I am not sure what I am doing wrong. I need to start sunspot on Port 8982 ( the development node).
Any help would be appreciated
See https://github.com/sunspot/sunspot/issues/262 to track the resolution of the bug.