Files
infosave2007 057abaa95a feat!: API keys actually gate the gateway — auth, attribution, rate limits, budgets
The office-readiness audit found the foundation missing: configured API keys
were decorative. Any bearer — or none — passed every model endpoint, per-key
rate limits existed only in the form, and all real traffic was recorded as
"anonymous", leaving the per-key spend table permanently blank.

A middleware on the model surface (/v1/*, /route, /mcp) now enforces keys:
- no keys configured → open mode as before (the console already warns);
- keys exist → Bearer or x-api-key must match (401 invalid_api_key);
- per-key rate_per_min → fixed one-minute window, 429 with Retry-After;
- NEW per-key monthly_budget_usd → 429 insufficient_quota once the account's
  month-to-date spend crosses the ceiling;
- the matched account rides the request into stats — the keys table's spend
  columns finally see real traffic.

Month-to-date spend is tracked per account in stats and persisted in the
totals sidecar with a watermark (no double counting across restarts). The
key dialog gains a budget field; the table shows "budget $N/mo" in red once
exhausted. All verified live: 401 wrong/missing key, 200 + attribution with
the right key, 429 + Retry-After over the limit, 429 insufficient_quota on
the second request past a $0.000001 budget.

Also: the dashboard shows the OpenRouter credit balance (GET
/api/v1/credits via the stored key, cached 5 min, hidden without a key, red
under $5 — live: $16.18), the server drains connections on Ctrl-C instead
of dropping them, request bodies are capped at 32 MB, and docs/DEPLOY(.ru)
cover office deployment: systemd/launchd/Windows service, nginx/caddy TLS,
security checklist, backups. 10 strings ×7 languages.
2026-08-08 14:01:16 +03:00

4.6 KiB
Raw Permalink Blame History

Развёртывание cortiq-gateway для команды / офиса

Один шлюз на небольшом сервере, API-ключи по отделам, локальные модели для дешёвых уровней, облачные — для сложных. Эта страница про эксплуатацию.

1. Запуск как сервис

Linux (systemd)

# /etc/systemd/system/cortiq-gateway.service
[Unit]
Description=Cortiq Gateway
After=network-online.target

[Service]
User=cortiq
Environment=CORTIQ_GATEWAY_HOME=/var/lib/cortiq-gateway
ExecStart=/usr/local/bin/cortiq-gateway --no-port-search
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target
sudo systemctl enable --now cortiq-gateway

macOS (launchd)

<!-- ~/Library/LaunchAgents/com.cortiq.gateway.plist -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
  <key>Label</key><string>com.cortiq.gateway</string>
  <key>ProgramArguments</key><array>
    <string>/usr/local/bin/cortiq-gateway</string>
    <string>--no-port-search</string>
  </array>
  <key>RunAtLoad</key><true/>
  <key>KeepAlive</key><true/>
</dict></plist>
launchctl load ~/Library/LaunchAgents/com.cortiq.gateway.plist

Windows

Планировщик заданий → Создать задачу → «Выполнять вне зависимости от входа пользователя», триггер «При запуске», действие cortiq-gateway.exe --no-port-search. Либо NSSM: nssm install cortiq-gateway C:\bin\cortiq-gateway.exe.

Docker

docker run -d --restart unless-stopped -p 9000:9000 \
  -v cortiq-data:/data ghcr.io/infosave2007/cortiq-gateway:latest

2. TLS и внешний мир

Сам шлюз говорит по HTTP — поставьте перед ним reverse-proxy с TLS, а шлюз привяжите к localhost:

# gateway.toml
listen = "127.0.0.1:9000"
server {
    listen 443 ssl;
    server_name ai.example.com;
    ssl_certificate     /etc/letsencrypt/live/ai.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ai.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:9000;
        proxy_http_version 1.1;
        proxy_buffering off;          # SSE-стриминг
        proxy_read_timeout 3600s;     # долгие генерации
    }
}

(caddy reverse-proxy --from ai.example.com --to 127.0.0.1:9000 делает то же с автоматическими сертификатами.)

3. Чек-лист безопасности

  • Токен админки: задайте [admin] token (или CORTIQ_ADMIN_TOKEN) — без него консоль предупреждает, что открыта сети.
  • API-ключи: по ключу на отдел/разработчика на странице ключей. Как только настроен хотя бы один ключ, модельные API требуют Bearer / x-api-key — запросы без валидного ключа получают 401.
  • Rate-limit: запросов/мин на ключ → 429 с Retry-After.
  • Месячные бюджеты: потолок $ на ключ → 429 insufficient_quota, когда траты аккаунта за месяц превысят лимит.
  • Привязывайте к 127.0.0.1 за прокси; не выставляйте админку наружу голой.

4. Бэкапы

Всё живёт в data-директории (CORTIQ_GATEWAY_HOME):

  • gateway.toml — полный конфиг вкл. ключи (или TOML-экспорт из консоли);
  • secrets.toml — ключи провайдеров (chmod 600);
  • stats.jsonl + stats.jsonl.totals.json — учёт запросов вкл. вечные тоталы по ключам и месячные траты для бюджетов.

Скопируйте эти три файла — и инстанс поднимается где угодно.

5. Наблюдаемость

  • Рабочий стол: KPI, расходы по ключам, последние запросы с коэффициентами сложности, баланс OpenRouter (красный ниже $5).
  • GET /metrics (включите [telemetry] metrics = true) для Prometheus.
  • Просмотр логов в консоли; stats.max_file_mb ограничивает диск.