Colloq в вузе ставят двумя способами — выберите тот, что подходит вашей инфраструктуре.
В вашем Kubernetes
Helm-чарт в одно пространство имён: без прав администратора кластера, под Pod Security restricted, с вашим реестром, хранилищем, ingress и секретами из Vault. Для организаций, где кластер ведёт платформенная команда.
B / ОДНА МАШИНАНа одной VM
Готовый образ и colloq-host на выделенной Linux-машине за обратным прокси вуза. Об этом — вся страница ниже.
Кратко для ИТ-службы
| Что это | Colloq — совместные тетради Jupyter для занятий: веб-приложение и отдельный контейнер с ядром Python для каждой комнаты. Открытый код, лицензия MIT. |
|---|---|
| Машина | Одна выделенная VM x86-64 с Ubuntu 22.04 или 24.04 и Docker Engine 28 или новее. Приложение управляет Docker, а это права root на VM, поэтому других служб на ней не держите. |
| Ресурсы | Для начала 16 vCPU, 64 ГБ памяти, 250 ГБ NVMe, без GPU. Этого хватает на группу из 30 человек с личными тетрадями или с соревнованием и на лекцию на 100 человек; расчёт — в разделе «Машина и ресурсы». |
| Входящие | Только HTTPS от браузеров пользователей к вашему обратному прокси; прокси обращается к приложению по 127.0.0.1:3000. Если пользователи в сети вуза или в VPN, из интернета не нужно ничего. |
| Исходящие | Во время работы основным функциям не нужно ничего: нет ни телеметрии, ни проверки обновлений, ни CDN. Для установки и обновления нужен ghcr.io — или ваше зеркало реестра, или перенос образов файлом. По желанию: модель ИИ (OpenAI или своя внутри сети), импорт тетрадей с GitHub, PyPI или внутреннее зеркало для пакетов соревнований, интернет для кода студентов. |
| Данные | Всё на этой VM в /workspace/colloq: база SQLite, файлы комнат, данные соревнований, резервные копии. Настройки — в /etc/colloq/colloq.env. |
| Резервные копии | colloq-host backup вручную или colloq-host backup-timer on — каждую ночь. Уносить копии с машины нужно вашими средствами. |
Как это устроено
Обратный прокси вуза принимает HTTPS и передаёт запросы приложению. Приложение — один контейнер colloq из образа ghcr.io/colloq-edu/colloq-server: сервер на Node.js, собранный веб-интерфейс и база SQLite. Его порт 3000 опубликован только на 127.0.0.1 этой VM. Запускает и обновляет контейнер colloq-host — небольшой скрипт на хосте, который ставится из того же образа.
Для каждой комнаты приложение запускает на том же Docker свой контейнер с ядром Jupyter: свои пределы памяти, процессора и числа процессов, смонтирована только папка этой комнаты, uid 1000, без Linux capabilities. Личные тетради студентов считаются во втором контейнере занятия, посылка соревнования — в двух одноразовых контейнерах без сети. Приложение и ядра комнат делят сеть Docker colloq.
Каталог состояния — /workspace/colloq: data/ (база и ключи), workspace/<комната>/ (файлы комнат), environments/ (окружения, созданные в панели), backups/. Он смонтирован в контейнер по тому же пути. Настройки лежат в /etc/colloq/colloq.env (права 0600), выбранный образ — в /etc/colloq/image. Подключите под /workspace/colloq отдельный диск или раздел: тогда переполнение не заденет систему.
Машина и ресурсы
Отправная точка: 16 vCPU, 64 ГБ памяти, 250 ГБ NVMe, x86-64 (образ собирается только для amd64), Ubuntu 22.04 или 24.04, Docker Engine 28 или новее, GPU не нужен. Часы машины должны синхронизироваться по NTP (без интернета — с внутренним сервером): от времени зависят ссылки входа, cookies и сертификаты. Docker должен сам управлять iptables: сетевой запрет комнат встаёт в его цепочку DOCKER-USER, поэтому не подходят "iptables": false в daemon.json и nftables-бэкенд Docker 29. Память и процессор машины уходят на ядра комнат и посылки; цифры для них ниже выведены из пределов в коде. Само приложение лёгкое, это замерено.
| Сценарий | vCPU | Память | Диск |
|---|---|---|---|
| (a) 30 студентов, одна общая тетрадь | 4 | 8 ГБ | 60 ГБ |
| (b) 30 студентов, у каждого личная тетрадь | 16 | 64 ГБ (не меньше 48 ГБ) | 100 ГБ |
| (c) 30 студентов и соревнование, посылка 2 ядра / 2 ГБ | 16 (авто даёт 7 слотов) | 32 ГБ | 100 ГБ |
| (d) три занятия как (c) в один час | 32 (около 15 слотов) | 64 ГБ; 160–192 ГБ, если у всех трёх личные тетради | 200 ГБ |
| (e) 100 человек в лекционной комнате | 4 (8, если студенты запускают ячейки) | 8 ГБ | 60 ГБ |
Отправная точка покрывает (a), (b), (c) и (e), а (d) — с более медленной очередью посылок. Предположения: pandas и scikit-learn с настройками по умолчанию, посылка идёт около двух минут.
Замер приложения (30.09.2026, VM 21 vCPU / 49 ГБ, nginx перед приложением, make load): 500 человек вошли в одну комнату за минуту без единого отказа, вход — 7 мс в середине распределения. Процесс приложения держал 243 МБ памяти и 20 % одного ядра в покое и 50 % ядра, когда двадцать человек печатали одновременно; правка доходила до остальных за 0,17 с (p95). На 300 человек — 198 МБ и те же доли ядра.
Память считайте так: около 3 ГБ на систему и приложение + пределы комнат (4 ГБ на комнату по умолчанию) + пределы контейнеров личных тетрадей + слоты × (память посылки + 0,25 ГБ) + 1,6 ГБ на время подготовки пакетов. Docker ничего не резервирует, поэтому Colloq сам не запустит ядро, если его предел вместе с пределами уже работающих контейнеров не помещается в память машины за вычетом 1 ГБ. Процессор делится, а не резервируется: у комнаты потолок в 2 ядра.
- Личные тетради: около 1–1,5 ГБ и 0,25 ядра на студента. Все личные тетради занятия живут в одном контейнере и по умолчанию получают на всех столько же, сколько комната, — 4 ГБ. Для группы поднимите «Память на класс» в панели: «Ресурсы» → «Личные тетради студентов» (или в правилах конкретного занятия).
- Соревнования: сколько посылок идёт одновременно («Исполнителей одновременно» во вкладке «Ресурсы»), по умолчанию считается само: меньшее из (ядра − 2) / ядра посылки и (память − 2 ГБ) / (память посылки + 0,25 ГБ), но не больше 32. 30 посылок по две минуты проходят примерно за 9 минут на 7 слотах и примерно за 20 минут на 3 слотах (машина 8 vCPU / 16 ГБ).
- Комната держит память, пока в ней кто-то есть, и ещё 2 часа после того, как все ушли: конец пары ядро не останавливает. Поэтому занятия подряд накладываются друг на друга.
- Диск: образ kaggle-base занимает около 1 ГБ, base-gpu — около 9 ГБ; дальше растут файлы комнат, посылки соревнований и резервные копии. Страницы занятий держат свои копии опубликованных тетрадей и файлов в
data/page-files/: около 0,3–0,8 ГБ на курс из 33 занятий, одинаковый файл в разных страницах хранится один раз. Квоты на комнату нет, см. наблюдение. - GPU необязателен. Он нужен только окружениям с GPU (base-gpu): по одной карте, 16 ГБ памяти и около 10 ГБ диска на каждую одновременно работающую GPU-комнату, плюс драйвер NVIDIA и NVIDIA Container Toolkit (
colloq-hostставит его сам через apt). Личные тетради и посылки соревнований GPU не получают никогда.
Во вкладке «Ресурсы» есть шкала памяти: работающие комнаты, личные тетради и слоты соревнований против памяти машины за вычетом 1 ГБ; если памяти не хватает, шкала так и пишет. Там же показан свободный диск раздела с данными, с предупреждением, когда свободно меньше 15 % или 10 ГБ; GPU шкала не показывает.
Входящие и исходящие соединения
Входящие соединения:
| Откуда и куда | Порт | Зачем |
|---|---|---|
| Браузеры пользователей → обратный прокси | 443/TCP; 80 — только для перенаправления на HTTPS | Всё приложение: страницы, API, WebSocket, server-sent events. |
| Обратный прокси → приложение | 127.0.0.1:3000, если прокси на этой же VM; иначе внутренний адрес VM, порт 3000 (COLLOQ_BIND) | HTTP без TLS внутри машины или доверенного сегмента. |
| Администраторы → VM | 22/TCP | SSH и colloq-host; только из сети ИТ-службы. |
| Интернет → VM | — | Не нужен, если пользователи в сети вуза или в VPN. Порты 80/443 из интернета нужны, только если прокси сам получает сертификат Let's Encrypt. |
Jupyter ядер и остальные служебные порты не публикуются: они живут внутри сети Docker. Сторонних обращений нет: шрифты, просмотрщик PDF и plotly приложение отдаёт само, и браузеры обращаются только к адресу Colloq.
Исходящие соединения:
| Куда | Зачем и когда | Нужно | Можно ли заменить |
|---|---|---|---|
ghcr.io, pkg-containers.githubusercontent.com | Образ приложения colloq-server и образы ядер colloq-kernel: установка и обновление | Да, если не переносить образы файлом | Да: зеркало реестра в COLLOQ_IMAGE и KERNEL_IMAGE_REPO; без сети — перенос файлом |
get.docker.com, download.docker.com | Установка Docker, если его нет на машине | Нет, если Docker уже стоит | Ставьте Docker из своего репозитория |
Docker Hub (registry-1.docker.io, auth.docker.io, production.cloudflare.docker.com), deb.debian.org, pypi.org, files.pythonhosted.org | Сборка образа ядра на месте: окружение из панели или опубликованный образ, который не удалось скачать | Нет | Частично: строки --index-url в списке пакетов окружения; готовые образы ядер из реестра |
nvidia.github.io | NVIDIA Container Toolkit при первой установке на машине с GPU | Только для GPU | Поставьте пакет заранее |
Модель ИИ, по умолчанию api.openai.com | Оракул — когда его спрашивают | Нет | Да: OPENAI_BASE_URL или панель — Ollama, vLLM или другой совместимый с OpenAI адрес внутри сети |
api.github.com, raw.githubusercontent.com | Импорт тетради с GitHub в панели — по кнопке | Нет | Нет, только github.com |
pypi.org, files.pythonhosted.org | «Свои пакеты» участников соревнований — при подготовке набора | Нет | Да: DEPENDENCY_INDEX_URL, DEPENDENCY_FILES_HOSTS |
| Интернет из ядер комнат | pip install, датасеты и API в коде студентов — во время занятия | Нет | Можно отключить: COLLOQ_ROOM_NETWORK=none, см. ниже |
Сеть для кода студентов
- Посылки соревнований исполняются вовсе без сети.
- Комнаты и личные тетради по умолчанию выходят в интернет (
pip install, датасеты, API), а частные адреса для них закрыты: 10/8, 172.16/12, 192.168/16, 100.64/10, 169.254/16 с метаданными облака, 127/8, multicast, сама VM и соседние комнаты. Соединение туда сразу получает отказ; открытым для любого адреса остаётся только DNS, порт 53. Правила ставит само приложение — в собственные цепочки iptablesCOLLOQ-ROOMS-*, в которые ведутDOCKER-USERиINPUT. Если поставить их не удалось, комнаты не запускаются. - Публичные диапазоны вуза. Код студентов выходит в сеть с адреса VM, и службы, которые доверяют адресам вуза (подписки библиотеки, внутренние сайты на публичных адресах), примут его за своего. Перечислите такие диапазоны:
KERNEL_BLOCKED_CIDRS=192.0.2.0/24,198.51.100.0/24. COLLOQ_ROOM_NETWORK=none— у ядер комнат и личных тетрадей совсем нет исходящей сети, до них доходит только сервер Colloq.pip installв ячейке тогда не работает: нужные библиотеки заранее кладите в окружение (панель → «Окружения»).COLLOQ_ROOM_NETWORK=openснимает запрет частных адресов — только для доверенных групп, которым нужна локальная сеть.
Исходящий прокси, внутренний CA и зеркало PyPI
Если наружу можно выйти только через прокси, задайте HTTPS_PROXY, HTTP_PROXY и NO_PROXY (понимаются и в нижнем регистре). Через прокси идут все исходящие HTTP-запросы сервера — к модели ИИ и к GitHub, — и те же значения получает pip при подготовке пакетов. Частные адреса и внутренние имена Colloq (ядра, контейнеры) идут мимо прокси сами; в NO_PROXY перечислите внутренние домены, например своей модели и зеркала PyPI. NODE_EXTRA_CA_CERTS — путь к файлу PEM с сертификатами внутреннего CA на хосте: colloq-host монтирует его в контейнер по тому же пути, и его тоже получает pip. Тот же файл положите и в системное хранилище: образы скачивает сам Docker, и ему нужны и этот CA, и свой прокси.
cp campus-ca.pem /usr/local/share/ca-certificates/campus-ca.crt
update-ca-certificates # для скачивания образов самим Docker
# вместе с остальными настройками colloq-host up, см. «Установка»
HTTPS_PROXY=http://proxy.example.edu:3128
HTTP_PROXY=http://proxy.example.edu:3128
NO_PROXY=localhost,127.0.0.1,.example.edu
NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/campus-ca.crtПрокси для Docker задаёт ключ proxies в /etc/docker/daemon.json (или drop-in systemd для docker.service); после этой правки и после update-ca-certificates перезапустите Docker.
{
"proxies": {
"http-proxy": "http://proxy.example.edu:3128",
"https-proxy": "http://proxy.example.edu:3128",
"no-proxy": "localhost,127.0.0.1,.example.edu"
}
}Зеркало PyPI для «своих пакетов» соревнований задаёт DEPENDENCY_INDEX_URL=https://pypi.example.edu/simple — подойдёт любой индекс, совместимый с PyPI по Simple API (по умолчанию https://pypi.org/simple). Если сами файлы пакетов отдаёт другой хост, перечислите его в DEPENDENCY_FILES_HOSTS. Адреса зеркала могут быть частными; адрес индекса — только https и без учётных данных, то есть зеркало должно отдавать пакеты анонимно.
Установка без интернета
- На машине с интернетом и Docker возьмите
colloq-hostнужной версии и соберите комплект: образ приложения, образы ядер и самcolloq-hostв одном файле. Ядра в нём — для окружения по умолчанию (base), другие перечислите вKERNEL_PRELOAD. Пока файл пишется, свободного места нужно примерно вдвое больше его размера. - Перенесите файл на VM вуза и поставьте на ней Docker Engine 28 или новее из пакетов дистрибутива или внутреннего зеркала: без сети
colloq-hostего не установит. - Достаньте из файла
colloq-host, загрузите образы и запустите Colloq.loadкладётcolloq-hostв/usr/local/sbin, запоминает образ и записываетCOLLOQ_OFFLINE=1: дальше ничего не скачивается, не ставится и не собирается из сети.
# на машине с интернетом
docker run --rm -v "$PWD:/host" ghcr.io/colloq-edu/colloq-server:X.Y.Z install-host /host
KERNEL_PRELOAD=base,kaggle-base ./colloq-host bundle colloq-X.Y.Z.tar ghcr.io/colloq-edu/colloq-server:X.Y.Z
# на сервере вуза, от root
tar -xf colloq-X.Y.Z.tar colloq-host && ./colloq-host load colloq-X.Y.Z.tar
colloq-host doctor
COLLOQ_TUNNEL=none PUBLIC_URL=https://colloq.example.edu colloq-host upОбновление — так же: новый комплект, colloq-host load, затем colloq-host update. Без интернета не работают импорт с GitHub, оракул (если внутри сети нет своей модели), «свои пакеты» соревнований (если нет зеркала PyPI) и сборка новых окружений из панели: ей нужны Docker Hub, Debian и PyPI.
Обратный прокси
Что должен делать прокси:
- Обслуживать корень отдельного имени, например
https://colloq.example.edu/. Настройки базового пути у приложения нет, из подкаталога оно работать не будет. - Пропускать WebSocket на
/collab/,/control/и/file/. Сервер шлёт ping каждые 25 с. - Не буферизовать server-sent events:
/api/k/competitions/<адрес>/stream,/api/k/competitions/<адрес>/dependencies/<набор>/stream,/api/admin/competitions/<id>/stream,/api/admin/environments/<имя>/log. Приложение помечает эти ответы заголовкомX-Accel-Buffering: no(nginx учитывает его сам) и раз в 20 с шлёт пульс. - Держать WebSocket и потоки часами: тайм-аут чтения — не меньше часа.
- Принимать тело запроса не меньше 210 МБ: данные соревнования загружаются одним запросом до 200 МБ. Файл в комнату — до 50 МБ по умолчанию (
MAX_UPLOAD_MB); подняли этот предел — поднимите и предел прокси. - Успевать передать загрузку приложению за 5 минут — это тайм-аут запроса в Node.js. nginx по умолчанию сначала принимает тело целиком и только потом быстро отдаёт его приложению, так что медленный клиент в этот предел не упирается; прокси, который передаёт тело потоком (Caddy), упирается.
- Держать простаивающее соединение с приложением меньше 130 с: столько его держит само приложение, и прокси не должен отправлять запрос в соединение, которое приложение как раз закрывает.
- Передавать
Hostтаким, каким его прислал клиент: приложение сверяет с нимOrigin, и иначе каждая запись под/apiполучит 403. - Записывать в
X-Forwarded-Forадрес клиента (заменять, а не дописывать), вX-Forwarded-Proto—https; заголовокCF-Connecting-IPудалять.
nginx (1.18 из Ubuntu 22.04 и 1.24 из 24.04), файл /etc/nginx/conf.d/colloq.conf. Если прокси на другой машине, в upstream укажите внутренний адрес VM.
map $http_upgrade $connection_upgrade {
default upgrade;
'' '';
}
upstream colloq {
server 127.0.0.1:3000;
keepalive 32;
keepalive_timeout 60s; # меньше 130 с, которые держит приложение
}
server {
listen 80;
server_name colloq.example.edu;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2; # с nginx 1.25.1: listen 443 ssl; и http2 on;
server_name colloq.example.edu;
ssl_certificate /etc/ssl/colloq/fullchain.pem;
ssl_certificate_key /etc/ssl/colloq/privkey.pem;
client_max_body_size 256m; # данные соревнования: до 200 МБ одним запросом
location / {
proxy_pass http://colloq;
proxy_http_version 1.1;
proxy_set_header Host $http_host; # с портом, если он есть: с ним сверяется Origin
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header CF-Connecting-IP "";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 1h; # WebSocket и server-sent events
proxy_send_timeout 1h;
}
}Caddy, файл /etc/caddy/Caddyfile:
colloq.example.edu {
# Сертификат вуза. Без этой строки Caddy получит сертификат Let's Encrypt,
# и тогда имя должно быть доступно из интернета на портах 80 и 443.
tls /etc/caddy/colloq.crt /etc/caddy/colloq.key
request_body {
max_size 256MB
}
# Host, X-Forwarded-For и X-Forwarded-Proto Caddy выставляет сам,
# WebSocket и server-sent events пропускает без настройки,
# а простаивающее соединение с приложением держит 2 минуты — меньше 130 с.
reverse_proxy 127.0.0.1:3000 {
header_up -CF-Connecting-IP
}
}Журналы доступа прокси содержат адреса комнат, ключи входа преподавателей (/admin/k/…, /admin/t/…) и токены комнат в адресах WebSocket (?token=…). Храните их так же закрыто, как базу, или пишите без адреса запроса.
Проверка: curl -sS https://colloq.example.edu/api/readyz, затем комната с двух устройств — совместная правка, запуск ячейки, загрузка файла. Потоки видны по журналу сборки окружения в панели: строки должны появляться по одной, а не одним куском в конце.
Адреса клиентов и HTTPS
Заголовку X-Forwarded-For приложение верит, только если соединение пришло с адреса из TRUSTED_PROXIES. Прокси на этой же VM приходит к приложению через проброс порта Docker, поэтому приложение видит не 127.0.0.1, а шлюз сети Docker colloq. Пока порт опубликован на loopback, а TRUSTED_PROXIES не задан, colloq-host сам доверяет loopback и этому шлюзу, так что прокси на той же машине ничего настраивать не нужно. Задаёте TRUSTED_PROXIES сами — это умолчание пропадает, и шлюз нужно вписать тоже. Без доверенного прокси вся группа выглядит одним адресом: 61-й новичок в комнате за 10 минут получит отказ 429, а оракул примет 20 вопросов в минуту на всех.
# шлюз сети colloq
docker network inspect colloq -f '{{range .IPAM.Config}}{{.Gateway}}{{end}}'Свои сети Docker по умолчанию берёт из 172.17.0.0–172.31.255.255 и 192.168.0.0/16. Если это пересекается с сетями кампуса, до установки задайте другие диапазоны в default-address-pools файла /etc/docker/daemon.json.
TRUSTED_PROXIES принимает адреса и подсети IPv4 и IPv6 через запятую или пробел, а также слова loopback, private (все частные диапазоны) и none. Клиентом считается самый правый адрес в X-Forwarded-For, который сам не входит в доверенные.
Прокси на другой машине. Опубликуйте порт на внутреннем адресе VM — COLLOQ_BIND=10.0.0.5 — и впишите адрес прокси в TRUSTED_PROXIES (например, TRUSTED_PROXIES=10.0.0.2); colloq-host запоминает оба значения. Порт 3000 закройте для всех, кроме прокси. Правила ufw и firewalld опубликованные порты Docker не видят: фильтруйте в цепочке DOCKER-USER или на сетевом экране перед VM.
Общие адреса. Если много людей приходят с одного адреса — через NAT Wi-Fi кампуса или концентратор VPN, — перечислите такие адреса: SHARED_ADDRESSES=198.51.100.7/32,10.20.0.0/16. Для них не действуют пределы на адрес: 60 новичков в комнате за 10 минут, 20 вопросов оракулу в минуту, входы и вступления в соревнования. Пределы на комнату и на человека остаются.
Адрес для ссылок. PUBLIC_URL=https://colloq.example.edu — внешний адрес без пути и без слеша в конце. Из него строятся все ссылки, которые раздаёт Colloq, в том числе ссылка владельца.
HTTPS. Когда прокси сообщает X-Forwarded-Proto: https, cookies получают флаг Secure, а приложение само отправляет Strict-Transport-Security (180 дней, без includeSubDomains); по обычному http этот заголовок не уходит. Если прокси уже добавляет свой, выключите заголовок приложения: HSTS=0.
Установка
Всё ниже выполняется от root на подготовленной VM: Ubuntu 22.04 или 24.04, Docker Engine 28 или новее из репозитория Docker или вашего зеркала, диск под /workspace/colloq. Номер версии возьмите на странице Releases.
# 1. colloq-host из образа выбранной версии и проверка машины
IMAGE=ghcr.io/colloq-edu/colloq-server:X.Y.Z
docker run --rm -v /usr/local/sbin:/host "$IMAGE" install-host /host
colloq-host doctor
# 2. Запуск за прокси на этой же VM
COLLOQ_TUNNEL=none \
PUBLIC_URL=https://colloq.example.edu \
COLLOQ_IMAGE="$IMAGE" \
colloq-host up
# 3. Ссылка владельца, готовность и ночные копии
colloq-host link
colloq-host status
colloq-host backup-timer ondoctor ничего не меняет: по строке PASS, WARN или FAIL на каждую проверку — архитектура, версия Docker и его сетевой экран, память и диск, порт 3000, DNS, синхронизация часов, доступ к ghcr.io, PUBLIC_URL и доверенные прокси. Исправьте каждую строку FAIL до первого занятия. up ставит недостающее, скачивает образ, записывает настройки в /etc/colloq/colloq.env и запускает контейнер colloq. Образ ядра по умолчанию (base) скачивается из ghcr.io/colloq-edu/colloq-kernel, а если не вышло — собирается на месте; это несколько минут в фоне, и панель тем временем уже работает. Если прокси на другой машине, добавьте к up COLLOQ_BIND и TRUSTED_PROXIES, см. «Адреса клиентов».
colloq-host link печатает адрес и, пока у сервера нет владельца, ссылку установки …/admin/t/…. Это ключ от сервера: не отправляйте его в общий чат. Откройте ссылку, введите имя и почту — и вы владелец. Преподавателей добавьте в панели, в разделе «Преподаватели»: каждый получит личную ссылку входа.
colloq-host status показывает /api/health, образы ядер и контейнеры комнат; сервер готов к занятию, когда в ответе "ok":true. Перед первой группой создайте две комнаты, откройте их с двух устройств из сети студентов, запустите ячейку, загрузите файл, а затем проверьте резервную копию и восстановление на запасной VM.
Настройки
colloq-host up записывает в /etc/colloq/colloq.env (права 0600) переменные из своего окружения: непустое значение заменяет прежнее, а отсутствующее ничего не стирает. Там же он запоминает и собственные настройки — COLLOQ_HOME, COLLOQ_BIND, — чтобы следующий update действовал так же. Чтобы убрать строку, отредактируйте файл. Изменения применяет повторный colloq-host up: контейнер приложения пересоздаётся, только если изменились настройки или образ, а ядра комнат при этом продолжают работать. Оракул, ресурсы комнат и слоты соревнований владелец меняет и в панели, без перезапуска; сохранённое в панели главнее файла.
| Переменная | Что задаёт | По умолчанию |
|---|---|---|
| Адрес и прокси | ||
COLLOQ_TUNNEL | none — адрес даёт ваш прокси. Остальные режимы (relay, cloudflare, direct) — для аренды и публикации без своего прокси. | auto; вне Vast без PUBLIC_URL — none с предупреждением |
PUBLIC_URL | Внешний адрес, из которого строятся ссылки. | — |
TRUSTED_PROXIES | Адреса прокси, чей X-Forwarded-For принимается: IP, подсети, loopback, private, none. | loopback; при порте на loopback colloq-host добавляет шлюз сети colloq |
SHARED_ADDRESSES | Подсети NAT, для которых не действуют пределы на адрес. | пусто |
HSTS | 0 — не отправлять Strict-Transport-Security. | включено |
TRUST_CF_CONNECTING_IP | 1 — принимать CF-Connecting-IP; только для туннелей Cloudflare самого Colloq, не за вашим прокси. | выключено |
COLLOQ_BIND | Где хост публикует порт 3000; нужен, если прокси на другой машине. Читает только colloq-host. | 127.0.0.1 |
| Исходящие соединения | ||
HTTPS_PROXY, HTTP_PROXY, NO_PROXY | Исходящий прокси для модели ИИ, импорта с GitHub и pip. | — |
NODE_EXTRA_CA_CERTS | Файл PEM внутреннего CA (путь внутри контейнера). | — |
DEPENDENCY_INDEX_URL | Индекс для «своих пакетов» соревнований. | https://pypi.org/simple |
DEPENDENCY_FILES_HOSTS | Хосты, которые отдают файлы пакетов, через запятую. | — |
COLLOQ_ROOM_NETWORK | none — у комнат нет сети; open — нет запрета частных адресов. | пусто: интернет есть, частные адреса закрыты |
KERNEL_BLOCKED_CIDRS | Дополнительные подсети, закрытые для комнат. | — |
COLLOQ_HELPER_IMAGE | Образ служебного контейнера, который ставит правила iptables. | образ самого сервера |
COLLOQ_OFFLINE | 1 — ничего не скачивать, образы приходят через colloq-host load; его и записывает load. | выключено |
| Образы и резервные копии | ||
COLLOQ_HOME | Каталог состояния; задаётся до первого up. Читает только colloq-host. | /workspace/colloq |
COLLOQ_IMAGE | Образ первого up; дальше образ выбирает colloq-host update (/etc/colloq/image). | — |
KERNEL_IMAGE_REPO | Откуда брать готовые образы ядер: <repo>:v<версия>-<окружение>; none — собирать все окружения на месте. | ghcr.io/colloq-edu/colloq-kernel |
COLLOQ_REGISTRY_USER, COLLOQ_REGISTRY_TOKEN | Вход в закрытый реестр (токен только на чтение); читает только colloq-host. | — |
BACKUP_KEEP | Сколько последних копий хранить; 0 — все. | 14 |
BACKUP_AGE_RECIPIENT | Открытый ключ age: копии шифруются для него. Восстановление — с BACKUP_AGE_IDENTITY, путём к закрытому ключу. | — |
COLLOQ_ALLOW_SCHEMA_DOWNGRADE | 1 — открыть базу, которую записала более новая версия. Без него старый образ на такой базе не запускается; обычный откат — restore --image с копией до обновления. | — |
COLLOQ_BACKUP_AT | Время ежедневной копии; читает backup-timer on. | 03:30 |
COLLOQ_BACKUP_BEFORE_UPDATE | 0 — не делать копию перед update; читает update. | 1 |
COLLOQ_FREEZE_UPDATES | 1 — отключить автообновления системы и закрепить пакеты NVIDIA. Его ставит только on-start для Vast; на сервере вуза не задавайте. | выключено |
| Занятия | ||
INSTITUTION | Название рядом с логотипом. | — |
UI_LANGUAGE | Язык интерфейса (ru, en), пока владелец не выберет его в панели. | ru |
TZ | Часовой пояс: границы дня для дневных норм, даты. | Europe/Moscow |
ADMIN_EMAIL | Почта, которую форма владельца предлагает заранее. | — |
MAX_UPLOAD_MB | Предел одного файла, загружаемого в комнату. | 50 |
MAX_SESSION_MB | Предел всех загрузок в одну комнату; это не квота диска. | 1024 |
KERNEL_MEM | Память ядра комнаты; KERNEL_MEM_<ОКРУЖЕНИЕ> — для одного окружения. | 4g, у GPU-окружений 16g |
KERNEL_CPUS | Ядра процессора на комнату. | 2 |
KERNEL_OWN_MAX, KERNEL_OWN_PIDS, KERNEL_OWN_IDLE_MIN | Контейнер личных тетрадей: сколько в нём ядер, потолок процессов, минуты простоя до остановки ядра. | 60, 2048, 30 |
KERNEL_ENV, KERNEL_PRELOAD | Окружение по умолчанию; какие окружения подготовить при старте. | base; как KERNEL_ENV |
KERNEL_GPUS | Карты для GPU-комнат. | все найденные |
OPEN_SEMINAR_CREATION | Разрешить создавать комнаты через API без входа преподавателя. | false |
SESSION_SECRET | Ключ подписи ссылок; новое значение делает недействительными все выданные ссылки. | создаётся сам, data/session-secret |
| Оракул | ||
AI_PROVIDER | openai, ollama, vllm, openrouter или custom. | openai |
OPENAI_API_KEY | Ключ модели; без него оракул выключен (Ollama и vLLM работают без ключа). | — |
OPENAI_BASE_URL | Адрес модели. | https://api.openai.com/v1 |
OPENAI_MODEL | Модель. | gpt-4o-mini |
| Вход через прокси (SSO) | ||
AUTH_JWT_JWKS_URL, AUTH_JWT_AUDIENCE, AUTH_JWT_ISSUER и другие AUTH_JWT_* | Вход через Teleport или другой прокси, который подписывает JWT: преподаватели узнаются по почте, студенты входят под своим именем. Как это устроено и какие поля токена читаются — в руководстве для Kubernetes; на машине те же переменные передаются colloq-host up. Если приложение публикует Teleport на этой же машине: COLLOQ_TUNNEL=none, а PUBLIC_URL — адрес приложения в Teleport. | выключено |
Резервные копии
colloq-host backup # копия сейчас
colloq-host backup-timer on # каждый день в 03:30; другое время — COLLOQ_BACKUP_AT=02:00
colloq-host backup-timer statusТаймер — это служба systemd: копия делается по часовому поясу машины, а пропущенная, пока машина была выключена, — сразу после включения. Копия — это пара файлов в /workspace/colloq/backups/: согласованный снимок базы colloq-<время>.db и архив colloq-<время>-files.tar.gz с файлами комнат, картинками вывода, файлами страниц занятий, данными и посылками соревнований, наборами пакетов, ключом подписи ссылок, setup-token и списками пакетов своих окружений. Файлы копируются на ходу и у идущего занятия могут измениться во время копирования, поэтому таймер лучше ставить на ночь. Хранятся 14 последних копий (BACKUP_KEEP), более старые удаляются после успешной копии. Образов ядер в копии нет: их скачают или соберут заново.
Копия — это ключи от сервера: в ней ключ подписи, setup-token и база с ключами входа преподавателей и ключом ИИ, если его вводили в панели. Файлы создаются с правами 0600. Уносите их с машины своими средствами (rsync, restic или borg в хранилище вуза) и храните зашифрованными: диск VM — не резервная копия. Зашифровать копию может и сам Colloq: задайте BACKUP_AGE_RECIPIENT — открытый ключ age, и обе части копии запишутся как .age. Закрытый ключ держите вне машины; для восстановления укажите путь к нему: BACKUP_AGE_IDENTITY=/root/colloq-backup.key REPLACE=1 colloq-host restore ….
Восстановление: положите пару файлов в /workspace/colloq/backups/ и выполните команду ниже. colloq-host остановит Colloq, восстановит базу и файлы и запустит его снова; REPLACE=1 нужен, если на машине уже есть база. Проверяйте восстановление на запасной VM хотя бы раз в семестр.
REPLACE=1 colloq-host restore backups/colloq-20260930-033000.db
Обновление и откат
colloq-host update ghcr.io/colloq-edu/colloq-server:X.Y.Z
colloq-host statusupdate скачивает образ, делает резервную копию и печатает команду отката — и только потом пересоздаёт контейнер приложения, так что новый образ встречается с базой уже после копии. Данные остаются на диске, ядра комнат продолжают работать, и новый сервер снова подключается к ним; перерыв длится секунды, открытые комнаты переподключаются сами. И всё же обновляйтесь между занятиями. Выбранный образ записывается в /etc/colloq/image и переживает перезагрузку. Новый colloq-host из нового образа update ставит сам. Только при переходе с 0.8.x, где colloq-host этого ещё не умел, сначала поставьте новый вручную: docker run --rm -v /usr/local/sbin:/host ghcr.io/colloq-edu/colloq-server:X.Y.Z install-host /host.
Прежний образ на базе, которую новая версия могла изменить, не проверяется. Поэтому откат — это прежний образ вместе с копией, сделанной перед обновлением; всё, что сделано после обновления, пропадёт. Эту команду и печатает update:
REPLACE=1 colloq-host restore --image ghcr.io/colloq-edu/colloq-server:<прежняя версия> \
backups/colloq-<время>.dbПерезапуск Docker — например, при его обновлении — останавливает ядра комнат: тетради и файлы остаются, переменные Python теряются. Обновляйте Docker в окно обслуживания. Автообновления Ubuntu colloq-host не отключает.
Наблюдение, журналы и перезагрузка
| Адрес | Что проверяет |
|---|---|
/api/livez | Процесс жив. |
/api/readyz | База и рабочие файлы в порядке; от Docker и ядер не зависит. Подходит для балансировщика и внешней проверки. |
/api/health | Полная проверка: база, Docker и образ ядра, рабочие файлы, версия; при сбое — 503. Тексты ошибок видят только преподаватели и colloq-host status. Сразу после установки отвечает 503, пока готовится образ ядра. |
Преподавателям доступен GET /api/instance/operations: возраст очереди, повторы, сбои сохранения тетрадей, резервы памяти и свободный диск.
Диск. Квоты на комнату нет: база, файлы комнат, посылки и копии лежат на одном разделе, и студент, заполнивший диск, остановит сохранение тетрадей у всех. Следите за свободным местом и inode на разделе /workspace/colloq, например с тревогой при заполнении на 80 %; жёсткий предел дают отдельный раздел или проектные квоты XFS.
Журнал. colloq-host logs — это docker logs контейнера colloq; Docker хранит 5 файлов по 50 МБ. В журнале есть адреса комнат, а адрес комнаты — это ссылка для входа, поэтому доступ к журналу равен доступу к комнатам.
Перезагрузка. Docker сам поднимает контейнер приложения (--restart unless-stopped). Контейнеры ядер не поднимаются: комната запустит ядро снова, когда в неё войдут или запустят ячейку. Тетради и файлы на месте, а переменные Python пропадают.
Что смотреть регулярно: свободный диск; шкалу памяти во вкладке «Ресурсы»; что ночная копия сделана и унесена с машины; colloq-host status перед занятием.
Безопасность и персональные данные
Что хранится. Всё — на этой VM, в /workspace/colloq:
data/colloq.db— комнаты и тетради с историей правок; имена, которые участники ввели при входе; посещаемость и число запусков; преподаватели (имя, почта) и их ключи входа; настройки оракула, включая ключ, если его ввели в панели; учёт вопросов оракулу; участники соревнований (логин Telegram или почта), посылки и результаты.- В
data/лежат ещё ключ подписи ссылок, setup-token, картинки вывода, файлы страниц занятий (page-files/), данные и скрытые ответы соревнований, наборы пакетов; вworkspace/<комната>/— файлы комнат, вbackups/— копии. Ключ ИИ, заданный переменной, лежит в/etc/colloq/colloq.env. - Срока хранения нет: данные живут, пока комнату или соревнование не удалят. Текст, удалённый из ячейки, остаётся в истории правок, которую по умолчанию видят участники. Браузер получает cookie устройства на год.
Что уходит провайдеру ИИ. При вопросе оракулу — тетради комнаты целиком (ячейки и вывод), имена файлов комнаты, файл, открытый у спрашивающего, и сам вопрос. Имена участников — только если включён переключатель «Имена учащихся в запросах к модели» (панель → «Оракул»; по умолчанию включён); иначе провайдер видит «Студент 1», «Студент 2» по порядку входа в комнату и «Преподаватель» для ведущих; в консилиуме — метки S1…SN, имена вместо них подставляются уже в консоли преподавателя. Переключатель можно выключить для всей установки. Имена, которые студенты сами написали в решениях, уходят в любом случае. Для чувствительных курсов используйте модель внутри сети (Ollama, vLLM) или не включайте оракул.
Соревнования. На досках для студентов чужие адреса почты сокращены (abc…@example.edu), логины Telegram показаны как есть; свою строку участник видит целиком, преподаватели — все строки. В редакторе соревнования, в строке «Кто видит лидерборд», доску можно оставить только участникам. Участника можно удалить из соревнования; вместе с ним с диска сервера уходят его посылки.
Журнал действий. Владелец видит в панели «Журнал действий»: входы сотрудников, изменения состава преподавателей, удаления и настройки (GET /api/admin/audit-log, только владельцу).
Доступ преподавателей. Владелец и преподаватели входят по личным ссылкам /admin/k/…; владелец может перевыпустить ссылку преподавателя, и старая сразу перестаёт действовать. Входа через SSO, LDAP и второго фактора пока нет; панель может закрыть прокси — SSO или список разрешённых адресов на /admin и /api/admin, студентам эти пути не нужны. Любой преподаватель может вести любую комнату, курс и соревнование: одна установка — одна команда преподавателей, доверяющих друг другу.
Cookies и HTTPS. Все cookies — HttpOnly и SameSite=Lax, за HTTPS-прокси — ещё и Secure; про HSTS см. выше.
Честные ограничения:
- нет SSO;
- нет квоты диска на комнату;
- комната — общее рабочее место: участники делят ядро, файлы, пользователя Linux и контейнер личных тетрадей, поэтому для индивидуально оцениваемых и конфиденциальных работ комнаты не подходят;
- ссылку комнаты нельзя отозвать: кто её получил, тот войдёт и по умолчанию сможет запускать код;
- загруженные файлы не проверяются антивирусом;
- шрифт интерфейса HSE Sans принадлежит НИУ ВШЭ и не покрыт лицензией MIT: другому вузу его стоит заменить (THIRD_PARTY_NOTICES.md).
Kubernetes и одноузловой k3s
Если в организации уже есть кластер Kubernetes, ставьте Colloq Helm-чартом в пространство имён: это описано в разделе «Colloq в вашем Kubernetes» — отдельный под на комнату, приватный брокер, сетевые политики, образы по дайджестам. Скрипт, который сам ставит одноузловой k3s на голую VM («Установка на k3s»), остаётся предварительным путём для тех, у кого кластера нет: ни один опубликованный выпуск по 0.9.0 включительно не содержит его комплекта (release.json, colloq-deploy.tar.gz, SHA256SUMS), так что поставить его из опубликованного нельзя. Без кластера рекомендуемый путь — эта страница.