Skip to content
VDS · Сайти та вебсервери

Застосунок на Python: gunicorn і systemd

Запуск Django, Flask або FastAPI на VPS: віртуальне середовище, gunicorn із сокетом, служба systemd і вибір кількості воркерів для вашого тарифу.

Оновлено 23 серпня 2026 р.

Вбудований сервер розробки (manage.py runserver, flask run) не призначений для продакшен-навантаження. На VPS ви встановлюєте gunicorn або uvicorn, а вебсервер обслуговує їх ззовні.

Середовище

Ніколи не встановлюйте пакети проєкту в системний Python — оновлення системи зламає застосунок.

apt install -y python3 python3-venv python3-pip
useradd -r -m -d /srv/app -s /usr/sbin/nologin appuser

sudo -u appuser python3 -m venv /srv/app/venv
sudo -u appuser /srv/app/venv/bin/pip install -r /srv/app/requirements.txt
sudo -u appuser /srv/app/venv/bin/pip install gunicorn

Для FastAPI додатково встановіть uvicorn[standard] — gunicorn запускає його як клас воркера.

Служба

/etc/systemd/system/myapp.service:

[Unit]
Description=Python app
After=network-online.target postgresql.service

[Service]
User=appuser
WorkingDirectory=/srv/app
EnvironmentFile=/srv/app/.env
ExecStart=/srv/app/venv/bin/gunicorn \
  --workers 3 \
  --bind unix:/run/myapp/gunicorn.sock \
  --access-logfile - \
  myproject.wsgi:application
RuntimeDirectory=myapp
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Для FastAPI замініть рядок запуску на --worker-class uvicorn.workers.UvicornWorker app.main:app.

systemctl daemon-reload
systemctl enable --now myapp
journalctl -u myapp -f

RuntimeDirectory=myapp створює /run/myapp з потрібними правами під час кожного запуску — інакше сокету нікуди подітися.

Скільки воркерів

Звична формула — 2 × cores + 1, але вона впирається в обмеження пам'яті: кожен воркер Django використовує 80–200 МБ.

ТарифЯдраВоркери
VDS-112
VDS-223
VDS-345
VDS-469

Якщо застосунок багато часу чекає на мережу та базу даних, додайте --threads 2 замість збільшення кількості процесів.

Вебсервер

location / {
    proxy_pass http://unix:/run/myapp/gunicorn.sock;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

location /static/ { alias /srv/app/static/; }

Статичні файли Django віддавайте напряму через Nginx після їх збору: collectstatic. Передача їх через Python додає зайве навантаження.

Типові помилки

СимптомПричина
502 і connect() to unix:... failed (13)Nginx не має прав на сокет — задайте --umask 007 і спільну групу
ModuleNotFoundErrorЗапуск із системним Python замість venv
DisallowedHost у DjangoДомен не додано до ALLOWED_HOSTS
Воркери вбиває таймаутДовгий запит — збільште --timeout, перенесіть важку роботу в чергу
Усе зупинилося після релізуВи забули systemctl restart myapp — код у пам'яті сам не оновлюється

Тримайте секрети в EnvironmentFile з правами 600, а не в settings.py. Файл налаштувань рано чи пізно потрапить до репозиторію.