How to change the default binding ip of Rails 4.2 development server?
Asked Answered
S

9

90

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.

Sassan answered 23/2, 2015 at 7:2 Comment(3)
rails 5 answer: https://mcmap.net/q/196823/-lt-module-rails-gt-39-superclass-mismatch-for-class-server-typeerrorConley
current rails 5 answer is to use PumaInfuse
Yet another Rails 5 answer: set the env var HOST=0.0.0.0, and the Rails dev server will automatically use this value.Bosson
S
72

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

Sweatt answered 10/4, 2015 at 13:36 Comment(2)
With this approach, you lose the other defaults. See Vanitas's answer below for an alternative.Gothicism
I agree, take a look at Vanita's answerMizell
O
48

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.

Omega answered 23/2, 2015 at 8:40 Comment(2)
thanks. i'll accept ur answer in a few days if it turns out to be the best solution :)Sassan
Abbreviated foreman s will also work - may be an easier transition from rails s.Ezara
H
18

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
Halfassed answered 21/10, 2015 at 1:51 Comment(1)
this answer has the added benefit of not losing the original defaults (namely, port 3000!)Gothicism
S
12

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.

Syllogism answered 30/4, 2019 at 19:12 Comment(0)
E
7

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'
Eximious answered 9/9, 2015 at 10:16 Comment(0)
H
2

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.

Hildahildagard answered 21/8, 2019 at 9:57 Comment(0)
Y
1

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.

Yenyenisei answered 7/3, 2017 at 18:9 Comment(0)
G
1

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'
Gunman answered 2/5, 2020 at 13:49 Comment(0)
I
0

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

Infuse answered 6/6, 2018 at 13:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.