当前位置:首页>Linux>AlmaLinux部署Flask遇到502,SELinux不背这个锅

AlmaLinux部署Flask遇到502,SELinux不背这个锅

  • 2026-10-21 13:28:52
AlmaLinux部署Flask遇到502,SELinux不背这个锅

CentOS不再维护,换用Alma Linux 来部署了 Flask 应用,一切看起来都很顺畅,可访问 URL 时却报了——502 Bad Gateway!​从头检查了配置、权限、日志,全都无济于事。于是尝试输入 sudo setenforce 0,应用居然能正常访问了!​

是不是觉得SELinux就是没事找事的东西,但实际上它是在执行它的安全职责,禁用只是你放开了安全策略。今天我们就来看看这个问题。

默认情况下SELinux会拦截Nginx连接Gunicorn的Unix套接字;systemd从/home目录启动Gunicorn,应用通过SMTP发送邮件。上面这些他都拦。那么怎么来判断是不是SELinux干的活的?通过两个命令定位问题

# 查看 SELinux 拦截的操作sudo ausearch -m avc -ts recent# 查看服务日志sudo journalctl -u your-service -n 50 --no-pager

如果日志重出现"Permission denied with code  203/EXEC",那就是SELinux在拦截。

接下来我们看看解决方案,首先将Web迁移到/var/www目录,SELinux对Web应用放在/home目录非常的敏感

sudo systemctl stop your-service  # 停止应用服务sudo mkdir -p /var/www  # 创建目标目录sudo mv /home/user/my-app /var/www/my-app  # 迁移应用sudo chown -R user:user /var/www/my-app  # 设置目录权限sudo restorecon -Rv /var/www/my-app  # SELinux 权限重置(关键一步)

然后编辑systemd服务文件/etc/systemd/system/your-service.service,替换为以下内容:

[Unit]Description=Gunicorn for Flask app  # 服务描述After=network.target  # 网络启动后再启动该服务[Service]User=your-user  # 运行服务的用户Group=your-group  # 运行服务的用户组WorkingDirectory=/var/www/my-app  # 应用工作目录# 启动前准备:创建套接字目录、设置权限ExecStartPre=/usr/bin/mkdir -p /var/run/my-appExecStartPre=/usr/bin/chown your-user:nginx /var/run/my-appExecStartPre=/usr/bin/chmod 755 /var/run/my-appEnvironment="PATH=/var/www/my-app/venv/bin"  # 虚拟环境路径# Gunicorn 启动命令ExecStart=/var/www/my-app/venv/bin/gunicorn \    --workers 4 \  # 工作进程数(根据服务器配置调整)    --bind unix:/var/run/my-app/my-app.sock \  # 绑定 Unix 套接字    --umask 007 \  # 设定文件创建权限掩码    wsgi:app  # 应用入口(wsgi.py 中的 app 实例)Restart=always  # 服务异常时自动重启[Install]WantedBy=multi-user.target  # 多用户模式下启动

配置完成后重载systemd配置

sudo systemctl deamon-reload

配置SELinux上下文,告诉哪些是合法操作,避免被误拦截:

# 配置套接字目录的 SELinux 上下文(标记为合法的 Web 服务运行目录)sudo semanage fcontext -a -t httpd_var_run_t "/var/run/my-app(/.*)?"sudo restorecon -Rv /var/run/my-app# 允许 Nginx 进行网络连接sudo setsebool -P httpd_can_network_connect 1

创建定义专属放行策略:

# 临时切换到宽容模式(让应用正常运行以生成拦截记录)sudo setenforce 0# 重启应用,触发可能的 SELinux 拦截(生成日志)sudo systemctl restart your-servicesleep 5  # 等待 5 秒,让应用稳定运行curl http://localhost  # 访问应用,触发相关操作# 根据拦截日志生成自定义策略(my_policy 是策略名称,可自定义)sudo ausearch -m avc -ts recent | audit2allow -M my_policy# 安装自定义策略sudo semodule -i my_policy.pp# 切回强制模式(恢复 SELinux 安全防护)sudo setenforce 1# 重启服务,验证效果sudo systemctl restart your-service

audit2allow工具会分析所有SELinux的拦截记录,生成一个允许这些操作的策略文件,安装后,SELinux就知道哪些是合法操作了。

接下来编辑Nginx反向代理,修改/etc/nginx/conf.d下的.conf文件:

upstream app_server {    # 连接 Gunicorn 的 Unix 套接字(与 systemd 配置中的路径一致)    server unix:/var/run/my-app/my-app.sock fail_timeout=0;}server {    listen 80;  # 监听 80 端口    server_name my-domain.com;  # 你的域名或服务器 IP    location / {        proxy_pass http://app_server;  # 反向代理到 Gunicorn        proxy_set_header Host $host;  # 传递主机头信息        proxy_set_header X-Real-IP $remote_addr;  # 传递真实客户端 IP    }}

配置完成后,验证并重载Nginx

sudo nginx -t  # 验证配置是否正确sudo systemctl reload nginx  # 重载 Nginx 配置

以下是一些常见问题的快速修复方式

无法发送邮件:执行 sudo setsebool -P httpd_can_sendmail 1外部数据库连接被拦截:sudo setsebool -P httpd_can_network_connect_db 1API 调用失败:sudo setsebool -P httpd_can_network_connect 1
通过以下命令逐一验证:
# 检查 SELinux 模式(应显示 "Enforcing",即强制模式)getenforce# 检查应用服务状态(应显示 "active (running)")sudo systemctl status your-service# 检查是否还有 SELinux 拦截记录(无输出即正常)sudo ausearch -m avc -ts recent# 测试应用访问(应返回 200 OK)curl -I http://your-domain.com
总之,遇到问题,千万别甩锅给SELinux,它在生产环境中起到关键的作用,遇到问题找到原因,解决它才是我们的目的。

最新文章

随机文章