# Конфигурация проекта transmittal-api Документ описывает все переменные окружения и способы конфигурирования сервиса. ## Способы конфигурирования Сервис настраивается **только через переменные окружения**. Разбор выполняется в `src/transmittal_service/infra/settings.py` через библиотеку [`pydantic-settings`](https://docs.pydantic.dev/latest/concepts/pydantic_settings/) (класс `AppSettings`). Особенности разбора (`SettingsConfigDict`): - `env_prefix="TRANSMITTAL_SERVICE_"` — все переменные приложения начинаются с этого префикса; - `env_nested_delimiter="__"` — вложенные секции задаются двойным подчёркиванием, напр. `TRANSMITTAL_SERVICE_DATABASE__HOST` → `database.host`; - `env_ignore_empty=False` — пустая строка считается заданным значением (не игнорируется), поэтому пустое обязательное поле-строка проходит валидацию, а вот отсутствие обязательного поля приводит к ошибке старта. Отдельного конфиг-файла (yaml/toml) у приложения нет. Настройки Uvicorn читаются отдельным классом `UvicornSettings` (тот же префикс/делимитер). Источники переменных по способам запуска: | Способ запуска | Откуда берутся переменные | | --- | --- | | Локально (бинарник) | Переменные окружения процесса. `make config` копирует `.example.env` → `.env` как шаблон, но приложение **не загружает `.env` автоматически** (в коде нет `env_file`/`dotenv`) — файл нужно экспортировать самому, напр. `set -a && . ./.env && set +a` | | Локально (контейнеры) | `makefile`: цели `container-run`, `container-run-database`, `container-run-rabbitmq` пробрасывают переменные хоста через `--env` | | Kubernetes (Helm) | `.helm/values-.yaml`: блок `envs` (обычные значения) и `secrets` (значения из k8s-секретов); шаблоны `deployment.yaml`, `worker.yaml`, `crontab_periodic.yaml` | | CI/CD (GitLab) | `.gitlab-ci.yml`: переменные пайплайна (`workflow.rules`) и переменные job-а `test-unit` для запуска тестов | Способы запуска процессов (`[project.scripts]` в `pyproject.toml`): | Команда | Точка входа | Назначение | | --- | --- | --- | | `start_api` (`make run-api`) | `cmd/api.py` | HTTP API (uvicorn/gunicorn) | | `taskiq worker …` (`make run-worker`) | `tasks.broker:broker` | Обработчик фоновых задач | | `process_expired_transmittals` | `cmd/process_expired_transmittals.py` | Разовая задача обработки просроченных трансмитталов (в k8s — CronJob `0 3 * * *`) | | `create_system_values` | `cmd/create_system_values.py` | Создание системных значений | | `generate-act` | `cmd/generate_act.py` | Генерация акта | Порядок запуска в контейнере (`scripts/entrypoint.sh`): сначала выполняются миграции (`alembic upgrade heads`), затем стартует gunicorn с воркерами `ConfigurableWorker`. ## Переменные приложения Все перечисленные ниже переменные имеют префикс `TRANSMITTAL_SERVICE_`. В столбце «Переменная» указано полное имя. Дефолт `—` означает, что значение обязательно (иначе ошибка старта). ### App (`app.*`) | Переменная | Тип | Значение по умолчанию | Назначение | | --- | --- | --- | --- | | `TRANSMITTAL_SERVICE_APP__NAME` | string | `Transmittal Service` | Имя приложения | | `TRANSMITTAL_SERVICE_APP__LOG_LEVEL` | enum | `INFO` | Уровень логирования: `CRITICAL`/`FATAL`/`ERROR`/`WARNING`/`WARN`/`INFO`/`DEBUG`/`NOTSET` | | `TRANSMITTAL_SERVICE_APP__ENVIRONMENT` | enum | — | Окружение развёртывания: `stage`/`preprod`/`prod` | | `TRANSMITTAL_SERVICE_APP__HOST` | string | — | Внешний базовый URL сервиса (используется в письмах/ссылках) | ### Auth (`auth.*`) | Переменная | Тип | Значение по умолчанию | Назначение | | --- | --- | --- | --- | | `TRANSMITTAL_SERVICE_AUTH__PUBLIC_KEY` | string | — | Публичный RSA-ключ для проверки JWT. Экранированные `\n` автоматически заменяются на реальные переводы строк | ### CORS (`cors.*`) | Переменная | Тип | Значение по умолчанию | Назначение | | --- | --- | --- | --- | | `TRANSMITTAL_SERVICE_CORS__ALLOW_ORIGINS` | list[str] (JSON) | — | Разрешённые Origin, напр. `["*"]` | | `TRANSMITTAL_SERVICE_CORS__ALLOW_METHODS` | list[str] (JSON) | — | Разрешённые HTTP-методы | | `TRANSMITTAL_SERVICE_CORS__ALLOW_HEADERS` | list[str] (JSON) | — | Разрешённые заголовки | | `TRANSMITTAL_SERVICE_CORS__ALLOW_CREDENTIALS` | bool | — | Разрешить передачу учётных данных | ### Uvicorn (`uvicorn.*`) Читаются отдельным классом `UvicornSettings`. | Переменная | Тип | Значение по умолчанию | Назначение | | --- | --- | --- | --- | | `TRANSMITTAL_SERVICE_UVICORN__HOST` | string | `127.0.0.1` | Адрес прослушивания | | `TRANSMITTAL_SERVICE_UVICORN__PORT` | int | `8001` | Порт | | `TRANSMITTAL_SERVICE_UVICORN__ENABLE_AUTO_RELOAD` | bool | `False` | Live/hot-reload (для разработки) | | `TRANSMITTAL_SERVICE_UVICORN__LOG_LEVEL` | enum | `info` | `critical`/`error`/`warning`/`info`/`debug`/`trace` | | `TRANSMITTAL_SERVICE_UVICORN__NUM_WORKERS` | int | `1` | Число воркеров gunicorn | | `TRANSMITTAL_SERVICE_UVICORN__ROOT_PATH` | string | `""` | Root path (префикс за реверс-прокси) | ### Database (`database.*`) | Переменная | Тип | Значение по умолчанию | Назначение | | --- | --- | --- | --- | | `TRANSMITTAL_SERVICE_DATABASE__HOST` | string | — | Хост PostgreSQL | | `TRANSMITTAL_SERVICE_DATABASE__PORT` | int | — | Порт PostgreSQL | | `TRANSMITTAL_SERVICE_DATABASE__USER` | string | — | Пользователь БД | | `TRANSMITTAL_SERVICE_DATABASE__PASSWORD` | string | — | Пароль пользователя БД | | `TRANSMITTAL_SERVICE_DATABASE__NAME` | string | — | Имя базы данных | | `TRANSMITTAL_SERVICE_DATABASE__POOL_SIZE` | int | `5` | Размер пула соединений | | `TRANSMITTAL_SERVICE_DATABASE__MAX_POOL_OVERFLOW` | int | `5` | Доп. соединения сверх пула | | `TRANSMITTAL_SERVICE_DATABASE__ENABLE_SSL` | bool | — | Подключение к БД по TLS | | `TRANSMITTAL_SERVICE_DATABASE__SSL_MODE` | enum | — | `verify-full`/`verify-ca`/`""`. Обязателен при `ENABLE_SSL=true` | | `TRANSMITTAL_SERVICE_DATABASE__SSL_ROOT_CERT_PATH` | string | — | Путь к CA-сертификату. Обязателен при `ENABLE_SSL=true` | > При `ENABLE_SSL=true` валидатор требует непустые `SSL_MODE` и `SSL_ROOT_CERT_PATH`, иначе — ошибка старта. Итоговый DSN собирается в `database.uri`. ### RabbitMQ (`rabbitmq.*`) | Переменная | Тип | Значение по умолчанию | Назначение | | --- | --- | --- | --- | | `TRANSMITTAL_SERVICE_RABBITMQ__USER` | string | — | Пользователь | | `TRANSMITTAL_SERVICE_RABBITMQ__PASSWORD` | string | — | Пароль | | `TRANSMITTAL_SERVICE_RABBITMQ__VHOST` | string | — | Виртуальный хост | | `TRANSMITTAL_SERVICE_RABBITMQ__HOST` | string | — | Хост | | `TRANSMITTAL_SERVICE_RABBITMQ__PORT` | int | — | Порт | ### HTTP-клиенты внешних сервисов Все клиенты наследуют общий набор полей (`HttpClient`): `BASE_URL`, `MAX_CONNECTIONS`, `MAX_KEEPALIVE_CONNECTIONS`, `TIMEOUT`. Все четыре поля обязательны (дефолтов нет). | Секция / префикс | Назначение | Доп. поля | | --- | --- | --- | | `TRANSMITTAL_SERVICE_SAREX_BACKEND_REPOSITORY__*` | Основной backend Sarex | `BASIC_AUTH_ENCODED` — base64 от `login:password` (обязателен), декодируется в пару login/password | | `TRANSMITTAL_SERVICE_RESOURCE_REPOSITORY__*` | Сервис ресурсов (IAM/resources) | — | | `TRANSMITTAL_SERVICE_DOCUMENTATIONS_REPOSITORY__*` | Сервис документаций | — | | `TRANSMITTAL_SERVICE_FLOWS_REPOSITORY__*` | Сервис flows | — | | `TRANSMITTAL_SERVICE_HTML_TO_PDF_CONVERTER__*` | Конвертер HTML→PDF (export-project) | — | | `TRANSMITTAL_SERVICE_MARKINGS__*` | Сервис PDF-маркировок | — | Для каждого — четыре переменные, напр. для markings: | Переменная | Тип | Назначение | | --- | --- | --- | | `TRANSMITTAL_SERVICE_MARKINGS__BASE_URL` | string | Базовый URL сервиса | | `TRANSMITTAL_SERVICE_MARKINGS__MAX_CONNECTIONS` | int | Макс. число соединений | | `TRANSMITTAL_SERVICE_MARKINGS__MAX_KEEPALIVE_CONNECTIONS` | int | Макс. keep-alive соединений | | `TRANSMITTAL_SERVICE_MARKINGS__TIMEOUT` | int | Таймаут запроса (сек) | Для `SAREX_BACKEND_REPOSITORY` дополнительно: | Переменная | Тип | Назначение | | --- | --- | --- | | `TRANSMITTAL_SERVICE_SAREX_BACKEND_REPOSITORY__BASIC_AUTH_ENCODED` | string (base64) | Basic-auth в виде base64(`login:password`) | ### S3 (`s3_client.*`) | Переменная | Тип | Значение по умолчанию | Назначение | | --- | --- | --- | --- | | `TRANSMITTAL_SERVICE_S3_CLIENT__ENDPOINT` | string | — | Эндпоинт S3. Если без `http(s)://` — префикс добавляется автоматически по `USE_SSL` | | `TRANSMITTAL_SERVICE_S3_CLIENT__REGION_NAME` | string | — | Регион | | `TRANSMITTAL_SERVICE_S3_CLIENT__DEFAULT_BUCKET` | string | — | Бакет по умолчанию | | `TRANSMITTAL_SERVICE_S3_CLIENT__ACCESS_KEY` | string | — | Access key | | `TRANSMITTAL_SERVICE_S3_CLIENT__SECRET_KEY` | string | — | Secret key | | `TRANSMITTAL_SERVICE_S3_CLIENT__USE_SSL` | bool | — | Использовать SSL | | `TRANSMITTAL_SERVICE_S3_CLIENT__VERIFY` | bool | — | Проверять TLS-сертификат | | `TRANSMITTAL_SERVICE_S3_CLIENT__MAX_POOL_CONNECTIONS` | int | `10` | Размер пула соединений | | `TRANSMITTAL_SERVICE_S3_CLIENT__CONNECT_TIMEOUT` | int | `10` | Таймаут подключения (сек) | | `TRANSMITTAL_SERVICE_S3_CLIENT__READ_TIMEOUT` | int | `30` | Таймаут чтения (сек) | | `TRANSMITTAL_SERVICE_S3_CLIENT__USE_PATH_STYLE` | bool | `True` | Path-style адресация | | `TRANSMITTAL_SERVICE_S3_CLIENT__REQUEST_CHECKSUM_CALCULATION` | enum | `when_required` | `when_supported`/`when_required` | | `TRANSMITTAL_SERVICE_S3_CLIENT__RESPONSE_CHECKSUM_VALIDATION` | enum | `when_required` | `when_supported`/`when_required` | ### Почта: Mailgun или SMTP Должен быть настроен **ровно один** из двух сервисов (валидатор `check_mailing_service`), иначе — ошибка старта. По умолчанию используется Mailgun. Mailgun (`mailgun.*`) — наследует поля `HttpClient` плюс: | Переменная | Тип | Значение по умолчанию | Назначение | | --- | --- | --- | --- | | `TRANSMITTAL_SERVICE_MAILGUN__BASE_URL` | string | — | URL API, напр. `https://api.mailgun.net/v3/` | | `TRANSMITTAL_SERVICE_MAILGUN__MAX_CONNECTIONS` | int | — | Макс. соединений | | `TRANSMITTAL_SERVICE_MAILGUN__MAX_KEEPALIVE_CONNECTIONS` | int | — | Макс. keep-alive | | `TRANSMITTAL_SERVICE_MAILGUN__TIMEOUT` | int | — | Таймаут (сек) | | `TRANSMITTAL_SERVICE_MAILGUN__EMAIL` | string | — | Адрес отправителя | | `TRANSMITTAL_SERVICE_MAILGUN__API_KEY` | string | — | API-ключ Mailgun | SMTP (`smtp.*`) — альтернатива Mailgun: | Переменная | Тип | Значение по умолчанию | Назначение | | --- | --- | --- | --- | | `TRANSMITTAL_SERVICE_SMTP__HOST` | string | — | SMTP-хост | | `TRANSMITTAL_SERVICE_SMTP__PORT` | int | — | SMTP-порт | | `TRANSMITTAL_SERVICE_SMTP__EMAIL` | string | — | Адрес отправителя | | `TRANSMITTAL_SERVICE_SMTP__ENABLE_TLS` | bool | `False` | Включить TLS | | `TRANSMITTAL_SERVICE_SMTP__LOGIN` | string \| null | `None` | Логин | | `TRANSMITTAL_SERVICE_SMTP__PASSWORD` | string \| null | `None` | Пароль | ### OpenTelemetry (`otel.*`) | Переменная | Тип | Значение по умолчанию | Назначение | | --- | --- | --- | --- | | `TRANSMITTAL_SERVICE_OTEL__ENABLE` | bool | `False` | Включить трейсинг | | `TRANSMITTAL_SERVICE_OTEL__HOST` | string | — | Адрес OTLP-коллектора | | `TRANSMITTAL_SERVICE_OTEL__SERVICE_NAME` | string | — | Имя сервиса в трейсах | | `TRANSMITTAL_SERVICE_OTEL__INSECURE` | bool | `False` | Небезопасное (без TLS) подключение к коллектору | ## Переменные инфраструктуры, сборки и вспомогательных утилит Не читаются кодом приложения, но участвуют в запуске/сборке/деплое. | Переменная | Где используется | Назначение | | --- | --- | --- | | `TRANSMITTAL_SERVICE_PGDATA` | `.example.env` (закомментировано) | Каталог данных локального PostgreSQL | | `TRANSMITTAL_SERVICE_PGHOST` | `.example.env` (закомментировано) | Хост локального PostgreSQL | | `TRANSMITTAL_SERVICE_PGPORT` | `makefile` (`container-run-database`) | Внутренний порт контейнера Postgres при пробросе | | `OCI` | `makefile` | Инструмент контейнеризации (`docker`/`podman`), по умолчанию `docker` | | `TRANSMITTAL_SERVICE_IMAGE_NAME` / `TRANSMITTAL_SERVICE_IMAGE_VERSION` | `makefile` | Имя/тег собираемого образа | | `TRANSMITTAL_SERVICE_CONTAINER__NETWORK_NAME` | `makefile` | Имя docker-сети | | `TRANSMITTAL_SERVICE_DATABASE_CONTAINER__*` | `makefile` | Параметры контейнера Postgres (образ, имя, volume) | | `TRANSMITTAL_SERVICE_RABBITMQ_CONATINER__*` | `makefile` | Параметры контейнера RabbitMQ | | `PIP_INDEX_URL`, `PIP_TRUSTED_HOST` | `Dockerfile` (build-arg) | Приватный индекс пакетов при сборке | | `TRANSMITTAL_SERVICE_PYTHON_IMAGE_NAME`, `TRANSMITTAL_SERVICE_PYTHON_IMAGE_TAG` | `Dockerfile` (build-arg) | Базовый образ Python (по умолчанию `python:3.12-slim`) | | `UID`, `GID`, `USERNAME` | `Dockerfile` (build-arg) | Пользователь внутри образа (по умолчанию `10000`/`10001`/`transmittal_service`) | ## Переменные из Helm-чарта (`.helm/values-.yaml`) Обычные значения задаются в блоке `envs` для каждого окружения (`stage`/`preprod`/`production`) и содержат те же переменные приложения `TRANSMITTAL_SERVICE_*`, что описаны выше (различаются адресами БД/сервисов, портами, `LOG_LEVEL`, `ROOT_PATH`, бакетом, доменом Mailgun и т.п.). Значения из секретов (блок `secrets`, монтируются как env через `secretKeyRef`): | Переменная | Секрет (`secret_name`) | Ключ (`secret_key`) | | --- | --- | --- | | `TRANSMITTAL_SERVICE_DATABASE__USER` | `ya-pg-secret` | `username` | | `TRANSMITTAL_SERVICE_DATABASE__PASSWORD` | `ya-pg-secret` | `password` | | `YC-PG-CERTIFICATE` | `ya-pg-secret` | `certificate` | | `TRANSMITTAL_SERVICE_AUTH__PUBLIC_KEY` | `public-key` | `key` | | `TRANSMITTAL_SERVICE_SAREX_BACKEND_REPOSITORY__BASIC_AUTH_ENCODED` | `django-auth` | `key` | | `TRANSMITTAL_SERVICE_S3_CLIENT__ACCESS_KEY` | `s3-secret` | `access_key` | | `TRANSMITTAL_SERVICE_S3_CLIENT__SECRET_KEY` | `s3-secret` | `secret_key` | | `TRANSMITTAL_SERVICE_RABBITMQ__USER` | `rabbitmq-cred` | `username` | | `TRANSMITTAL_SERVICE_RABBITMQ__PASSWORD` | `rabbitmq-cred` | `password` | | `TRANSMITTAL_SERVICE_MAILGUN__API_KEY` | `mailgun-cred` | `api_key` | Помимо env, чарт монтирует CA-сертификат PostgreSQL из секрета `ya-pg-secret` (ключ `certificate`) как файл `/opt/.postgresql/root.crt` — именно на него указывает `TRANSMITTAL_SERVICE_DATABASE__SSL_ROOT_CERT_PATH` в prod-конфигурации. Прочие значения чарта (не переменные приложения): `deployment.*` (имя, образ, порт, реплики, ресурсы), `api.*` (host/prefix/path ingress), `worker.*`, `job.name_periodic`, `imagePullSecrets`. ## Переменные в CI (`.gitlab-ci.yml`) Пайплайн подключает общие шаблоны из `generic/common-ci` и переключает окружение по ветке/тегу через `workflow.rules`: | Условие | STAND | Namespace | | --- | --- | --- | | ветка `master` | `preprod` | `transmittal-api-preprod` | | ветка `stage` | `stage` | `transmittal-api-stage` | | тег (`CI_COMMIT_TAG`) | `prod` | `transmittal-api-prod` | Ключевые переменные пайплайна: `RELEASE_NAME`, `CHART_NAME`, `CHART_VERSION`, `DOCKERFILE_PATH`, `HELM_SET_ARGS` (`--set deployment.image=…`), флаги `ENABLE_LINTER`/`ENABLE_BUILD_CHART`/`ENABLE_BUILD_IMAGE`/`ENABLE_DEPLOY`. Job `test-unit` задаёт полный набор `TRANSMITTAL_SERVICE_*` переменных для прогона юнит-тестов. ## Замечания и потенциальные проблемы - Переменные БД в `.example.env` должны иметь префикс `TRANSMITTAL_SERVICE_DATABASE__*` — код читает их именно так. Ранее в файле они были записаны без префикса (`DATABASE__USER` и т.д.) и не подхватывались; сейчас исправлено. В `makefile`, `.gitlab-ci.yml` и Helm имена с префиксом корректны. - Приложение **не загружает `.env` автоматически** (в `settings.py` не задан `env_file`, зависимости `python-dotenv` нет). `make config` лишь создаёт файл-шаблон; переменные нужно экспортировать в окружение вручную либо задавать через `--env` (см. `make container-run`). - `env_ignore_empty=False`: пустая строка воспринимается как заданное значение. Например `TRANSMITTAL_SERVICE_AUTH__PUBLIC_KEY=''` — валидное (пустой ключ), а вот полностью отсутствующая обязательная переменная вызовет ошибку старта. - Переменная `YC-PG-CERTIFICATE` прокидывается из секрета в окружение, но **кодом приложения не читается** — сертификат используется как смонтированный файл (`root.crt`). Имя с дефисами не соответствует схеме `TRANSMITTAL_SERVICE_*`. - Почтовый сервис: должен быть задан ровно один из `mailgun`/`smtp`. Если заданы оба или ни одного — сервис не стартует. - В `.example.env` секция `FLOWS_REPOSITORY__BASE_URL` пустая, но поле обязательно — для реального запуска его нужно заполнить. ## Минимальный набор для локального запуска Postgres и RabbitMQ поднимаются через `make container-deps`, приложение — через `make run-api` / `make run-worker`. Минимально необходимо задать (с префиксом `TRANSMITTAL_SERVICE_`): - `APP__ENVIRONMENT`, `APP__HOST` - `AUTH__PUBLIC_KEY` (можно пустой для локальной разработки) - `CORS__ALLOW_ORIGINS`, `CORS__ALLOW_METHODS`, `CORS__ALLOW_HEADERS`, `CORS__ALLOW_CREDENTIALS` - `DATABASE__HOST`, `DATABASE__PORT`, `DATABASE__USER`, `DATABASE__PASSWORD`, `DATABASE__NAME`, `DATABASE__ENABLE_SSL` (`false` локально), `DATABASE__SSL_MODE`, `DATABASE__SSL_ROOT_CERT_PATH` - `RABBITMQ__USER`, `RABBITMQ__PASSWORD`, `RABBITMQ__VHOST`, `RABBITMQ__HOST`, `RABBITMQ__PORT` - `BASE_URL`/`MAX_CONNECTIONS`/`MAX_KEEPALIVE_CONNECTIONS`/`TIMEOUT` для всех шести HTTP-клиентов (`SAREX_BACKEND_REPOSITORY` + `BASIC_AUTH_ENCODED`, `RESOURCE_REPOSITORY`, `DOCUMENTATIONS_REPOSITORY`, `FLOWS_REPOSITORY`, `HTML_TO_PDF_CONVERTER`, `MARKINGS`) - `S3_CLIENT__*` (эндпоинт, регион, бакет, ключи, `USE_SSL`, `VERIFY`) - один из почтовых сервисов: `MAILGUN__*` **или** `SMTP__*` - `OTEL__ENABLE` (`False` локально), при `True` — `OTEL__HOST`, `OTEL__SERVICE_NAME` Готовые значения-примеры для всех переменных приведены в `.example.env` (с учётом замечаний выше по префиксу БД).