unbit / uwsgi

uWSGI application server container
http://projects.unbit.it/uwsgi
Other
3.43k stars 679 forks source link

uwsgi + ruby on rails + namespace unshare #874

Open thuantran opened 9 years ago

thuantran commented 9 years ago

Hi,

I tried to run uwsgi as a rack application server for my redmine. It works fine without namespace unshare but if I use namespace unshare with following configuration:

[uwsgi]
master = true
master-as-root = true
unshare = fs

if-not-exists = <jail_root>/%n
hook-pre-jail = exec:mkdir <jail_root>/%n
endif =

hook-post-jail = mount:none none / recursive,private
hook-post-jail = mount:tmpfs none <jail_root>/%n

for = .old_root etc usr proc dev run tmp var <redmine_dir>
hook-post-jail = exec:mkdir -p <jail_root>/%n/%(_)
endfor =

hook-post-jail = exec:ln -s /usr/bin <jail_root>/%n/bin
hook-post-jail = exec:ln -s /usr/lib <jail_root>/%n/lib
hook-post-jail = exec:ln -s /usr/lib <jail_root>/%n/lib64
hook-post-jail = exec:ln -s /tmp <jail_root>/%n/var/tmp
hook-post-jail = exec:cp -a /etc/resolv.conf <jail_root>/%n/etc/resolv.conf
hook-post-jail = exec:grep http /etc/passwd > <jail_root>/%n/etc/passwd
hook-post-jail = exec:grep http /etc/group > <jail_root>/%n/etc/group
hook-post-jail = exec:grep http /etc/shadow > <jail_root>/%n/etc/shadow
hook-post-jail = exec:grep http /etc/gshadow > <jail_root>/%n/etc/gshadow

pivot-root = <jail_root>/%n <jail_root>/%n/.old_root

hook-as-root = mount:none /.old_root/<redmine_dir> /<redmine_dir> bind
hook-as-root = mount:none /.old_root/usr /usr bind
hook-as-root = mount:none none /usr bind,remount,readonly
hook-as-root = mount:none /.old_root/dev /dev bind
hook-as-root = mount:none /.old_root/run /run bind
hook-as-root = mount:none /.old_root/tmp /tmp bind
hook-as-root = mount:proc none /proc nodev hidepid=2
hook-as-root = umount:/.old_root recursive

uid = http
gid = http
cheaper = 4
processes = 12
socket=/run/uwsgi/%n.sock
chmod-socket = 600
disable-logging = true

plugin = rack
ruby-gc-freq = 100
rack = config.ru
lazy-apps = true
chdir = /<redmine_dir>
env = RAILS_ENV=production
env = RAILS_RELATIVE_URL_ROOT=/rm
env = BUNDLE_GEMFILE=%(chdir)/Gemfile

It doesn't work because the line chdir = / near the end is run before jailing and causing the rack app to fail as it's run after jailing and that path is invalid then. Do you know anyway to work around this?

P.S. I used the same configuration for php and it works brilliantly, jailing php with uwsgi is much easier.

BR, Thuan

unbit commented 9 years ago

chdir can be specified as an hook action too:

hook-post-jail = chdir:xxxx

thuantran commented 9 years ago

Didn't notice that. Wish you guys had a better documentation. Anyway here's the working config:

[uwsgi]
master = true
master-as-root = true
unshare = fs

if-not-exists = <jail_root>/%n
hook-pre-jail = exec:mkdir <jail_root>/%n
endif =

hook-post-jail = mount:none none / recursive,private
hook-post-jail = mount:tmpfs none <jail_root>/%n

for = .old_root etc usr proc dev run tmp var <redmine_dir>
hook-post-jail = exec:mkdir -p <jail_root>/%n/%(_)
endfor =

hook-post-jail = exec:ln -s /usr/bin <jail_root>/%n/bin
hook-post-jail = exec:ln -s /usr/lib <jail_root>/%n/lib
hook-post-jail = exec:ln -s /usr/lib <jail_root>/%n/lib64
hook-post-jail = exec:ln -s /tmp <jail_root>/%n/var/tmp
hook-post-jail = exec:cp -a /etc/resolv.conf <jail_root>/%n/etc/resolv.conf
hook-post-jail = exec:grep http /etc/passwd > <jail_root>/%n/etc/passwd
hook-post-jail = exec:grep http /etc/group > <jail_root>/%n/etc/group
hook-post-jail = exec:grep http /etc/shadow > <jail_root>/%n/etc/shadow
hook-post-jail = exec:grep http /etc/gshadow > <jail_root>/%n/etc/gshadow

pivot-root = <jail_root>/%n <jail_root>/%n/.old_root

hook-as-root = mount:none /.old_root/<redmine_dir> /<redmine_dir> bind
hook-as-root = mount:none /.old_root/usr /usr bind
hook-as-root = mount:none none /usr bind,remount,readonly
hook-as-root = mount:none /.old_root/dev /dev bind
hook-as-root = mount:none /.old_root/run /run bind
hook-as-root = mount:none /.old_root/tmp /tmp bind
hook-as-root = mount:proc none /proc nodev hidepid=2
hook-as-root = umount:/.old_root recursive
hook-as-root = chdir:/<redmine_dir>

uid = http
gid = http
cheaper = 4
processes = 12
socket=/run/uwsgi/%n.sock
chown-socket = %(uid):%(gid)
chmod-socket = 600
disable-logging = true

plugin = rack
ruby-gc-freq = 100
rack = config.ru
lazy-apps = true
env = RAILS_ENV=production
env = RAILS_RELATIVE_URL_ROOT=/rm
env = BUNDLE_GEMFILE=/<redmine_dir>/Gemfile

I also have a working jailed config for php if you're interested I can post it for other users, too.

unbit commented 9 years ago

Any specific reason for master-as-root ?

thuantran commented 9 years ago

Because I was trying to make this work with emperor mode but couldn't. I believe the line could be removed and as I've just tried it. It does work that way. Anyway in the end I prefer to manage them uwsgi instances using systemd instead of emperor mode, clearer that way for me because this is just a production server, I don't need the dynamic features of emperor mode much.

unbit commented 9 years ago

Emperor mode wins only if you need to deploy dozens of different instances. There is no need to introduce it for simple scenario (expecially now that systemd is basically everywhere).

Btw, if you want to make a tutorial i will publish it on the official docs site (just make a pull request for uwsgi-docs repository). Thanks a lot