۱. نسخهی Python
Python پیشفرض نسخهی ۹ این توزیعها 3.9 است و نسخهی ۱۰ با 3.12 عرضه میشود. روی نسخهی ۹ میتوانید نسخهی جدیدتر را از AppStream نصب کنید، بدون اینکه Python سیستم تغییر کند:
python3 --version
sudo dnf install -y python3.12 python3.12-pip # Rocky/Alma 9; already default on 10Python سیستم (/usr/bin/python3) را هرگز جایگزین نکنید. dnf و ابزارهای سیستم به آن وابستهاند.
۲. کاربر و محیط مجازی
sudo useradd --system --create-home --home-dir /opt/app --shell /sbin/nologin app
sudo -u app python3.12 -m venv /opt/app/venv
sudo -u app /opt/app/venv/bin/pip install --upgrade pip flask gunicornیک برنامهی آزمایشی در /opt/app/app.py:
from flask import Flask
app = Flask(__name__)
@app.get("/health")
def health():
return {"status": "ok"}۳. سرویس systemd
/etc/systemd/system/app.service:
[Unit]
Description=Sahor Python app
After=network.target
[Service]
User=app
Group=app
WorkingDirectory=/opt/app
ExecStart=/opt/app/venv/bin/gunicorn --workers 3 --bind 127.0.0.1:8000 app:app
Restart=on-failure
NoNewPrivileges=true
ProtectSystem=strict
ReadWritePaths=/opt/app
PrivateTmp=true
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now app
curl -s 127.0.0.1:8000/health۴. Nginx و SELinux
sudo dnf install -y nginx/etc/nginx/conf.d/app.conf:
server {
listen 80;
server_name app.corp.sahor.ir;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}SELinux بهطور پیشفرض اجازه نمیدهد Nginx به پورت برنامه وصل شود و نتیجه خطای 502 Bad Gateway است. اتصال شبکهای وبسرور را مجاز کنید:
sudo setsebool -P httpd_can_network_connect 1sudo nginx -t && sudo systemctl enable --now nginx
sudo firewall-cmd --permanent --add-service=http && sudo firewall-cmd --reloadاگر هنوز 502 میگیرید، دلیل را در لاگ SELinux ببینید:
sudo ausearch -m avc -ts recent | audit2why۵. بهروزرسانی برنامه
sudo -u app /opt/app/venv/bin/pip install -r /opt/app/requirements.txt
sudo systemctl restart app
journalctl -u app -n 30 --no-pager