We might want to revisit #634 to revert that decision as it is coming in the way. While I agree that "Software should be secure by default", but I am not sure how much I would buy the argument of protecting my development application from being accessed by someone in a "Coffee Shop".
In contrast, in a pair coding session, I would much prefer my colleagues in the same network (perhaps on the coffee table) to be able to access and test the app on their machines while I make changes.
Now, that more and more people are using containers (such as Docker) for their development environment (where the context of localhost is jailed inside the container, hence not accessible from the host machine), running the development server on localhost by default causes more trouble than it solves. This is against Ruby's mantras of "Optimize for programmer happiness" and "The Principle of Least Surprise". This is especially causing more issues when the documentation does not reflect the situation accurately. Due to the following line, one would assume that their application running inside a Docker container would easily be accessible from the host machine if appropriate ports are bound.
-o # set the host (default is 0.0.0.0)
I agree the documentation for command line option could be improved. The documentation for the :bind setting explains that the default is localhost for development and 0.0.0.0 for all other environments.
http://sinatrarb.com/configuration.html#bind---server-hostname-or-ip-address
Yes, I saw the :bind documentation later, but by that time I already got enough surprises and wasted quite some time in figuring out why it won't work for me. Since, :bind is a config option that would require code change, which may not be desired when someone is using a script that would otherwise work. For me, -o flag was a better option which I can supply when running inside a container, but the documentation was not accurate there. After explicitly specifying -o 0.0.0.0, I was able to get it working, so I thought the default might have been changed later and documentation was not updated accordingly.
Correcting the documentation here to reflect the current behavior is the easy part, which I can perhaps make a PR for. However, I really wanted to encourage a discussion around changing the default behavior. Sinatra used to be one of those things that anyone with basic Ruby knowledge can just create a simple Ruby file containing the code on its landing page and execute that script to get it working without diving any further in the documentation.
require 'sinatra'
get '/frank-says' do
'Put this in your pipe & smoke it!'
end
That element of "obviousness" is being hurt here. Especially, when use of Docker for development environment is rising day by day.
we have set :bind, '0.0.0.0' too
I was not talking about the number of ways it can be achieved, but suggesting that the default out of the box experience can be improved.
create-react-app binds to 0.0.0.0 by default, in development mode, and I think that's a mistake. I was curious what others thought and I find that the opinions expressed in #634 match mine. It should be documented somewhere easy to find how to bind to 0.0.0.0 in development mode but I very strongly think binding to localhost should be the default. Besides, some browser features are only available with https or localhost, and the number is increasing:
Note: As with almost all new APIs, CSS Paint API is only available over HTTPS (or localhost).
Besides, some browser features are only available with https or localhost, and the number is increasing:
As per my understanding this has nothing to do with 0.0.0.0 vs. 'localhost' or '127.0.0.1'. A service listening on 0.0.0.0 can happily be accessed from localhost. In fact 0.0.0.0 is not a resolvable interface, so it is not used when interacting with the service.
As far as the secure-by-default argument is concerned, I don't oppose that, but putting unnecessary hyper-security in every place comes in the way of smooth user experience. This is against the Ruby's philosophy of developers' happiness. How about adding two-factor authentication by default in development mode and leaving the production mode as it is so that when someone is developing in a coffee house, no one can access their super secret product until it is released? I would perhaps be concerned about securing many other things if I have to develop while using public WiFi of a coffee house. There are many more popular apps and frameworks which listen on 0.0.0.0 interface by default, create-react-app is not an exception.
I don't think the default for development should be changed back to 0.0.0.0. If you are dealing with Docker, I think it is reasonable to know about changing the binding for your application.
If you are developing on an open Wi-Fi in a coffee shop, I think it is a big chance that you don't know about the risks with it, so I agree with the opinion that Sinatra should pick the secure option for its default.
yeah, the "development" mode should be use "localhost"
If you are dealing with Docker, I think it is reasonable to know about changing the binding for your application.
Agreed on this part. In my case, I was well aware of it as I consider myself a Docker expert, but the documentation of Sinatra was inaccurate, so I wasted a lot of time when I filed this ticket.
If you are developing on an open Wi-Fi in a coffee shop, I think it is a big chance that you don't know about the risks with it, so I agree with the opinion that Sinatra should pick the secure option for its default.
I really want to understand the risks involved. Rather than just tossing opinions back and forth and mentioning big terms like security and risks (which can be very much real), let's asses potential risks and see if those are significant enough to bear the cost of inconvenience and unexpected surprises?
Just as a note: Rack, Padrino, and Rails all bind to localhost in development mode. It seems like this has become the norm in our community. We don't have to copy what they do, but I think it could be argued that bucking the trend in this particular instance could also cause unexpected surprises.
I was bitten by this in a new project because I forgot to set APP_ENV in the new Dockerfile. So IMHO it's not about the interface but about setting the right environment (APP_ENV/RACK_ENV). Maybe we can just add a warning like the way with lib/sinatra/indifferent_hash.rb?
For example:
WARNING: Your application currently runs in development mode which is not designed for remote access and/or use with Docker. Consider setting APP_ENV to "production".
We still want to use development mode though, so my personal feeling is that should not invoke a warning. I think this is something that might have to be resolved with more documentation. To use Docker in development the app simply needs to set the bind option.
yes, we need 127.0.0.1 for development
from #1576, as a note for everyone interested:
IMHO it's good to give a nice convention over configuration feeling when running sinatra in development on the local machine or within docker without sacrificing security best practices in regard to exposing development applications to the local network.
I intentionally didn't change the default hint for the OptionParser, as i consider this a convenience feature for development (one thing less to get wrong), where the best practice should be to declare it.
Most helpful comment
Just as a note: Rack, Padrino, and Rails all bind to localhost in development mode. It seems like this has become the norm in our community. We don't have to copy what they do, but I think it could be argued that bucking the trend in this particular instance could also cause unexpected surprises.