【问题标题】:nginx under supervisor can't open conf filesupervisor下的nginx无法打开conf文件
【发布时间】:2019-02-18 17:49:57
【问题描述】:

这很令人费解:

我在 RHEL 7.5 上,尝试在 Supervisor 3.3.4 下运行 Nginx 1.14.0。最终目标是为 Django 站点提供服务。

我的“/etc/init.d/supervisord”看起来像这样:

#!/bin/sh
...
# Source init functions
. /etc/rc.d/init.d/functions

prog="supervisord"
prog_bin="/bin/supervisord -c /etc/supervisord.conf"
PIDFILE="/var/run/$prog.pid"

start()
{
   echo -n $"Starting $prog: "
   daemon $prog_bin --pidfile $PIDFILE
   sleep 1
   [ -f $PIDFILE ] && success $"$prog startup" || failure $"$prog startup"
   echo
}
... # "stop", "restart" functions, etc.

“/etc/supervisord.conf”看起来像这样:

[unix_http_server]
file=/var/run//supervisor.sock 

[supervisord]
logfile=/var/log/supervisor/supervisord.log
pidfile=/var/run/supervisord.pid
childlogdir=/var/log/supervisor

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = 
supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///var/run//supervisor.sock

[include]
files = /etc/supervisor/conf.d/*.conf

"/etc/supervisor/conf.d/" 里面只有一个文件:nginx.conf:

[program:nginx]
user=root
command=/usr/sbin/nginx -c /path/to/site/etc/nginx.conf
autostart=true
autorestart=true
startretries=3
redirect_stderr=True

直接用sudo /usr/sbin/nginx -c /path/to/site/etc/nginx.conf &调用上述命令是成功的。它立即启动,我可以看到带有 ps -ef 的 nginx 进程

但如果我这样启动主管:

$ sudo /etc/init.d/supervisord restart

Nginx 启动失败:

$ sudo cat /var/log/supervisor/nginx-stdout---supervisor-tqI97D.log
nginx: [emerg] open() "/path/to/site/etc/nginx.conf" failed (13: Permission denied)

读取该文件的权限一直很好。当然,路径实际上并不称为“/path/to/site/etc/nginx.conf”,但每个目录上的所有用户都有一个“x”,所有用户都有一个“r” conf文件本身的用户:

$ namei -om /path/to/site/etc/nginx.conf
f: /path/to/site/etc/nginx.conf
 dr-xr-xr-x root    root   /
 drwxr-xr-x root    root   path
 drwxr-xr-x root    root   to
 drwxrwxr-x user1   group1 site
 drwxrwxr-x user1   group1 etc
 -rw-r--r-- root    group1 nginx.conf

这个文件的“open()”操作怎么会出错?我尝试在“/etc/supervisor/conf.d/nginx.conf”和/或“/etc/supervisord.conf”中将“用户”更改为root,但结果始终相同。

这是 SELinux 的事实会有所不同吗?它目前已激活。

$ getenforce
Enforcing

如果有帮助,打不开的nginx.conf文件如下:

user  nginx;
daemon off;

error_log  /path/to/site/var/log/nginx-error.log warn;
pid        /path/to/site/var/run/nginx.pid;

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  /path/to/site/var/log/nginx-access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    upstream app_server {
        server unix:/path/to/site/var/run/my-django.socket fail_timeout=0;
    }

    server {
        listen 8000;
        server_name xxx.xxx.xxx.xxx;
        charset utf-8;

        location /media  {
            alias /path/to/site/htdocs/media;
        }

        location /static {
            alias /path/to/site/htdocs/static;
        }

        location / {
            uwsgi_pass  app_server;
            include     /path/to/site/etc/uwsgi_params;
        }
    }
}

有人有什么想法吗?

【问题讨论】:

  • 您能否在您的 nginx.conf 中使用“root”作为用户来测试运行,看看它是否还有更多功能?当然,我确定你知道,以 root 身份运行程序从来都不是解决方案,而且非常危险——我觉得我需要警告未来的读者这一点,当我们开始摆弄电脑时,我们都做了疯狂的事情,对吧。呵呵
  • 另外,您可以尝试 setenforce 0 来帮助消除 selinux 潜在故障,这只是临时措施,不会持续
  • 审计日志(/var/log/audit/audit.log)中是否有相关日志条目?
  • @OldFart - 是的!设置 setenforce 0 使其能够工作!所以问题出在 SELinux 上,而不是在主管配置中。我还注意到将 nginx 配置文件从 /path/to/site/etc/nginx.conf 移动到简单的 /etc/nginx/nginx.conf 允许它在 SELinux 强制执行的情况下运行。 SELinux 是否有关于它可以和不能从文件系统中读取的位置的规则?
  • @sebasth 当我尝试从 supervisorctl 启动 Nginx 时,“audit.log”的第一行是“type=AVC msg=audit(1536945269.368:22963):avc: denied { read } for pid =1605 comm="nginx" name="nginx.conf" dev="dm-0" ino=102588286 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file" - 这个可以帮忙吗我想办法让 Nginx 用户读取那个文件?

标签: nginx supervisord selinux rhel7


【解决方案1】:

我建议您在对生产机器进行任何操作之前与SELinux 联系以真正掌握整个概念。

httpd_t 上下文允许 NGINX 监听常见的 Web 服务器端口,访问 /etc/nginx 中的配置文件,以及访问标准 docroot 位置 (/usr/share/nginx) 中的内容。它不允许许多其他操作,例如代理到上游位置或通过套接字与其他进程通信。

一旦您成为 SELinux 的王者(哈哈),请查看 NGINX's - Modifying SELinux Settings

让我们知道,祝你好运!

【讨论】:

    【解决方案2】:

    在启用 SELinux 的系统上,进程和文件具有安全标签。 SELinux 策略包含这些标签之间允许的访问模式。如果没有规则允许访问,则拒绝访问。

    您的 nginx 文件上的安全标签似乎不正确:AVC 错误消息告诉 httpd_t 域中的进程试图访问带有 default_t 标签的文件的访问被拒绝。要允许访问,您需要为您的 nginx 文件分配合适的安全上下文。可能的上下文记录在httpd_selinux man page 中。对于配置文件,合适的上下文是httpd_config_t,对于用户内容,可能是httpd_user_content_t

    您可以使用chcon 工具手动将新的安全上下文应用于文件。在您决定要使用的安全上下文之后,您应该使用semanage 将它们保存在文件上下文数据库中。否则自动重新标记会错误地标记文件。

    我已经在相关的 Unix 和 Linux 堆栈交换问题Configure SELinux to allow daemons to use files in non-default locations 上写了一个更详细的答案。

    【讨论】:

    • 我最终解决了我的问题,方法是跟踪/var/log/audit/audit.log 并记录我尝试启动 Nginx 时出现的错误。然后我使用该日志 sn-p 创建一个带有 audit2allow 的策略模块并插入带有 semodule -i <my_policy.pp> 的策略。错误自然不止一轮,所以我把策略去掉,重复上面的过程,直到 Nginx 运行成功。我使用了这种迭代方法,以便 audit2allow 不会生成过于宽松的策略。这是否与您想象的结果相同?
    • 否,因为 AVC 拒绝消息表明问题在于您的文件标记不正确。使用audit2allow 可能会为httpd_t 添加所需的权限以访问/修改类型为default_t 的文件。使用适当的httpd_..._t 标签重新标记/path/to/site 中的文件可能会解决问题,因为已经存在允许这些类型之间访问的规则。
    猜你喜欢
    • 2016-09-11
    • 1970-01-01
    • 1970-01-01
    • 2013-08-10
    • 2019-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多