Шаблон рабочего пространства может публиковать веб-приложения на отдельных HTTPS-адресах и резервировать адреса для портов, которые владелец откроет из портала. Например, шаблон может предоставлять веб-терминал, а пользователь — временно публиковать сервер разрабатываемого приложения.

Публикация настраивает адрес и доступ. Само приложение запускается контейнером шаблона, скриптом или пользователем. Шлюз gate передаёт HTTP-запросы и WebSocket-соединения на порт приложения по 127.0.0.1 внутри пода.

Домены и сеть

Настройте DNS, Ingress и TLS до публикации шаблона. Для адреса IDE https://ddp-ws-0a26ad26.example-workspaces.com используются такие адреса:

НазначениеАдрес
Приложение с идентификатором terminalhttps://terminal-ddp-ws-0a26ad26.example-workspaces.com
Первый опубликованный портhttps://p1-ddp-ws-0a26ad26.example-workspaces.com

Wildcard-запись и сертификат для *.example-workspaces.com покрывают IDE, приложения и зарезервированные адреса портов. Стартовый Ingress направляет все эти хосты через gate. При изменении Ingress сохраните маршруты и TLS для каждого хоста.

Домен рабочих пространств должен быть отдельным от родительского домена DDP и Dex, для которого браузер допускает cookie. Например, используйте example-workspaces.com при адресе портала ddp.example.com. Приложение на ide.example.com может установить cookie для example.com, поэтому такой вариант не обеспечивает разделение с порталом.

Приложения шаблона

В стартовом main.tf список local.apps содержит веб-терминал. Для добавления приложения измените этот список, например:

apps = [
  { slug = "terminal", name = "Терминал", port = local.terminal_port, share = "owner" },
  { slug = "preview", name = "Предпросмотр", port = 3000, share = "authenticated" },
]

Приложение предпросмотра должно самостоятельно запуститься на порту 3000 в поде. Если сервер проверяет заголовок Host, разрешите его внешний хост, например preview-ddp-ws-0a26ad26.example-workspaces.com. Для сервера разработки Vite это задаётся через server.allowedHosts.

Поля приложения задают адрес, подпись и доступ:

ПолеТребования
slugУникальный идентификатор до 32 символов: строчные латинские буквы, цифры и дефис; начало и конец — буква или цифра. ide и p<N> зарезервированы
nameНазвание от 1 до 60 символов
portПорт приложения от 1 до 65535
shareowner, authenticated или public
iconНеобязательный HTTPS URL иконки

В outputs.tf обязателен результат:

output "ddp_apps" {
  value = local.apps
}

Если приложений нет, верните пустой список []. Отсутствующий или некорректный ddp_apps завершает операцию применения ошибкой.

Уровни доступа

Уровень задаётся отдельно для каждого приложения и опубликованного порта:

Значение шаблонаНазвание в интерфейсеКто открывает
owner«Только владелец»Владелец с правом обновлять рабочее пространство, как при открытии IDE
authenticated«Пользователи DDP»Любой вошедший в DDP пользователь, который не заблокирован
public«Публично»Любой посетитель без входа в DDP

Для authenticated не требуется доступ к карточке рабочего пространства. Пользователь открывает переданную ему ссылку и при необходимости входит в портал. Сессии приложений отделены от сессии IDE.

В настройках шаблона в блоке «Приложения» задайте «Потолок уровня для публикации портов». Владелец не сможет выбрать уровень выше этого значения. Ограничение относится к портам, публикуемым из интерфейса; уровни приложений в local.apps задаёт автор шаблона.

Веб-терминал и другие приложения с выполнением команд от имени владельца оставляйте с share = "owner". Они получают доступ к файлам и токенам внутри пода.

Адреса для публикации портов

Стартовый шаблон резервирует восемь адресов p1–p8. Чтобы изменить количество, замените значение в существующем блоке locals:

app_slots = 8

Допустимо от 0 до 100; значение 0 отключает публикацию портов из интерфейса. Стартовый проект формирует хосты и правила Ingress на основе этого значения. Результат ddp_runtime должен возвращать app_slots и порт шлюза gate_port:

app_slots = local.app_slots
gate_port = local.gate_port

Добавьте эти поля в существующий объект value результата ddp_runtime, а не отдельным output.

Публикация из интерфейса занимает свободный адрес без применения OpenTofu. Освобождение адреса выполняется кнопкой «Отменить публикацию». Если новая версия шаблона уменьшает количество адресов, публикации за пределами нового диапазона перестают открываться и помечаются «Адрес не зарезервирован текущей версией шаблона». Владелец может отменить их и при необходимости опубликовать порт заново в доступный адрес.

Веб-терминал стартового шаблона

Стартовый шаблон запускает ttyd из штатного образа IDE в контейнере terminal и публикует его как приложение «Терминал» с доступом только владельцу. Терминал использует тот же постоянный том, что IDE и агент. Команды выполняются в контейнере терминала с его собственными ограничениями ресурсов.

Чтобы изменить ограничения, замените значения terminal_requests и terminal_limits в main.tf. Инструменты, установленные на постоянный том, доступны и терминалу, если их пути включены в его окружение.

Проверка шаблона

После изменения проверьте черновик в новом рабочем пространстве:

  1. Дождитесь успешной операции создания и откройте вкладку «Приложения».
  2. Откройте «Терминал» и проверьте доступ к рабочей директории.
  3. Запустите HTTP-приложение на свободном порту и опубликуйте его из портала.
  4. Проверьте адрес, TLS и разрешённый уровень доступа. Для authenticated проверьте вход другим пользователем; для public — открытие без сессии портала.
  5. Отмените публикацию и убедитесь, что приложение больше не открывается по этому адресу.

После проверки опубликуйте и активируйте версию. Существующие рабочие пространства используют прежний состав приложений до обновления шаблона.