Introducing Pow, a zero-configuration Rack server for Mac OS X
pow.cx
pow.cx
The screencast shows how it works and why we made it: http://get.pow.cx/media/screencast.mov
If you're interested, you can read the annotated source code, written in literate style and generated with the wonderful Docco: http://pow.cx/docs/
curl get.pow.cx | sh
for installation. Yes, it's easy and slick. Yes, you'd have to read the code itself to make sure Pow didn't own your machine up after a secure install. Yes, you can just read the shell script. But 0.0001% of people playing with Pow will do that. Why make things easier for attackers at all?This is an idea that I think started with Ximian back in 2000 and I think we're ready for it to die. It'd be neat if the authors of Pow were cool enough to strike it from their (otherwise amazing) front page.
(I'd also be happier if the thread where the guy explains how Pow works and what it's components are were voted higher than this comment.)
EDIT: Okay, I see it's because of the use of sudo. But graphical installers often require the root/administrator password, and could be equally destructive.
curl https://get.pow.cx/ | sh
Fix your complaint? Like the grandparent said, I'm not sure why curl | sh is any less secure than gem install or whathaveyou, in the oh-god-this-script-just-ran-rm-rf-/ sense.How does this practice confound security more than a normal installer? sudo asks for my password just as a normal installer would.
Oddly, I'm more used to seeing arguments that distributing source code is better than distributing binaries because you can inspect source code.
We're arguing levels of badness here so it's a little hokey. But if you decide to open up your machine to run arbitrary code, a machine that can run shell will arguably get more infections than one that runs executables. To infect the ladder any script kiddies will need to know a 'harder' language and at least how to compile it. It's a couple more hoops to jump through. In the other case I could drive by and do scp ~/mailbox me@myserver:
We're already talking about running arbitrary code on a machine, compiled versus interpreted is irrelevant. And I think you have forgotten that a script with the appropriate hash-bang and file permissions is indistinguishable to most users from a compiled executable.
You can for example, at your network level point get.pow.cx to a malicious script and you're done. That's the security issue, it has nothing to do with the HTTP protocol.
With that being said, I don't care, the risk is the same as downloading any software via http, in fact I loved it, so easy :-).
Those that don't care won't look at the script any more than they'll check the md5 hash of a binary to see that it's a legit binary. For those that care, they can look at the bash source.
Since you are the security expert at Hn, we are trying to understand/learn from you.
This is not plain Nerdgasm making people understand about software security is making the world a little better.
curl https://github.com/37signals/pow/raw/master/install.sh | sh
The installation process is short and fully documented: http://get.pow.cx/
The web site and manual encourage you to read it.
I think it's far more transparent than, say, an OS X Installer package.
I think you would be doing the universe a small but meaningful favor not to advertise this installation mechanism.
But it is a very cool tool and a really well-done site. Congrats!
I'm not seeing how Pow's installation process is any less secure than, say, downloading a disk image from a random site.
With things like this that come from reputable sources, it's not unreasonable to put some trust in the source and some trust in the smaller percentage of developers who actually read the source code.
Although I suppose it is possible that 37signals' GitHub account was hacked and someone maliciously designed a convenient Rack server and website with the intent of targeting the lucrative Rails developer demographic, or that the package the installer downloads is an insidious 37signals trojan not built from the code at the public repo.
Point taken.
Even so, assuming you want to be extra careful (you're installing it on a development machine with highly sensitive information), it's not that difficult to clone the repo and edit the install script to install from your local copy of the repo.
It seems stupid, but on the other hand I never see people abusing the sticky bit, possibly as a result of the higher barrier to entry.
On the other hand, it causes me inconvenience every time I want to do something legitimate with it.
It is not really a script vs. binary issue so much as protecting against how scripts are loaded.
curl_review() {
result=`curl "$@"`
echo "$result" > `tty`
echo "Enter to proceed, Ctrl-C to abort:" > `tty`
read
echo "$result"
}
Then just change curl to curl_review: curl_review get.pow.cx | sh
Of course this kind of defeats the purpose of these easy installation tricks.cUrl is a shitty way to install software.
* No transport security. As many people mention, at least adding HTTPS would help with this. However, most non-browser SSL clients (wget, curl) don't include any root certs by default so even switching to SSL would not help this method. Firesheep, sslstrip, etc. automatically generate a self-signed cert which would look no different to wget than a real cert.
* No persistence. If you download any installer package once and then reuse it on multiple machines, you get the benefit of knowing that the same code was installed on each machine (good or bad). With this method, users may catch the site in the middle of an update and get multiple versions of the package.
* No authentication. Even with SSL, you only get strong transport security. You would know strongly that ".pow.cx" sent you some code, but not how that code got put on the server. With package-signing, typically done on the developer's end system, you know that it was protected even before it was uploaded to some site.
* Easier to trojan than binaries. Inserting a few extra shell commands in a single HTTP(S) session (say, targeting a single client IP) is much easier than building a custom binary package. Consider how hard it is to even compile Firefox with all the dependencies. Now do that work and insert a trojan and upload a separate 10 MB binary that needs to be stored somewhere on the server while waiting for that one client to visit the site. Compare this to keeping a two-line patch to a shell script (easily done in RAM, maybe even by hotpatch).
* Trains users that all the above is ok since the popularity of this "| sh" install method is relatively new. (Yes, I know about shar scripts in the past but those ended by 1996 or so with the advent of real package managers). It is absolutely impossible to retrofit "| sh" to be secure, whereas it is definitely feasible to add package signature verification support to gem or yum or apt or whatever (in fact, all those already support it).
The fact that many installers aren't signed today is not an ok to drive this process back to the 80's. We should be moving toward the future when package signing is a required part of being a software developer. Too hard? Well build tools to make this easier!
This is a blessing if you usually need multiple local apps running.
It also means you can now elegantly use local ruby webapps as personal desktop applications. Say you'd like to build a simple journal or expenses app to use on your desktop for personal use. You can now quickly build it with - say - Sinatra, Datamapper and SQLite. And no need to launch or quit it. Beautiful.
By the way, I didn't completely understand why I would use it instead of Thin until I had it running and had read http://pow.cx/manual.html. Maybe the mechanism I described in the first paragraph of the grandparent should be more prominently and clearly communicated? Maybe that's part of what you meant with the first two paragraphs under "Pow prevails over the forces of evil.", but in that case I think they could be more specific. But maybe that's just me.
Seriously, dude, get over yourself. It's pretty ridiculous how much FUD this project announcement received in here, versus positive focus. There are multiple other long FUD threads that missed the point of Pow; you only started (and kept throwing fire at) the one that doesn't even touch what the project is about.
Thanks but no thanks. Do yourself a favor and learn how to install rack and nginx. It's already dirt simple, and you'll save yourself having to go back and learn it when it's time to deploy your app somewhere other than your laptop.
The downside of zero configuration is "What do you do when it doesn't just work?" (I'm digging around the manual now...)
(A quick follow-up: The second app I symlinked in the exact same way does "Just work", so I don't doubt that there's something odd about my config for the first. Still, no fun to debug.)
$ bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head )
Check out Nack (https://github.com/josh/nack) to see how Pow runs Rack apps.
passenger start
no preference panes to install. No Apache configuration files to update. And Passenger eliminates the need to edit /etc/hosts. To get a Rack app running, just type a single command.
And upgrading Passenger requires you to install a gem, then run a command, copy and paste a bunch of text into your Apache config file, and restart Apache.
When this finished, I got an error and it all failed: "* ERROR: Please install file-tail first: sudo gem install file-tail"…
So I did and now its supposedly running on Port 3000 except I just get a 403 error when I visit it in my browser. The docs aren't very helpful either (http://www.modrails.com/documentation/Users%20guide%20Standa...).
Update: I apparently missed the line about going to my application's root directory. I still didn't really like all the stuff that got downloaded and compiled on my machine, when all I would like to do is get started developing.
The 'file-tail' thing is actually a bug (we should no longer have a requirement on file-tail). We've already fixed it in git master 3 days ago and the fix will be released very soon.
Can you give me some more details about the 403 error? Do you see anything in the console or in the browser window that tells you more about the error?
It still seems like a lot of software and time to just start developing. What does passenger get me for developing locally that Pow doesn't? (I've never used Passenger before today).
1. Phusion Passenger is currently the most popular production server for Ruby web apps (see ruby-toolbox.com and the last NewRelic survey). Phusion Passenger Standalone is practically the same as Phusion Passenger for Nginx. It's a good thing to have the development environment match the production environment as much as possible. Phusion Passenger actually comes in 3 editions: Phusion Passenger for Apache (integrates into Apache), Phusion Passenger for Nginx (integrates into Nginx) and Phusion Passenger Standalone (can run by itself, does not require an external web server).
2. Because Standalone is based on an Nginx core it's even fit for production. According to the Pow website it uses Nack, which according to its website is not ready for production. If 'passenger start' works for you locally then you can run the same thing in production. No need to learn how Apache and Nginx works.
There are other things as well, but I have to go in a few minutes. Feel free to ask me more questions if you like.
Hypothetically speaking, it's possible to modify Phusion Passenger to not download and install Nginx. We can run on a pure-Ruby web server like WEBrick. However I guarantee you, WEBrick sucks; it's slow, buggy and leaks memory.
* this is also a single command to get a rack app running once you have it installed
* you can easily support multiple ruby versions/gemsets (otherwise you'd need to install/compile passenger for each)
* appname.dev is easier than remembering which port all of your rails apps are running on.
* you don't have to start each app manually each time.
* Passenger supports using various gemsets very easily using the setup_load_paths.rb file in the config of your app (though multiple ruby versions still seem to be a problem).
* If you're using passenger, why do you have each app running on a different port? Using the Passenger Prefs Pane makes it trivially easy to have each app at its own appname.local URL (though, admittedly, installing an extra prefs pane, where Pow has it built in, gives bonus points to the latter).
* Same with my last point. Passenger automatically handles the booting up or apps when you access their URL in the browser, just like Pow does. Of course, I'm guessing you don't have Passenger installed this way if each app has to run on a different port.
$ curl get.pow.cx | sh
$ cd ~/.pow
$ ln -s /path/to/myapp
We could have: $ gem install pow
$ pow /path/to/myappIf you `git clone git://github.com/37signals/pow.git`, you can install it from source with `npm install -g` (requires npm 1.0)
As a minor aside, is there a way to get Chrome to treat .dev domain the same as .com? Whenever I type in my .dev app name, it tries to google search for it.
EDIT: scratch that. You can't do this.
In the meantime, you can access a new app the first time by entering http://myapp.dev (including the http://). Looks like after that, Chrome treats myapp.dev as desired.
Substituting launchd is easily done with any process launcher of your choice. As for the .dev TLD trick - that's a little harder, as OS X 10.6 has support for flat files inside /etc/resolver/* which the name of the file indicates what configuration/settings to use when resolving that domain. As such, they just drop a file named 'dev' in there and tell it to look to localhost on a custom port for DNS resolution. Then they run a mini DNS server on that port to resolve .dev domains to localhost.
Probably the only way to do something similar to this for linux would be to run a name server of your own on your box and add a custom zone configuration for the .dev TLD and recursive lookup for anything else.
This is very nice documentation. Is it generated using a freely available tool?
*** Installing local configuration files...
/Users/bonaldi/Library/Application Support/Pow/Versions/0.2.2/lib/command.js:50
throw err;
^
Error: EACCES, Permission denied '/Users/bonaldi/Library/LaunchAgents/cx.pow.powd.plist' launchctl load "$HOME/Library/LaunchAgents/cx.pow.powd.plist"
Bug: launchctl.c:2325 (23930):13: (dbfd = open(g_job_overrides_db_path, O_RDONLY | O_EXLOCK | O_CREAT, S_IRUSR | S_IWUSR)) != -1
launch_msg(): Socket is not connectededit: I only get the error using tmux, strange..
The file was chmodded to 664; changing it to 644 did the trick.
function pow {
if [ -d "`cd $1; pwd`" ]; then
ln -s "`cd $1; pwd`" ~/.pow/
fi
}At least in this instance you can read over the commands that will be run beforehand—in fact, Sam actively encourages you to do so.
I'll tell you one difference. It takes me 10 minutes to review the shell based installer. It takes a whole lot longer to inspect an installation package or application source code.
It's a one-page script and a reasonably small, public git repo, from a company that doesn't exactly have a reputation for hacky, unreliable software.