nginx 权限被拒绝错误

nginx 权限被拒绝错误

我正在运行 nginx 和 unicorn 来为 Rails 应用程序提供服务。Unicorn
和 Rails 应用程序运行良好,但 nginx 无法打开 rails 公共目录,出现权限错误并返回 502 Bad Gateway。

curl http://localhost/
<html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.6.1</center>
</body>
</html>

var/log/nginx/error.log

014/09/18 18:16:16 [crit] 16619#0: *1 stat() "/home/rails/public_html/rails_app/current/public//index.html" failed (13: Permission denied), client: 127.0.0.1, server: , request: "GET / HTTP/1.1", host: "localhost"
2014/09/18 18:16:16 [crit] 16619#0: *1 stat() "/home/rails/public_html/rails_app/current/public/" failed (13: Permission denied), client: 127.0.0.1, server: , request: "GET / HTTP/1.1", host: "localhost"
2014/09/18 18:16:16 [crit] 16619#0: *1 connect() to unix:/tmp/unicorn.rails_app.sock failed (2: No such file or directory) while connecting to upstream, client: 127.0.0.1, server: , request: "GET / HTTP/1.1", upstream: "http://unix:/tmp/unicorn.rails_app.sock:/", host: "localhost"
2014/09/18 18:16:16 [crit] 16619#0: *1 stat() "/home/rails/public_html/rails_app/current/public/500.html/index.html" failed (13: Permission denied), client: 127.0.0.1, server: , request: "GET / HTTP/1.1", upstream: "http://unix:/tmp/unicorn.rails_app.sock/", host: "localhost"
2014/09/18 18:16:16 [crit] 16619#0: *1 stat() "/home/rails/public_html/rails_app/current/public/500.html" failed (13: Permission denied), client: 127.0.0.1, server: , request: "GET / HTTP/1.1", upstream: "http://unix:/tmp/unicorn.rails_app.sock/", host: "localhost"
2014/09/18 18:16:16 [crit] 16619#0: *1 connect() to unix:/tmp/unicorn.rails_app.sock failed (2: No such file or directory) while connecting to upstream, client: 127.0.0.1, server: , request: "GET / HTTP/1.1", upstream: "http://unix:/tmp/unicorn.rails_app.sock:/500.html", host: "localhost"

nginx.conf

user    nginx;
worker_processes        1;

error_log       /var/log/nginx/error.log warn;
pid                     /var/run/nginx.pid;

events {
        worker_connections 1024; # increase if you have lots of clients
        # accept_mutex off; # "on" if nginx worker_processes > 1
}

http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;

        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
        '$status $body_bytes_sent "$http_referer" '
        '"$http_user_agent" "$http_x_forwarded_for"';

        access_log  /var/log/nginx/access.log  main;

        sendfile                on;
        # tcp_nopush    on;
        # tcp_nodelay   off;

        upstream unicorn {
                server unix:/tmp/unicorn.rails_app.sock fail_timeout=0;
        }

        server {
                listen 80 default deferred;
                # server_name example.com;
                root /home/rails/public_html/rails_app/current/public;

                try_files $uri/index.html $uri @unicorn;
                location @unicorn {
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                        proxy_set_header Host $http_host;
                        proxy_redirect off;
                        proxy_pass http://unicorn;
                }

                error_page 500 502 503 504 /500.html;
                client_max_body_size 4G;
                keepalive_timeout 10;
        }
}

rails 公共目录的权限为 775 或 775。nginx
由“nginx”用户执行,rails 公共目录归“rails”用户所有。
我尝试过用“rails”用户和 root 用户执行 nginx,但出现了相同的错误。
我不知道这些错误是怎么回事。
如果我将根目录设置为 /usr/share/nginx/html/,nginx 可以正常工作。我的环境是 Vagrant 上的 Centos7 和带有 unicorn gem 4.8.3 的 rails 2.2.2。

[注意]我知道/tmp/unicorn.rails_app.sock需要放在另一个目录中这个问题,但我猜这不是问题。

答案1

nginxnginx以配置中规定的用户身份运行。您说您的目录归所有root:root

确保这件事每一个目录从根目录到 nginx 尝试访问的文件具有权限执行(有可能阅读?) 权限。就你的情况而言,其他权限组(chmod o+(r)x <recursive list of dirs>)。

如果这还不够,请尝试添加阅读允许其他的在套接字文件上。

正常情况下,现在 nginx 将能够访问stat()这些文件。

事实上,在 nginxroot设置下一切运行正常/usr/share/nginx/html,是因为这些文件是由 nginx 包创建的,并且具有适当的用户/组/权限组合......

现在,我看到另一个(更大的)问题:你尝试使用以 身份运行的 nginx 工作程序nginx:nginx和 所拥有的文件root:root,而没有nginx 的任何权限。因此,nginx 在套接字上进行的任何写入尝试最终都将失败……

你真的应该重新考虑一下你的整个结构。让 nginx 用户/组和目录/文件以某种方式匹配,这样 nginx 就可以打开它需要打开的内容(执行直接在目录上),读取需要读取的内容并写入需要写入的内容,而不依赖于其他权限组基本上允许任何用户做同样的事情。

答案2

我设法解决了这个问题。
问题是 nginx 无法读取 /tmp/unicorn.rails_app.sock,因为 PrivateTmp=true/etc/systemd//system/multi-user.target.wants/nginx.service

这些就是我做的。
为独角兽套接字创建目录

mkdir /var/run/unicorn
chown rails:rails /var/run/unicorn
chmod 755 /var/run/unicorn

修改nginx.conf

upstream unicorn {
    server unix:/var/run/unicorn/unicorn.rails_app.sock fail_timeout=0;
}

禁用 SElinux

sudo setenforce 0

永久禁用
在/etc/sysconfig/selinux中

SELINUX=permissive
SELINUXTYPE=targeted

现在运行良好。

答案3

编辑了我的 nginx.conf 并将用户从 nginx 更改为 deployer(我的 capistrano 部署用户和 wheel 组成员),现在一切正常!

答案4

要检查 SELinux 中是否存在这种情况,您可以禁用它

sudo setenforce 0

但关闭它并不安全,当你重新启动时问题会再次出现

很好的详细文章https://nts.strzibny.name/allowing-nginx-to-use-a-pumaunicorn-unix-socket-with-selinux/

简而言之,您需要执行命令并将输出保存到 nginx.te 文件中

sudo grep nginx /var/log/audit/audit.log | audit2allow -m nginx                                                                                                                        
                                                           
module nginx 1.0;                                          
                                                                
require {                                                                                                                                                                                                            
        type httpd_t;                                           
        type initrc_t;                                                                                                                                                                                               
        class unix_stream_socket connectto;              
}                                                         
                                                       
#============= httpd_t ==============                        
allow httpd_t initrc_t:unix_stream_socket connectto;  

然后检查、编译并减去

sudo checkmodule -M -m -o nginx.mod nginx.te
sudo semodule_package -o nginx.pp -m nginx.mod
sudo semodule -i nginx.pp

相关内容