I'm trying to find a way to bind my production Rails server to port 80 without having to run the entire server with root privileges. My question is basically the same as "Is there a way for non-root processes to bind to "privileged" ports (<1024) on Linux?", except that I need to do this with Rails. Currently, the top two answers on the question I referenced either require me to grant the CAP_NET_BIND_SERVICE
permission to the Ruby interpreter (probably not a good idea) or drop root privileges after starting the server (which I'm not sure is possible with Ruby). Any ideas?
Binding a Rails server to port 80 on Linux without running it as root
Asked Answered
Do you have the option of running a traditional web server on port 80 and forwarding the requests to a Rails server running on another port? For example, running nginx and directing requests to thin or unicorn running on a non-privileged port. –
Illiteracy
The odds you actually want to do this are extremely low. Thin, Mongrel, Puma, Unicorn, or whatever else should be behind a non-Ruby server in normal usage patterns. See this question. –
Noellenoellyn
Yeah, this is the first time I've actually tried to deploy a production application myself without the help of someone else to set up the server for me, or a PaaS like Heroku; so there's a good chance that I don't know I want. If you'd care to post a detailed answer suggesting an alternative to binding thin on port 80 (like nginx, as Jim said in his comment) I'd accept that as a valid answer. –
Garnierite
So basically, the answer is you don't. It's possible that there's some really hacky way to make this work, but the odds that you actually want to do this are exceedingly low. Instead, run Rails on a non-privileged port, and set up a real web server like nginx to forward to Rails.
As a super-simple example, with nginx you might use a config file that looks something like this:
upstream rails_server {
server localhost:3000;
}
server {
listen 80;
location / {
root /home/deploy_user/rails_app/public;
try_files $uri @missing;
}
location @missing {
proxy_pass http://rails_server;
proxy_set_header Host $http_host;
proxy_redirect off;
}
}
This solution is also better long-term, because it makes your infrastructure more flexible. For example, if you need to scale up your application to multiple machines you could use nginx as a load-balancer and have it forward requests to a whole bunch of Rails servers running on different machines.
This worked perfectly. Bonus points for including the
try_files
directive that serves any public assets directly through nginx instead of delegating that to the rails server –
Rubbico © 2022 - 2024 — McMap. All rights reserved.