Fixing nginx client body temp permission denied errorsEdit
This is a problem that I stumbled across because of the particular way in which I use nginx to host multiple Rails applications.
If you use a single master process that handles multiple virtual hosts then you most likely won’t see this problem. I did, however, because I actually use two master processes and each runs as a different user.
The problem
Most requests for your Rails application seem to work but all of a sudden you get an internal server error for a particular request. Upon looking in the error_log
you see something like this:
2008/03/22 09:44:33 [crit] 18223#0: *642 open() "/usr/local/nginx/client_body_temp/0000000002" failed (13: Permission denied)
Diagnosis
Upon inspection, you see that /usr/local/nginx/client_body_temp/
is owned by the user that corresponds to one of your Rails applications (the first one that tried to create it). You’ll see the problem only when the second application actually tries to use the client_body_temp
folder.
The problem may take a while to materialize because the client_body_temp
folder is only used if the body is sufficiently large enough to require it. In my case I saw the error the first time I tried to submit an edit for a wiki article that was beyond a certain size.
The fix
The fix is clear: each nginx master process must have it’s own client_body_temp
folder. The directive required is client_body_temp_path
and it’s documented here.
So we alter the two config files and then restart the servers (in my case, with monit).
At the same time I noticed two other directories under /usr/local/nginx
owned by one of the users:
fastcgi_temp
(the corresponding directive isfastcgi_temp_path
, documented here)proxy_temp
(the directive isproxy_temp_path
, documented here)
Just in case these also cause problems in the future per-worker-process (per-user) paths should be specified for those as well.
Rationale
It’s worth commenting on my rationale for having two master processes rather than using virtual hosts. In short:
- nginx processes are extremely lightweight so it is feasible to run separate processes for each user as an analogue to Apache’s suexec functionality; in my case I have two applications and therefore two users, so this is quite reasonable
- Having each process run as a different user brings all of the isolation and security benefits that suexec brings to Apache
- In my case the two applications are actually just two instances of the same application, but one is for staging and one is for production; as a result, I only sometimes want to run both applications (ie. when testing a new version of the application in the staging environment) but most of the time only the production environment will be running, so it isn’t at all wasteful to occasionally fire up another worker process