
pacod-demo запускает идентификацию, AI-шлюз, платформу агентов, CMS, базу знаний и бенчмарки шлюза вместе на одной машине, из одного файла конфигурации и одной командой make. Он подключает compose-файл каждого репозитория без изменений, даёт им по одному экземпляру каждого общего компонента, знакомит продукты друг с другом и проверяет, что они работают как единое целое; каждую ночь он возвращается в известное состояние.
Весь стек
- Лицензия: No licence file yet
- Версия: 0.1.0 · Предварительная
- Языки: Shell, Python
- Технологии: Docker Compose, Caddy, PostgreSQL, Qdrant, Prometheus, Grafana, OpenTelemetry, Mailpit, Playwright
- Открыть на GitHub · Создать issue
- Попробовать живое демо
Возможности
Одна главная страница
Каждый продукт с описанием, скриншотом и ссылками на его администрирование и сайты, в дневной или ночной теме.
Один вход
Один realm pacod-id для всех продуктов. Вошли в один — вошли во все.
Один шлюз
Вызовы моделей всех продуктов идут через pacod-gw, у каждого свой ключ. Без ключа провайдера отвечает его mock-провайдер, и ничего не покидает машину.
Всего по одному
Один Caddy, один PostgreSQL, один Qdrant, один сервис эмбеддингов, один почтовый ящик для отправленных писем и один стек мониторинга, общие для всех продуктов.
Собственные файлы репозиториев
Шесть compose-файлов подключаются без изменений; небольшой overlay на репозиторий только задаёт адреса и секреты и убирает опубликованные порты.
Сброс каждую ночь
По умолчанию в 05:00 UTC данные всех продуктов возвращаются к базовому состоянию. Всё изменённое исчезает после ближайшего сброса.
Дашборды и почта
Grafana с дашбордами каждого продукта, Prometheus для ad-hoc запросов и просмотр каждого письма, которое отправляет стек.
Проверен как одна платформа
make verify проверяет точку входа, внутреннюю сеть, единый вход в пять продуктов, ключи шлюза у продуктов, базу знаний, сайты и бенчмарк.
Готов к домену
HTTPS с одним сертификатом на домен, его поддомены и домен сайтов; при публикации за пределы машины инструменты, безопасные только на ноутбуке, закрываются.

Скриншоты




Попробовать
Демо работает на demo.pacod.io, и его главная страница ведёт ко всему остальному: каждый продукт с описанием, скриншотом и ссылками на его администрирование и сайты. Каждый продукт отвечает на собственном поддомене, все за одной точкой входа:
| Адрес | Что |
|---|---|
demo.pacod.io |
Главная страница: каждый продукт со своими ссылками |
app.demo.pacod.io |
Платформа агентов (pacod-ap): её сайт, чат и консоль администратора |
console.demo.pacod.io |
Консоль шлюза (pacod-gw): провайдеры, модели, ключи, потребление |
gw.demo.pacod.io/v1 |
OpenAI-совместимый API шлюза, по ключу шлюза |
studio.demo.pacod.io |
Студия CMS (pacod-cms) |
cms.demo.pacod.io |
Demo Journal, сайт CMS; Demo Notes на minimal., Starward на space. |
kb.demo.pacod.io |
База знаний (pacod-kb) |
bench.demo.pacod.io |
Бенчмарки шлюза (pacod-benchmark): наборы, прогоны, сравнения |
id.demo.pacod.io/admin |
Администрирование идентификации (pacod-id) |
grafana.demo.pacod.io |
Дашборды всех продуктов |
mail.demo.pacod.io |
Каждое письмо, которое отправляет стек |
prometheus.demo.pacod.io |
Метрики, для ad-hoc запросов |
Один вход покрывает все продукты: вошли в один — вошли во все. Самостоятельной регистрации нет: учётные записи создаёт администратор или выдают по приглашению, а без учётной записи всем открыты сайты и публичные страницы продуктов. Grafana, Prometheus и просмотр почты вместо этого спрашивают email и пароль администратора. Любое изменение отменит ближайший ночной сброс.
Зачем он нужен
Каждый проект PACOD работает сам по себе, со своими копиями всего, что ему нужно: базы данных, точки входа, входа в систему, шлюза. Так его лучше всего пробовать по отдельности. Но вместе ими пользоваться задумано не так, и так не видно, что они дают в сумме.
pacod-demo устроен наоборот. Он ставит шесть продуктов на одну машину как одну платформу, с одним экземпляром каждого общего компонента, и показывает то, что появляется только при совместной работе: один вход, который признаёт каждый продукт, один шлюз, через который идёт каждый вызов модели и который их все тарифицирует, бенчмарк, который измеряет этот же шлюз, и один набор дашбордов для всего стека. Он же служит образцом того, как продукты собираются вместе: соглашению о сети и именах, на котором он держится, docs/NETWORK.md, следует каждый репозиторий.
Как он устроен
Стек — это один compose-проект, pacod-demo: 42 сервиса, два из которых выполняются один раз при
старте и останавливаются (43 с необязательным ingestion).
| Откуда | Что работает в демо | Имена |
|---|---|---|
| pacod-id | Провайдер идентификации, с одним realm для всех продуктов | pacod-id |
| pacod-gw | Ядро, аналитика, консоль, тестер, ClickHouse, Valkey кэша ответов, mock-провайдер, а также агент и мок нагрузки его нагрузочных тестов | pacod-gw, gw-* |
| pacod-ap | API, admin API, MCP-сервер, воркеры, фронтенд, Redis и pgbouncer, общий сервис эмбеддингов и экспортёры его мониторинга | ap-*, pacod-embeddings, экспортёры |
| pacod-cms | Сайты, студия, MongoDB и Gotenberg | cms-* |
| pacod-kb | Конвейер и интерфейс | kb-* |
| pacod-benchmark | API и интерфейс | bench-* |
| pacod-demo | Caddy, PostgreSQL, Qdrant, Mailpit, Prometheus, Alertmanager, Grafana и коллектор OpenTelemetry | pacod-* |
- Две сети, уникальные имена. Каждый контейнер подключается к внешней Docker-сети
pacod-netпод именем, уникальным во всех репозиториях: общие компоненты называютсяpacod-*, всё остальное несёт префикс владельца. Слушатели, до которых должны доходить только серверы, — API управления шлюза, внутренний слушатель pacod-id и API бенчмарка, — находятся во второй сети,pacod-admin-net, внутренней (без выхода наружу). Каждый привязан к псевдониму, который есть только там, и в неё входят только те, кто их вызывает. - Собственные compose-файлы репозиториев. Каждый репозиторий делит свою compose-настройку на
app-файл со своими сервисами и standalone-файл со своими копиями общих компонентов для
самостоятельного запуска.
compose.ymlподключает шесть app-файлов без изменений, вместе с файлами разработки и нагрузочных тестов шлюза. Небольшой overlay на репозиторий только убирает опубликованные порты, задаёт секреты и публичные адреса демо и направляет настройки на файлы демо. - По одному экземпляру каждого общего компонента.
platform.ymlне пишет ни одного с нуля: каждый расширяет (extends) определение, которое уже есть в каком-либо репозитории, и берёт вклад продуктов из их каталоговplatform/: блоки сайтов Caddy, скрипты баз данных, задания, правила и дашборды Prometheus. В PostgreSQL у каждого продукта своя база данных и своя роль владельца. - Собственные хранилища продуктов остаются при них: ClickHouse и Valkey шлюза, MongoDB (по одной базе на сайт) и Gotenberg у CMS, Redis и pgbouncer у платформы агентов.
- Сгенерированное состояние лежит в
.state/, которое git игнорирует: секреты, созданные один раз и никогда не меняющиеся, учётные данные, которые создаёт bootstrap, и переменные каждого продукта, сгенерированные изdemo.env.
Что делает make up
- Предварительная проверка. Docker и Compose 2.24 или новее, память и диск, шесть соседних репозиториев в раскладке с общей сетью, отсутствие другого стека pacod, занявшего общие имена, пароль администратора, сертификат и порты. Блокирующая проблема останавливает всё здесь.
- Сети и секреты. Создаёт
pacod-netи внутреннююpacod-admin-net, затем один раз генерирует каждый секрет в.state/secrets.env. Если секретов нет, а тома с данными есть, он отказывается, вместо того чтобы создать новые секреты, с которыми данные не смогут работать. - Генерация. Из
demo.envполучаются собственные переменные каждого продукта в.state/env/<product>.env. - Старт. Compose запускает проект и ждёт, пока каждый сервис не станет здоровым. Первый старт собирает каждый образ из исходников и скачивает модель эмбеддингов.
- Bootstrap. Он запускает собственные скрипты продуктов, bootstrap шлюза и идентификации из pacod-ap и provisioner из pacod-cms, чтобы создать ключи шлюза и служебные токены, по которым продукты обращаются друг к другу. Он также создаёт токен pacod-benchmark для API управления шлюза (администратор платформы: бенчмарк создаёт и удаляет собственную организацию для каждого прогона) и выдаёт администратору каждую недостающую роль. Сервисы, которые читают эти учётные данные, пересоздаются.
- Начальные данные. Таблицы платформы агентов, справочные факты стартового агента и его пользователи для разработки.
- Базовое состояние. На новом стеке он ждёт, пока CMS запишет три своих демо-сайта, и затем сохраняет данные как базовое состояние.
- Планировщик. Запускает контейнер ночного сброса, затем выводит адреса и пароль администратора.
Ночной сброс
Каждый день в DEMO_RESET_TIME (по умолчанию 05:00) в DEMO_RESET_TIMEZONE (по умолчанию
UTC) демо отменяет все изменения: учётные записи, агентов, статьи, документы, ключи и настройки.
Главная страница объявляет об этом в полосе под шапкой, со временем в часовом поясе посетителя и
сколько осталось до следующего сброса.
- Базовое состояние — это данные стека в один момент: то, что создал первый
make up, или то, что позже сохранилmake baseline. Оно включает каждый том с данными (PostgreSQL, MongoDB, Qdrant, ClickHouse, Redis, файлы базы знаний и приложения, Grafana, Alertmanager), файлы CMS и учётные данные bootstrap, в сжатом виде в Docker-томеpacod-demo-baseline. - Не входят: модели, метрики Prometheus, собственные данные точки входа и кэш ответов шлюза, который живёт в памяти: каждый сброс его очищает.
- Бенчмарки тоже откатываются: прогоны и расписания pacod-benchmark, шлюзы, добавленные в его интерфейсе, и отчёты, опубликованные в консоли шлюза. Отчёт, который хочется сохранить, скачивается со страницы его прогона; консоль принимает его обратно загрузкой.
- Как. Все сервисы, кроме точки входа, останавливаются, так что главная страница остаётся
доступной, пока продукты несколько минут отвечают 502. Базовое состояние копируется обратно, стек
запускается, и bootstrap выполняется снова, заодно применяя ключ провайдера, добавленный за это
время.
make resetделает то же самое сразу. - Планировщик — это контейнер
pacod-demo-reset, вне compose-проекта, потому что сброс останавливает проект. Он пропускает ночь, если стек не запущен или машина спала. ПустойDEMO_RESET_TIMEего выключает.
Конфигурация
Два файла. demo.env — это конфигурация: домены, стека и сайтов, порты, сертификат, email первого
администратора, время сброса, модели каждого продукта, бэкенд эмбеддингов, необязательный компонент
и логирование. Git его игнорирует; первый make копирует его из шаблона в репозитории,
demo.env.example, и останавливается, чтобы его можно было отредактировать. demo.local.env
хранит секреты машины, пароль администратора и ключи провайдеров LLM; git игнорирует и его, а то,
что в нём задано, имеет приоритет.
# demo.local.env
DEMO_ADMIN_PASSWORD=a-long-passphrase
ANTHROPIC_API_KEY=sk-...
Провайдеры LLM. Без ключа каждый вызов модели уходит к mock-провайдеру шлюза: демо работает
офлайн, и make verify детерминирован, но ответы в чате заготовлены заранее. Добавьте ключ (модели
платформы агентов по умолчанию — от Anthropic) и выполните make bootstrap, и шлюз настроится на
реального провайдера. AP_PRIMARY_MODEL, AP_CLASSIFIER_MODEL, CMS_AI_MODEL и KB_LLM_MODEL
выбирают модели, которые продукты запрашивают у шлюза.
Бэкенд эмбеддингов фиксируется при первом make up, потому что от него зависят сохранённые
векторы. По умолчанию, auto, он запускает BGE-M3, когда у Docker около 8 GB памяти, а меньше —
лёгкую замену; смена позже требует make clean.
Необязательный компонент ingestion запускает приём документов платформы агентов и загружает
базу знаний стартового агента; без него агент отвечает только по своим справочным фактам. Его образ
весит около 10 GB и может занять 7 GiB памяти, поэтому ему нужно 16 GiB для Docker.
Логи. Каждый продукт пишет логи в одном общем формате, по одному событию на строку с
одинаковыми ключами везде
(docs/LOGGING.md).
DEMO_LOG_LEVEL и DEMO_LOG_FORMAT (text или json) настраивают их все, а также журнал
запросов точки входа.
Демо-сайты CMS записываются только при первом старте студии. make cms-seed заполняет сайт без
статей, а make cms-space создаёт Starward в стеке, запущенном до его появления. Для Starward и
главной страницы в demo.env можно задать тег Google Analytics и подтверждение для Search Console;
если оставить их пустыми, как по умолчанию, на странице нет ничего от Google.
Безопасность
- Один опубликованный порт. Порты публикует только точка входа,
pacod-caddy; все остальные сервисы доступны только в Docker-сетях. Слушатели для серверов находятся во внутреннейpacod-admin-netи привязаны к псевдонимам, до которыхpacod-netне дотягивается. - Секреты. Каждый секрет генерируется один раз на машине и никогда не попадает в репозиторий. Пароль администратора должен быть не короче 12 символов (pacod-id отклоняет более короткий); если он пуст, генерируется пароль из 24 символов.
- Домен сайтов. Сайт CMS выполняет скрипт своего владельца, который на регистрируемом домене
студии мог бы устанавливать cookies, получаемые студией и входом. Поэтому сайты получают
собственный домен (
DEMO_SITE_DOMAIN); на домене студии студия отказывается запускаться.DEMO_SITE_DOMAIN_SHARED=trueразмещает их под доменом демо — для демо, все сайты которого доверенные, и только по HTTPS. demo.pacod.io так и делает: все его сайты — его собственные. - При публикации за пределы машины (
DEMO_BIND— не loopback-адрес) демо закрывает то, что безопасно только на ноутбуке: просмотр почты, Prometheus и Grafana спрашивают email и пароль администратора,/grafanaконсоли шлюза отвечает 403, главная страница не называет администратора, а токены разработки платформы агентов выключены. Собственное администрирование продуктов, как всегда, закрыто их входом. - Сертификаты предоставляются, а не получаются автоматически: один сертификат на домен, его поддомены и домен сайтов.
На домене или на ноутбуке
С заданными DEMO_TLS_CERT и DEMO_TLS_KEY стек отвечает по HTTPS, а обычный HTTP только
перенаправляет на него. В DNS домен, его wildcard и wildcard сайтов должны указывать на сервер; до
этого make hosts выводит строки для /etc/hosts, чтобы попробовать.
Шаблон в репозитории — это шаблон публичного сервера. Для демо только на одной машине в demo.env
нужны пять настроек:
DEMO_DOMAIN=localhost
DEMO_TLS_CERT=
DEMO_TLS_KEY=
DEMO_HTTP_PORT=8800
DEMO_BIND=127.0.0.1
Тогда всё работает по обычному HTTP на http://<name>.localhost:8800, что браузеры разрешают без
DNS (Safari может не справиться: возьмите другой браузер или make hosts).
Что ему нужно
- Docker с Compose 2.24 или новее и make. Всё остальное, от секретов до проверок, работает в контейнерах.
- Шесть репозиториев продуктов, склонированных рядом с этим.
- Около 8 GB памяти для Docker. Весь стек с настоящей моделью эмбеддингов занимал около 5 GiB при измерении, до того как к нему присоединился pacod-benchmark; бенчмарк с агентом и моком нагрузки шлюза добавляет в покое меньше 100 MiB. С лёгкой заменой — около 4 GiB.
- Около 30 GiB диска для образов. Первый
make upсобирает каждый образ из исходников: три Rust-workspace, одну сборку Maven, несколько образов Python и три приложения SvelteKit, — и занимает от 30 до 60 минут. Последующие запуски занимают около двух минут.
make down останавливает стек и сохраняет данные; make clean удаляет всё, что создало демо.
После получения новых версий make build пересобирает образы (make up собирает только
недостающие), а make reset и затем make baseline делают перенесённые данные новым базовым
состоянием.
Что проверено и где его пределы
make verify проверяет работающий стек от начала до конца и завершается с кодом 1, если что-то не
прошло:
| Часть | Что проверяется |
|---|---|
| Docker | По одному экземпляру каждого общего компонента, порт публикует только точка входа, ни один сервис не остановлен и не нездоров, pacod-admin-net внутренняя и в ней только те, кто вызывает слушателей |
| Точка входа и здоровье | Адрес и health-эндпоинт каждого продукта, каждая цель Prometheus доступна, правила и дашборды шлюза и приложения загружены |
| Единый вход | Администратор входит один раз и без повторного входа попадает в приложение, консоль шлюза, студию, базу знаний и бенчмарк, и у него есть каждая положенная роль |
| Шлюз | Ключи платформы агентов, CMS и базы знаний каждый выводят список моделей и завершают чат; повторный вызов получает ответ из кэша ответов |
| Продукты | Потоковый ход чата через шлюз (только на ноутбуке); документ, принятый, найденный и удалённый в базе знаний; Demo Journal отображается, а Starward — на наборе magazine |
| Бенчмарк | Его токен — администратор платформы шлюза, и шлюз принимает его отчёты |
Его пределы:
- Агент нагрузки бенчмарка работает на той же машине, что и шлюз: его цифры показывают, как ведёт себя шлюз, а не его пропускную способность.
- Цифры памяти измерены до того, как pacod-benchmark вошёл в стек.
- Сброс делает продукты недоступными на несколько минут, а планировщик пропускает ночь, когда машина спала.
- Без ключа провайдера каждый ответ — от мока; с ключом вызовы настоящие и стоят денег.
- Стеку, запущенному до появления Starward или с его прежней версией, нужен ручной шаг, чтобы его получить; README описывает его, вместе с полным списком настроек и таблицей решения проблем.
Быстрый старт
Склонируйте семь репозиториев рядом друг с другом
mkdir pacod && cd pacod
for r in pacod-demo pacod-id pacod-gw pacod-ap pacod-cms pacod-kb pacod-benchmark; do git clone https://github.com/pacod22/$r.git; done
Настройте его только для этой машины
cd pacod-demo
cp demo.env.example demo.env
printf '%s\n' DEMO_DOMAIN=localhost DEMO_TLS_CERT= DEMO_TLS_KEY= DEMO_HTTP_PORT=8800 DEMO_BIND=127.0.0.1 >> demo.env
Соберите, запустите и проверьте стек
make up
make verify
open http://localhost:8800
Работает с
- pacod-id: Единственный провайдер идентификации в стеке, с одним realm, через который входит каждый продукт; bootstrap даёт администратору роль каждого продукта.
- pacod-gw: Единственный шлюз в стеке, запущенный с включённым кэшем ответов; bootstrap даёт каждому продукту собственный ключ шлюза.
- pacod-ap: Запускает стартового агента, небольшую вымышленную службу поддержки, с его сайтом, чатом и консолью администратора.
- pacod-cms: Запускает студию с её AI-помощью при написании и три демо-сайта, Demo Journal, Demo Notes и Starward.
- pacod-kb: Запускает базу знаний на общих Qdrant, PostgreSQL и сервисе эмбеддингов.
- pacod-benchmark: Измеряет собственный шлюз стека с помощью агента нагрузки и мока шлюза; его отчёты видны в консоли шлюза.
В репозитории pacod-demo пока нет файла лицензии. У каждого продукта, который он запускает, своя лицензия, указанная в его репозитории и на его странице.