Оркестратор окружений и L7 reverse-proxy на базе Caddy для Docker, спроектированный для ИИ-агентов. Хостите сколько угодно сайтов и API на одном VPS: без конфликтов портов, с автоматическим Let's Encrypt SSL, строгой изоляцией секретов и hot-reload без даунтайма. Один декларативный контракт
pegas.jsonзаменяет docker-compose, Caddyfile и списки CORS-доменов.
Pegas — это L7-шлюз и оркестратор локальной инфраструктуры. Он заменяет всю инфраструктурную обвязку, которая обычно копится в репозитории:
| Что исчезает из репо | Чем заменяется |
|---|---|
docker-compose.yml |
манифест генерируется из pegas.json на каждый деплой (эфемерный, не хранится) |
Caddyfile, конфиги обратного прокси |
маршруты и TLS шлюз строит из domains контракта |
| Ручные списки CORS-доменов | пегас знает все домены проекта и сам настраивает заголовки (services.<name>.cors) |
| env «про топологию» (порты, адреса соседей, NODE_ENV) | вычисляется пегасом, код читает готовые значения через Runtime SDK |
pegas.json в корне репо — единственный источник истины о топологии.
Один легковесный Caddy-шлюз (pegas-gateway, ~30 МБ RAM) держит порты 80 и 443.
Все проекты работают в изолированной Docker-сети pegas-network со скоуп-алиасами
(<проект>-<сценарий>-<сервис>). Контейнерная статика (например, Caddyfile
для file_server внутри образа) — легитимна и не является конфигом шлюза.
flowchart TD
Client["Клиенты / Браузеры (HTTPS :443 / HTTP :80)"]
Gateway["Shared Gateway: pegas-gateway<br/>~30 МБ RAM · Auto Let's Encrypt · Caddy L7"]
subgraph Network["Docker Network: pegas-network"]
AppA["Проект A · development · web"]
AppB["Проект B · stage · api"]
end
Client -->|443 / 80| Gateway
Gateway -->|reverse_proxy| AppA
Gateway -->|reverse_proxy| AppB
- Zero Scalars: каждое поле, зависящее от среды, — строгая карта сценариев (
runtime,image,port,domainsи др.). Корневогоenv,secrets,role,deployнет. - Сценарии вместо окружений:
scenarios: ["development", "stage", "production"]— явный список; сценарий выбирается только флагом-sпри запуске. Ветвления по средам в коде запрещены. - Разделение команд:
pegas connect -s <scenario>объявляет маршруты всех сервисов сценария (host и docker),pegas deploy -s <scenario>поднимает только docker-сервисы и не пишет маршруты. - Анти-хайджекинг: деплой блокируется, если домен уже закреплён за другим проектом.
- Zero 502: шлюз переключает трафик на новый контейнер только после успешных healthcheck-проб.
- Zero Dependencies: чистый TypeScript для Bun/Node 24+, ноль сторонних npm-зависимостей.
bunx @netrunner714/pegas initinit — тонкий scaffolder: создаёт docs/pegas.md (правила для агентов),
блок Pegas в AGENTS.md, правит .gitignore (.env* + !.env.example + .pegas).
Контракт pegas.json не создаётся и не трогается — его пишет разработчик
или агент по схеме и эталону example.json.
scenarios — открытый список: имён может быть сколько угодно, имена произвольны (^[a-z0-9-]+$); три выше — конвенция, не ограничение. Каждая сценарная карта (runtime, port, domains…) обязана содержать ровно эти ключи.
Проверка: pegas check — рид-онли аудит (контракт, паритет секретов, git-гигиена, свежесть артефактов,
dev-конфигурация Next.js на доменах *.localhost).
pegas ca install # доверенный Root CA (один раз на машину)
pegas connect -s development # объявить маршруты всех сервисов сценария
pegas deploy -s development # поднять только docker-сервисы (БД, контейнеры)
bun run dev # host-сервисы (driver: "bun") — когда нужно
`connect` — единственный владелец route-файлов: он регистрирует и host-, и
docker-сервисы, не запуская процессы. `deploy` не трогает маршруты. Порты
внутри project-сети канонические (`db:5432`), поэтому один и тот же порт в
разных проектах не конфликтует.pegas connect -s production
pegas deploy -s production| Команда | Описание |
|---|---|
pegas init |
Сгенерировать/обновить артефакты пегаса в репо (docs/pegas.md, AGENTS-блок, .gitignore) |
pegas check |
Рид-онли аудит: контракт, секреты, git-гигиена, свежесть артефактов |
pegas connect -s <scenario> |
Объявить маршруты всех сервисов сценария в шлюзе |
pegas disconnect -s <scenario> |
Снять маршруты сценария |
pegas deploy -s <scenario> |
Поднять docker-сервисы сценария (без маршрутов) |
pegas down -s <scenario> |
Остановить контейнеры; маршруты connect сохраняются |
pegas logs -f [service] |
Логи контейнеров (Ctrl+C только отвязывает вывод) |
pegas status |
Дашборд шлюза: контейнеры, маршруты, домены |
pegas ca <install|remove> |
Доверенный локальный HTTPS: Root CA |
pegas update |
Обновить pegas (--latest для мажоров) |
Полный справочник флагов: docs/reference/cli.md (генерируется из кода).
Env — транспорт инъекции, а не источник знания о топологии.
| Слой | Где живёт значение | Как читает код |
|---|---|---|
| Топология (порт, домены, адреса соседей, сценарий) | pegas.json |
currentService(), services() из SDK — никогда process.env.PORT |
| Секреты | .env / CI-хранилище (инжектируются деплоем) |
secret("KEY") из SDK — с понятной ошибкой и списком ожидаемых |
| Несекретный app-конфиг | services.*.env контракта (инжектируется как env) |
прямой process.env.MY_KEY — разрешён, ключ задекларирован в контракте |
Запрещены в коде: PORT, APP_DOMAIN, CLIENT_ORIGINS, ветвления по NODE_ENV/похожим — всё это выводится платформой.
import { currentService, services, secret } from "@netrunner714/pegas/runtime";
const port = currentService().port; // порт из контракта
const api = services().api.internalUrl; // адрес соседнего сервиса (discovery)
const key = secret("DATABASE_URL"); // секрет с понятной ошибкойКонтекст инжектится в каждый контейнер переменной PEGAS_CONTEXT. Код не парсит
process.env и не ветвится по средам: сценарий выбирает запуск, код читает готовые значения.
В env-контракте значение "pegas://<имя-сервиса>" разворачивается при генерации манифеста
во внутренний адрес сети (<scheme>://<project>-<scenario>-<service>:<port>; scheme по образу
целевого image: redis/postgresql/http). Для статических образов без импорта SDK.
- Строгий JSON-режим:
--jsonу всех команд. - Никаких интерактивных зависаний: команды не задают вопросов.
- Строгие флаги: неизвестный флаг — ошибка со списком валидных.
- Контекст в одном файле:
pegas llmsи llms.txt — компактный полный контекст. - Аудит без мутаций:
pegas checkтолько читает; единственный мутатор в репо —pegas init.
| Раздел | Содержание |
|---|---|
| Быстрый старт | Пошагово от init до деплоя |
| Руководства | init, локальный HTTPS, Next.js |
| Справочники | CLI (генерируется), контракт |
| Архитектура | Устройство и обоснование решений |
| Контекст для агентов | Полный контекст для ИИ-ассистентов |
MIT © NETRUNNER714
{ "$schema": "https://pegas.netrunner714.ru/schemas/pegas.json", "projectName": "my-app", "scenarios": ["development", "stage", "production"], "gateway": { "development": { "httpPort": 80, "httpsPort": 443 }, "stage": { "httpPort": 80, "httpsPort": 443, "acmeEmail": "admin@example.com" }, "production": { "httpPort": 80, "httpsPort": 443, "acmeEmail": "admin@example.com" } }, "services": { // development: api — host-процесс (bun run dev), stage/production — docker "api": { "runtime": { "development": { "driver": "bun" }, "stage": { "driver": "docker" }, "production": { "driver": "docker" } }, "build": { "development": null, "stage": { "context": "." }, "production": { "context": "." } }, "port": { "development": 3000, "stage": 3000, "production": 3000 }, "domains": { "development": ["api.my-app.localhost"], "stage": ["api-stage.example.com"], "production": ["api.example.com"] }, "cors": { "development": true, "stage": true, "production": true }, "env": { "DATABASE_HOST": { "development": "localhost", "stage": "pegas://postgres", "production": "pegas://postgres" } }, "secrets": ["DATABASE_URL"] }, "postgres": { "runtime": { "development": { "driver": "docker" }, "stage": { "driver": "docker" }, "production": { "driver": "docker" } }, "image": { "development": "postgres:18-alpine", "stage": "postgres:18-alpine", "production": "postgres:18-alpine" }, "port": { "development": 5432, "stage": 5432, "production": 5432 }, "volumes": { "development": ["pgdata:/var/lib/postgresql"], "stage": ["pgdata:/var/lib/postgresql"], "production": ["pgdata:/var/lib/postgresql"] }, "secrets": ["DATABASE_URL"] } } }