FastAPI-приложение можно развернуть на VPS как полноценный production-сервис: установить Python и зависимости, подключить PostgreSQL, настроить миграции, запустить приложение через Gunicorn/Uvicorn и оформить его как службу systemd. Nginx будет работать как reverse proxy и принимать внешние HTTP/HTTPS-запросы, а SSL-сертификат можно выпустить через Let’s Encrypt.
В этом руководстве развернем небольшой FastAPI API, добавим health endpoint и Swagger UI, настроим хранение секретов, работу с PostgreSQL, просмотр логов и перезапуск приложения после обновления кода. Использовать Docker и подобные средства контейнеризации мы не будем, пойдём по старинке - это поможет лучше понять, как работает приложение, reverse proxy, БД и вообще система.
Подготовка VPS
Для развертывания FastAPI понадобится VPS под управлением Linux с доступом по SSH. В примере используется Ubuntu, а приложение будет работать вместе с PostgreSQL и Nginx.
Подключение к серверу по SSH
Подключитесь к VPS по SSH. В Windows для этого можно использовать PowerShell или Windows Terminal: ssh root@203.0.113.10
При первом подключении подтвердите добавление ключа сервера в доверенные, введя yes, а затем укажите пароль пользователя root.
После успешной авторизации появится командная строка удаленного сервера.
Обновление системы и установка Python, PostgreSQL, Nginx
Сначала обновите индекс пакетов и установленные компоненты: sudo apt update && sudo apt upgrade -y
Затем установите Python, инструменты для создания виртуального окружения, PostgreSQL, Nginx и дополнительные пакеты, которые понадобятся приложению:
sudo apt install -y python3 python3-pip python3-venv python3-dev postgresql postgresql-contrib nginx libpq-dev
PostgreSQL доступен непосредственно из репозиториев Ubuntu и после установки может работать как системная служба.
Создание FastAPI-приложения
Приложение разместим в отдельном каталоге и изолируем его Python-зависимости от системных пакетов с помощью виртуального окружения venv. Такой подход позволяет устанавливать необходимые версии библиотек непосредственно для проекта, без влияния на всю систему.
Создание проекта и виртуального окружения
Создайте каталог приложения и перейдите в него:
sudo mkdir -p /var/www/fastapi-app
sudo chown -R $USER:$USER /var/www/fastapi-app
cd /var/www/fastapi-app
Создайте виртуальное окружение: python3 -m venv venv
Активируйте его: source venv/bin/activate
После активации в начале строки терминала появится (venv).
Установка FastAPI, Uvicorn, Gunicorn и зависимостей
Обновите pip: pip install --upgrade pip
Установите FastAPI, ASGI-сервер Uvicorn, Gunicorn, драйвер PostgreSQL, SQLAlchemy и Alembic: pip install fastapi uvicorn gunicorn sqlalchemy psycopg2-binary alembic python-dotenv
Сохраним список установленных зависимостей: pip freeze > requirements.txt
Файл requirements.txt позволит впоследствии установить те же зависимости после переноса или повторного развертывания приложения.
Создание API и health endpoint

Создайте основной файл приложения: nano main.py
Добавьте следующий код:
from fastapi import FastAPI
app = FastAPI(
title="FastAPI VPS Example",
version="1.0.0"
)
@app.get("/")
def root():
return {"message": "FastAPI is running"}
@app.get("/health")
def health():
return {"status": "ok"}
Сохраните файл сочетанием Ctrl+O, нажмите Enter, затем закройте редактор через Ctrl+X.
Для первой проверки запустите приложение через Uvicorn: uvicorn main:app --host 0.0.0.0 --port 8000
Uvicorn запустит ASGI-приложение на порту 8000. Для production-развертывания FastAPI поддерживает запуск нескольких рабочих процессов, а далее в руководстве управление процессом будет передано systemd.
В другом терминале или непосредственно на сервере можно проверить health endpoint: curl http://127.0.0.1:8000/health
В ответ API должен вернуть: {"status":"ok"}
Настройка PostgreSQL
FastAPI-приложению потребуется отдельная база данных и пользователь PostgreSQL. Параметры подключения вынесем из исходного кода в файл .env.
Создание базы данных и пользователя
Переключитесь на системного пользователя PostgreSQL и откройте консоль psql: sudo -u postgres psql
Создайте пользователя приложения с паролем: CREATE USER fastapi_user WITH PASSWORD 'StrongPassword123!';
Создайте базу данных и назначьте нового пользователя ее владельцем: CREATE DATABASE fastapi_db OWNER fastapi_user;
Команды CREATE ROLE/CREATE USER и CREATE DATABASE используются PostgreSQL для создания ролей и отдельных баз данных.
Выйдите из консоли PostgreSQL: \q
Проверить подключение можно командой: psql -h 127.0.0.1 -U fastapi_user -d fastapi_db
Введите созданный ранее пароль. После успешного подключения выйдите через: \q
Подключение FastAPI к PostgreSQL
Перейдите в каталог приложения: cd /var/www/fastapi-app
Создайте файл database.py: nano database.py
Добавьте конфигурацию SQLAlchemy:
import os
from dotenv import load_dotenv
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base, sessionmaker
load_dotenv()
DATABASE_URL = os.getenv("DATABASE_URL")
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(
autocommit=False,
autoflush=False,
bind=engine
)
Base = declarative_base()
SQLAlchemy создает подключение через URL базы данных; для PostgreSQL с драйвером psycopg2 используется формат postgresql+psycopg2://....
Хранение секретов в .env

Создайте файл .env: nano .env
Добавьте строку подключения: DATABASE_URL=postgresql+psycopg2://fastapi_user:StrongPassword123!@127.0.0.1:5432/fastapi_db
Ограничьте доступ к файлу: chmod 600 .env
Проверим подключение к базе из виртуального окружения:
source venv/bin/activate
python -c "from database import engine; conn = engine.connect(); print('PostgreSQL connection OK'); conn.close()"
При успешном подключении появится сообщение: PostgreSQL connection OK
Настройка миграций
Для управления структурой базы данных воспользуемся Alembic. Он позволяет хранить изменения схемы в виде последовательных миграций и применять их при развертывании или обновлении приложения.
Установка и настройка Alembic
Alembic уже был установлен вместе с зависимостями приложения. Находясь в каталоге проекта с активированным виртуальным окружением, создайте его конфигурацию: alembic init migrations
Команда создаст каталог migrations и файл alembic.ini.
Создадим простую модель, для которой затем сформируем миграцию: nano models.py
Добавьте:
from sqlalchemy import Column, Integer, String
from database import Base
class Item(Base):
__tablename__ = "items"
id = Column(Integer, primary_key=True)
name = Column(String(255), nullable=False)
Теперь откройте файл: nano migrations/env.py
Найдите строку: target_metadata = None
И замените ее на:
from database import Base
import models
target_metadata = Base.metadata
Также добавьте в начало файла:
import os
from dotenv import load_dotenv
load_dotenv()
После строки config = context.config добавьте config.set_main_option("sqlalchemy.url", os.environ["DATABASE_URL"])
Таким образом Alembic будет использовать ту же строку подключения из .env, что и приложение.
Создание и применение миграции

Создайте первую миграцию: alembic revision --autogenerate -m "create items table"
Параметр --autogenerate позволяет Alembic сравнить метаданные SQLAlchemy с текущей схемой базы данных и подготовить изменения для файла миграции.
Примените миграцию: alembic upgrade head
Проверим текущее состояние: alembic current
Затем можно убедиться, что таблица появилась в PostgreSQL: psql -h 127.0.0.1 -U fastapi_user -d fastapi_db -c "\dt"
В списке должны присутствовать таблицы items и alembic_version.
Проверка FastAPI
Перед настройкой постоянного запуска приложения убедимся, что FastAPI корректно работает через Uvicorn и созданные endpoints доступны локально.
Запуск приложения через Uvicorn
Перейдите в каталог проекта и активируйте виртуальное окружение:
cd /var/www/fastapi-app
source venv/bin/activate
Запустите приложение: uvicorn main:app --host 127.0.0.1 --port 8000
Здесь main — имя файла main.py, а app — созданный в нем объект FastAPI. Для ASGI-приложений FastAPI может работать через Uvicorn как отдельный серверный процесс.
После запуска в терминале появится сообщение о том, что Uvicorn принимает подключения на 127.0.0.1:8000.
Проверка health endpoint и Swagger UI
Не останавливая Uvicorn, откройте второй SSH-сеанс и выполните: curl http://127.0.0.1:8000/health
В ответ должно вернуться: {"status":"ok"}
Также проверим корневой endpoint: curl http://127.0.0.1:8000/
Ответ: {"message":"FastAPI is running"}
FastAPI автоматически формирует интерактивную документацию Swagger UI. Пока приложение доступно только локально, проверить ее с самого сервера можно запросом: curl -I http://127.0.0.1:8000/docs
Полноценный интерфейс Swagger UI откроем в браузере после настройки Nginx и доступа по домену.
После проверки остановите Uvicorn сочетанием Ctrl+C.
Запуск FastAPI через Gunicorn и systemd
Для постоянной работы приложение запустим через Gunicorn с отдельным Uvicorn Worker, а управление процессом передадим systemd. Это позволит автоматически запускать API вместе с сервером и перезапускать его после сбоев.
Настройка Gunicorn с Uvicorn Worker
Установите пакет uvicorn-worker:
source /var/www/fastapi-app/venv/bin/activate
pip install uvicorn-worker
pip freeze > requirements.txt
Отдельный пакет uvicorn-worker предоставляет ASGI-воркер для запуска приложений через Gunicorn. Его использование позволяет оставить управление процессами Gunicorn, а обработку ASGI-приложения передать Uvicorn.
Проверьте запуск приложения:
gunicorn main:app \
--workers 2 \
--worker-class uvicorn_worker.UvicornWorker \
--bind 127.0.0.1:8000
Параметр --workers 2 запускает два рабочих процесса. Несколько воркеров позволяют использовать несколько процессов приложения одновременно.
В другом SSH-сеансе выполните: curl http://127.0.0.1:8000/health
После успешной проверки остановите Gunicorn сочетанием Ctrl+C.
Создание systemd-сервиса
Создайте unit-файл: sudo nano /etc/systemd/system/fastapi.service
Добавьте:
[Unit]
Description=FastAPI application
After=network.target postgresql.service
[Service]
User=root
Group=www-data
WorkingDirectory=/var/www/fastapi-app
EnvironmentFile=/var/www/fastapi-app/.env
ExecStart=/var/www/fastapi-app/venv/bin/gunicorn main:app \
--workers 2 \
--worker-class uvicorn_worker.UvicornWorker \
--bind 127.0.0.1:8000
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Приложение будет принимать запросы только на локальном адресе 127.0.0.1:8000. Внешний доступ позднее будет организован через Nginx.
Запуск и проверка статуса сервиса

Перечитайте конфигурацию systemd: sudo systemctl daemon-reload
Добавьте сервис в автозагрузку: sudo systemctl enable fastapi
Запустите его: sudo systemctl start fastapi
Проверьте состояние: sudo systemctl status fastapi --no-pager
При нормальном запуске сервис должен находиться в состоянии: Active: active (running)
Дополнительно проверим API: curl http://127.0.0.1:8000/health
Ответ: {"status":"ok"}
Настройка Nginx
FastAPI уже работает как локальный сервис на 127.0.0.1:8000, но напрямую этот порт открывать в интернет не стоит и не требуется. Перед приложением настроим Nginx, который будет принимать внешние запросы и передавать их FastAPI как reverse proxy. Такой вариант соответствует типичной схеме размещения FastAPI за прокси-сервером.
Создание reverse proxy для FastAPI
Создайте отдельный конфигурационный файл сайта: sudo nano /etc/nginx/sites-available/fastapi
Добавьте конфигурацию:
server {
listen 80;
listen [::]:80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
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;
}
}
Директива proxy_pass передает запросы от Nginx локальному серверу FastAPI.
Активируйте конфигурацию: sudo ln -s /etc/nginx/sites-available/fastapi /etc/nginx/sites-enabled/fastapi
Если стандартный сайт Nginx больше не используется, отключите его: sudo rm -f /etc/nginx/sites-enabled/default
Проверьте конфигурацию: sudo nginx -t
При отсутствии ошибок примените изменения: sudo systemctl reload nginx
Проверка API через домен

До этого момента DNS-запись домена должна указывать на публичный IP VPS. Например, для api.example.com создается A-запись на адрес сервера.
После обновления DNS проверьте API: curl http://api.example.com/health
Ожидаемый ответ: {"status":"ok"}
В браузере также можно открыть: http://api.example.com/docs
Если проксирование настроено корректно, загрузится Swagger UI FastAPI.
Настройка HTTPS
Следующий этап — включение HTTPS. TLS-соединение будет терминироваться на Nginx, а FastAPI продолжит работать локально за reverse proxy. Такая схема позволяет не настраивать сертификаты непосредственно внутри приложения.
Установка Certbot
Установите Certbot и плагин для Nginx:
sudo apt update
sudo apt install -y certbot python3-certbot-nginx
Убедитесь, что Certbot доступен: certbot --version
Получение SSL-сертификата Let’s Encrypt
Запустите Certbot для домена приложения: sudo certbot --nginx -d api.example.com
Укажите адрес электронной почты, примите условия использования и выберите перенаправление HTTP-трафика на HTTPS, если Certbot предложит соответствующий вариант.
Плагин Nginx позволяет Certbot получить сертификат и автоматически изменить конфигурацию веб-сервера для работы через HTTPS.
После выпуска сертификата проверьте конфигурацию: sudo nginx -t
Затем проверьте механизм автоматического продления: sudo certbot renew --dry-run
Проверка API по HTTPS
Проверьте health endpoint: curl https://api.example.com/health
Ожидаемый ответ: {"status":"ok"}
Теперь Swagger UI доступен по защищенному адресу: https://api.example.com/docs
Логи и обслуживание приложения
При эксплуатации API важно иметь возможность быстро проверить состояние приложения и определить причину ошибки. Для этого можно использовать журнал systemd и стандартные журналы Nginx.
Просмотр логов FastAPI через journalctl
Поскольку приложение работает как systemd-сервис, его вывод можно просматривать через journalctl. Эта команда используется для чтения записей системного журнала systemd.
Для просмотра последних записей FastAPI выполните: sudo journalctl -u fastapi -n 50 --no-pager
Для просмотра журнала в реальном времени: sudo journalctl -u fastapi -f
Здесь будут отображаться сообщения Gunicorn, Uvicorn, ошибки запуска приложения и другая информация, записываемая сервисом.
Выйти из режима просмотра в реальном времени можно сочетанием Ctrl+C.
Просмотр логов Nginx
Журнал входящих запросов Nginx можно посмотреть командой: sudo tail -n 50 /var/log/nginx/access.log
Ошибки Nginx записываются отдельно: sudo tail -n 50 /var/log/nginx/error.log
Для наблюдения за ошибками в реальном времени: sudo tail -f /var/log/nginx/error.log
Обновление FastAPI-приложения
После изменения исходного кода приложение необходимо перезапустить, чтобы рабочие процессы Gunicorn загрузили новую версию. Если обновление затрагивает структуру базы данных, перед перезапуском также следует применить новые миграции.
Обновление кода и применение миграций
Перейдите в каталог проекта: cd /var/www/fastapi-app
Активируйте виртуальное окружение: source venv/bin/activate
После замены или получения новой версии исходного кода установите зависимости из requirements.txt, если они изменились: pip install -r requirements.txt
Если новая версия приложения содержит миграции Alembic, примените их: alembic upgrade head
Текущую примененную миграцию можно проверить командой: alembic current
Перезапуск systemd-сервиса
Чтобы Gunicorn загрузил обновленную версию приложения, перезапустите сервис: sudo systemctl restart fastapi
Проверьте его состояние: sudo systemctl status fastapi --no-pager
Сервис должен снова находиться в состоянии: Active: active (running)
Проверка приложения после обновления
Проверьте health endpoint через публичный HTTPS-адрес: curl https://api.example.com/health
Ожидаемый ответ: {"status":"ok"}
При необходимости сразу после перезапуска можно проверить журнал приложения: sudo journalctl -u fastapi -n 30 --no-pager
Это позволяет убедиться, что новая версия FastAPI успешно запустилась и не завершилась с ошибкой после обновления.
Заключение

FastAPI-приложение развернуто на VPS и подключено к PostgreSQL. Для управления схемой базы данных используется Alembic, приложение запускается через Gunicorn с Uvicorn Worker и работает как systemd-сервис с автоматическим запуском после перезагрузки сервера.
Nginx принимает внешние запросы и передает их FastAPI через reverse proxy, а Certbot обеспечивает работу API по HTTPS. Такая конфигурация также позволяет централизованно хранить секреты в .env, просматривать логи через journalctl и быстро перезапускать приложение после обновления кода.
FAQ
Зачем FastAPI нужен Nginx?
FastAPI можно запустить напрямую через ASGI-сервер, однако при публичном развертывании Nginx удобно использовать как reverse proxy. Он принимает внешние HTTP- и HTTPS-запросы, работает с TLS-сертификатом и передает запросы локальному приложению. Официальная документация FastAPI также рассматривает развертывание приложения за прокси-сервером.
Где хранить пароль от PostgreSQL и другие секреты?
Пароли, токены и строки подключения не следует размещать непосредственно в исходном коде. В рассмотренной конфигурации они хранятся в .env, доступ к которому ограничен средствами файловой системы Linux. При использовании системы контроля версий такой файл также следует добавить в .gitignore.
Для чего нужны миграции Alembic?
Миграции позволяют последовательно изменять структуру базы данных вместе с развитием приложения. Например, после добавления нового столбца в SQLAlchemy-модель можно создать новую миграцию и применить ее к PostgreSQL вместо ручного изменения таблиц.
Где находится Swagger UI FastAPI?
FastAPI автоматически предоставляет интерактивную документацию Swagger UI. При стандартных настройках после развертывания она доступна по адресу: https://api.example.com/docs
Через Swagger UI можно просматривать доступные endpoints, параметры запросов и отправлять тестовые запросы к API.
Как проверить, работает ли FastAPI после перезапуска сервера?
Проверьте состояние systemd-сервиса: sudo systemctl status fastapi
Затем отправьте запрос к health endpoint: curl https://api.example.com/health
При нормальной работе API вернет: {"status":"ok"}
Как перезапустить FastAPI после изменения кода?
После обновления файлов приложения выполните: sudo systemctl restart fastapi
Если вместе с кодом изменилась структура базы данных, перед перезапуском следует применить подготовленные миграции: alembic upgrade head



