Развернуть FastAPI на сервере с Uvicorn: пошаговая инструкция
Рабочий API на FastAPI + Uvicorn за один вечер: от чистого VPS до systemd-сервиса, который переживёт перезагрузку. Разбираем каждый шаг с проверкой результата.

Что понадобится до начала
На выходе вы получите FastAPI-приложение, которое слушает HTTP-запросы через Uvicorn и автоматически стартует после перезагрузки сервера. Весь процесс занимает 30–50 минут, если сервер уже арендован.
Убедитесь, что у вас есть:
- VPS или выделенный сервер с Ubuntu 22.04 / 24.04 (Debian 12 тоже подойдёт — команды те же);
- SSH-доступ с правами
sudo; - Python 3.10 или новее — проверьте командой
python3 --version; - доменное имя, направленное A-записью на IP сервера — если хотите HTTPS (необязательно для первого запуска).
Инструкция написана для FastAPI 0.110+ и Uvicorn 0.29+. Если вы используете другие версии, сверяйтесь с официальной документацией — синтаксис запуска стабилен, но детали конфигурации могут отличаться.
Шаг 1. Подготовка окружения
Обновите пакеты и установите venv, если его ещё нет:
sudo apt update && sudo apt upgrade -y
sudo apt install -y python3-venv python3-pip
Создайте каталог проекта и виртуальное окружение:
mkdir -p /opt/myapi && cd /opt/myapi
python3 -m venv .venv
source .venv/bin/activate
Проверка: командная строка должна начинаться с (.venv). Если нет — повторите source .venv/bin/activate.
Шаг 2. Установка FastAPI и Uvicorn
pip install fastapi uvicorn[standard]
Пакет uvicorn[standard] тянет за собой uvloop и httptools — они заметно ускоряют обработку запросов по сравнению с чистым asyncio. На некоторых архитектурах (например, ARM) uvloop может не собраться; в этом случае ставьте просто uvicorn без extras.
Проверка:
pip show fastapi uvicorn
Обе библиотеки должны появиться в выводе с указанием версий.
Шаг 3. Минимальное приложение
Создайте файл /opt/myapi/main.py:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
"""Корневой маршрут — отдаёт статус."""
return {"status": "ok"}
@app.get("/health")
async def health():
"""Эндпоинт для проверки жизнеспособности сервиса."""
return {"healthy": True}
Этого достаточно, чтобы проверить весь путь от кода до браузера. Бизнес-логику добавите позже — сейчас важно убедиться, что инфраструктура работает.
Шаг 4. Первый запуск Uvicorn
cd /opt/myapi
source .venv/bin/activate
uvicorn main:app --host 0.0.0.0 --port 8000
Разберём аргументы:
| Аргумент | Что делает |
|---|---|
main:app | Модуль main.py, объект app внутри него |
--host 0.0.0.0 | Слушать все сетевые интерфейсы, а не только localhost |
--port 8000 | Порт; по умолчанию и так 8000, но лучше указать явно |
Проверка: откройте в браузере http://<IP-сервера>:8000. Должен вернуться JSON {"status": "ok"}. Автоматическая документация доступна по адресу /docs.
Если страница не открывается — проверьте, что порт 8000 разрешён в файрволе:
sudo ufw allow 8000/tcp
Остановите Uvicorn комбинацией Ctrl+C — дальше мы превратим его в системный сервис.
Шаг 5. Systemd-сервис
Запуск в терминале умрёт вместе с SSH-сессией. Чтобы приложение жило самостоятельно, создайте unit-файл /etc/systemd/system/myapi.service:
[Unit]
Description=FastAPI via Uvicorn
After=network.target
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/myapi
ExecStart=/opt/myapi/.venv/bin/uvicorn main:app --host 127.0.0.1 --port 8000 --workers 2
Restart=on-failure
RestartSec=5
Environment="PATH=/opt/myapi/.venv/bin"
[Install]
WantedBy=multi-user.target
Обратите внимание: теперь --host 127.0.0.1, а не 0.0.0.0. Снаружи приложение будет доступно через Nginx, а не напрямую. Параметр --workers 2 запускает два процесса; на VPS с одним-двумя ядрами больше ставить смысла нет.
Передайте права на каталог пользователю www-data и запустите сервис:
sudo chown -R www-data:www-data /opt/myapi
sudo systemctl daemon-reload
sudo systemctl enable myapi
sudo systemctl start myapi
Проверка:
sudo systemctl status myapi
В выводе должно быть active (running). Если статус failed — читайте лог:
sudo journalctl -u myapi -n 50 --no-pager
Шаг 6. Nginx как обратный прокси
Nginx принимает входящий трафик на порт 80 (и 443 для HTTPS) и передаёт его Uvicorn. Это стандартная схема: Nginx лучше справляется со статикой, медленными клиентами и TLS-терминированием.
sudo apt install -y nginx
Создайте файл /etc/nginx/sites-available/myapi:
server {
listen 80;
server_name your-domain.com; # замените на свой домен или IP
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;
}
}
Активируйте конфигурацию:
sudo ln -s /etc/nginx/sites-available/myapi /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Проверка: откройте http://your-domain.com/ — должен вернуться тот же JSON. Порт 8000 в URL больше не нужен.
Не открывайте Uvicorn напрямую в интернет на продолжительное время. Без Nginx перед ним вы остаётесь без защиты от slowloris-атак, без ограничения размера тела запроса и без удобного TLS. Прокси — не опция, а гигиена.
Шаг 7. HTTPS через Certbot
Если у вас есть домен, получить бесплатный TLS-сертификат от Let's Encrypt можно за минуту:
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.com
Certbot сам допишет нужные строки в конфиг Nginx и настроит автообновление сертификата. Проверка: откройте https://your-domain.com/docs — должна загрузиться Swagger-документация по защищённому соединению.
Если не получилось
Пять ошибок, которые встречаются чаще всего:
ModuleNotFoundError: No module named 'fastapi'— вы запустили Uvicorn системным Python, а не из виртуального окружения. В unit-файле должен быть полный путь:/opt/myapi/.venv/bin/uvicorn.ERROR: [Errno 98] Address already in use— порт 8000 уже занят. Найдите процесс:sudo lsof -i :8000и остановите его или выберите другой порт.502 Bad Gatewayв Nginx — Uvicorn не запущен или слушает другой порт/хост. Убедитесь, чтоproxy_passсовпадает с--hostи--portв unit-файле.Permission deniedпри старте сервиса — пользовательwww-dataне имеет прав на каталог/opt/myapi. Повторитеchown.- Страница открывается по IP, но не по домену — A-запись DNS ещё не обновилась. Проверьте:
dig +short your-domain.com. Если IP не совпадает — подождите или проверьте настройки DNS у регистратора.
Что дальше
Рабочий скелет готов. Следующие шаги зависят от проекта, но порядок обычно такой:
- Вынесите секреты (ключи БД, токены) в переменные окружения или
.env-файл — никогда не храните их в коде. - Подключите базу данных: для FastAPI часто берут SQLAlchemy 2.x с асинхронным драйвером или Tortoise ORM.
- Настройте логирование: Uvicorn пишет в stdout, systemd сохраняет это в journald, но для продакшена удобнее структурированные JSON-логи.
- Добавьте rate limiting и CORS — без них открытый API быстро привлечёт нежелательный трафик.
- Посмотрите в сторону Gunicorn с Uvicorn worker-классом, если нужна более гибкая стратегия перезапуска воркеров. Об этом подробно рассказывает официальная документация FastAPI по деплою.
Мерьте время ответа эндпоинтов на реальных данных до того, как начнёте оптимизировать. Встроенная документация по адресу /docs — хороший способ показать API коллегам или заказчику без дополнительных инструментов.
Проверка рекламы на риски: Что в макете вызовет вопросы ФАС: превосходные степени, сравнения, обещания результата, маркировка.
Спросить за 40 ₽Источники: FastAPI — официальная документация по деплою, Uvicorn — официальная документация
Частые вопросы
Можно ли обойтись без Nginx и открыть Uvicorn напрямую?
Сколько воркеров Uvicorn ставить?
Приложение падает после закрытия SSH-сессии — что делать?
Как обновить код на сервере без даунтайма?
А если у меня другая версия Python или ОС?
Нужен ли Gunicorn, если есть Uvicorn?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.