Мы не будем подробно рассматривать что такое uWSGI. Цель статьи - запустить сайт написанный на python (Flask). Также подразумевается, что nginx уже установлен и активно используется.
На тему uWSGI написано много статей. Схема ниже показывает главную суть — реализация протокола WSGI для обеспечения взаимодействия между веб-сервером и конечными приложениями.

uWSGI, как и др. пакеты, можно установить из deb-пакетов:
sudo apt update
sudo apt install nginx uwsgi uwsgi-plugin-python
Этот способ предпочтительнее т.к. сервер сразу регистрируется в системе как сервис:
sudo systemctl enable uwsgi
service uwsgi status
Также можно произвести установку в виде модуля python. Примерно с 22.04 версии в Ubuntu введен запрет на установку python-модулей без активации виртуального окружения. Но, для того чтобы не использовать --break-system-packages, появилась утилита pipx:
sudo apt install pipx
pipx install uwsgi
sudo pipx ensurepath --global
command -v uwsgi >/dev/null 2>&1 || sudo ln -s ~/.local/bin/uwsgi /usr/bin/uwsgi && uwsgi --version
Если вы выберете этот способ, то для автоматического запуска uWSGI прийдется создать:
systemd unit
sudo touch /etc/systemd/system/myapp.service
sudo mcedit /etc/systemd/system/myapp.service
# /etc/systemd/system/uwsgi.service
[Unit]
Description=uWSGI instance for myapp
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/domain-or-subdomain
ExecStart=/var/www/domain-or-subdomain/uwsgi --ini uwsgi.ini
Restart=always
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all
[Install]
WantedBy=multi-user.target
После внесения изменений ниже нужно будет сделать enable/start для одноименного сервиса — myapp
Продолжаем. Создаем директории и конфиги:
touch /etc/nginx/sites-available/domain-or-subdomain.conf
ln -s /etc/nginx/sites-available/domain-or-subdomain.conf /etc/nginx/sites-enabled/
mkdir -p /var/www/domain-or-subdomain
touch /var/www/domain-or-subdomain/myapp.py
touch /var/www/domain-or-subdomain/uwsgi.ini
sudo mkdir -p /var/log/uwsgi/ && touch /var/log/uwsgi/myapp.log
sudo chgrp -R www-data /var/log/uwsgi/myapp.log
sudo chmod g+rw /var/log/uwsgi/myapp.log
Содержимое конфига nginx:
server {
listen 80;
server_name your_domain.com;
root /var/www/domain-or-subdomain;
#index index.html index.htm;
# Обслуживание статических файлов напрямую через Nginx
location /static/ {
alias /path/to/your/www-root/static/;
}
# Проксирование всех остальных запросов к uWSGI
location / {
include uwsgi_params;
uwsgi_pass unix:/run/uwsgi/app/myapp/socket;
uwsgi_param Host $host;
uwsgi_param X-Real-IP $remote_addr;
uwsgi_param X-Forwarded-For $proxy_add_x_forwarded_for;
uwsgi_param X-Forwarded-Proto $scheme;
}
# Статистика веб-сервера (только для localhost)
location /uwsgi-stats {
allow 127.0.0.1;
deny all;
uwsgi_pass 127.0.0.1:9191;
}
location ~* \.(jpg|jpeg|gif|png|svg|webp)$ {
expires 30d;
add_header X-Cache-Status "Browser Cache";
}
access_log /var/log/nginx/myapp_access.log;
error_log /var/log/nginx/myapp_error.log;
}
Содержимое конфига uwsgi.ini:
[uwsgi]
uid = www-data
gid = www-data
chdir = /var/www/domain-or-subdomain
module = myapp:app
plugins = python3
# Включение мастер-процесса
master = true
processes = 4
enable-threads = true
threads = 2
max-requests = 6000
no-orphans = true
die-on-term = true
# Сокет для связи с Nginx (используется протокол uwsgi)
socket = unix:/run/uwsgi/app/myapp/socket
# Права на сокет (чтобы Nginx мог писать)
chmod-socket = 660
# Очистка сокета при остановке
vacuum = true
# Отключение логирования для статики
static-skip-ext = .jpg,.jpeg,.png,.gif,.ico,.css,.js
# Graceful restart при изменении кода
py-autoreload = 1
stats = 127.0.0.1:9191
memory-report = true
Сам скрипт, который будет отвечать на запросы:
#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
def app(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b"<h1>Hello Master!</h1>"]
Теперь можно проверить работу сервера:
cd /var/www/domain-or-subdomain
sudo chown -R www-data:www-data /var/www/domain-or-subdomain
# sudo запустит сервис по днужным пользователем, если без sudo, то запуск произойдет от вашего имени
sudo uwsgi --http-socket :8080 --plugin python3 --module myapp:app
Сайт должен отдавать контент по адресу: http://localhost:8080/ Если это так, то можно переходить к тестированию боевой схемы с nginx
Применяем новые конфигурации:
sudo nginx -t && sudo systemctl reload nginx
sudo uwsgi --ini /var/www/domain-or-subdomain/uwsgi.ini
Результат работы скрипта будет досткпен по доменному имени, который прописан в nginx. Но перестанет после перезагрузки системы. Давайте пропишем его как автозапускаемый сервис:
sudo mv /var/www/domain-or-subdomain/uwsgi.ini /etc/uwsgi/apps-available/myapp.ini
sudo ln -s /etc/uwsgi/apps-available/myapp.ini /etc/uwsgi/apps-enabled/myapp.ini
Применяем изменения и смотрим информацию о нашем приложении:
sudo systemctl restart uwsgi
sudo service uwsgi status myapp
Наслаждаемся результатом!
См. также