Files
drhider/History/infra/2026-08-21-vm-files-api-plan.md
T

4.9 KiB

ПЛАН: универсальный файловый сервис на ВМ (API)

Дата: 2026-08-21. Статус: РЕАЛИЗОВАНО И ЗАДЕПЛОЕНО (v1.0.0), см. README.md сервиса /home/naeel/nubes/vmfiles/ и 2026-08-21-vm-upload-implemented.md.

Цель

Один внутренний (НЕ публичный) сервис на ВМ 5.172.178.213 (contracts.kube5s.ru) для приёма/временного хранения/выдачи файлов. Потребители: drhider, contracts, SQS IoT. Заменяет сырой nginx-dav /drhider-upload/ на задокументированный, версионированный API, чтобы любому сервису было ясно, как им пользоваться.

Потребители и режимы

  • drhider — браузер (PUT файла) + сервер (pull). Нужен CORS для браузера.
  • contracts — сервер-к-серверу, много файлов из локали.
  • SQS IoT — сервер-к-серверу.

Технология

FastAPI + uvicorn (Python уже есть на ВМ). Почему FastAPI: автогенерация OpenAPI/Swagger (/docs) → «как юзать» видно из коробки; нативный streaming для больших тел.

API v1 (контракт)

Метод Путь Вход Ответ
POST /api/v1/files тело=файл (raw или multipart file), header X-App-Key 201 {"id","url","size","expires_at"}
GET /api/v1/files/{id} header X-App-Key байты файла
DELETE /api/v1/files/{id} header X-App-Key 204
GET /api/v1/health {"ok":true,"version":...}
GET /api/v1/docs Swagger UI (авто)

Единые ошибки: {"error": "...", "code": "unauthorized|not_found|too_large|expired|quota_exceeded"}.

Авторизация

Заголовок X-App-Key, по одному секрету на приложение. Ключи — в конфиге на ВМ (файл apps.yml/.env): drhider, contracts, sqs-iot. Без валидного ключа — 401.

Хранилище и метаданные

  • Файлы: /var/lib/vmfiles/ (или /var/www/vmfiles/, владелец — пользователь сервиса).
  • Метаданные: SQLite (id, app, name, size, created_at, expires_at).
  • id — серверный UUID (или клиентский токен — см. «открытые вопросы»).

Лимиты и TTL

  • max_file_size (по умолчанию 1024m) и quota на приложение.
  • TTL по умолчанию 30 мин (на приложение можно переопределить).
  • Чистка — встроенная фоновая задача сервиса (вместо текущего cron-find).

Деплой на ВМ

  1. Код сервиса — в отдельной папке на ВМ (или отдельный репозиторий).
  2. systemd-юнит vmfiles.serviceuvicorn app:app --host 127.0.0.1 --port 8769.
  3. nginx: новый location /api/v1/ { proxy_pass http://127.0.0.1:8769; ... }
    • proxy_request_buffering off (стримить большие тела) + client_max_body_size 1024m. CORS — отдать сервису (FastAPI), не nginx.
  4. Проверка: nginx -t → reload.

Миграция drhider

  • Пока сервис поднимается — /drhider-upload/ оставить как есть (не ломать текущее).
  • После готовности — перевести uploadFiles() и /api/upload_refs на /api/v1/files, убрать dav-location и cron-find.

Порядок работ

  1. Скелет FastAPI + health + /docs.
  2. POST/GET/DELETE /files + SQLite-метаданные + TTL-чистка.
  3. X-App-Key авторизация + квоты.
  4. systemd + nginx proxy_pass.
  5. Тесты: curl (raw + multipart), большие файлы, expiry, quota.
  6. Перевести drhider на новый API, выпилить старый dav.
  7. Документ-спека (README/API.md) + примеры для contracts/SQS.

Открытые вопросы (до «делай»)

  1. Язык: FastAPI (рекомендую) или Flask?
  2. id файла: сервер генерирует (POST) или клиент приносит токен (PUT)? Влияет на браузерный поток drhider.
  3. Загрузка: только raw-тело или поддерживать multipart тоже?
  4. Где живёт код сервиса — отдельный репозиторий на gitea или папка на ВМ?
  5. Ключи приложений — придумать сейчас или сервис сгенерирует при первом старте?