[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"docs-infra\u002Fdeploy\u002Fport":3,"docs-tabs-infra\u002Fdeploy\u002Fport":6},{"content":4,"lastmod":5},"\n## Задать порт приложения\n\n`PATCH \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fport`\n\nЗадаёт TCP-порт, на который агент туннеля проксирует входящие HTTPS-запросы с субдомена. По умолчанию туннель идёт на `:3000` — это стандарт платформы, большинство приложений должны слушать именно его. Этот эндпоинт нужен в редких случаях: приложение по историческим причинам работает на другом порту или вы хотите `0` (автоопределение), чтобы агент сам нашёл слушающий порт. Порты 1–1023 запрещены — это системные (SSH, HTTP, HTTPS, SQL), их использование создало бы риск перенаправления трафика на служебные процессы.\n\n## Параметры\n\n| Параметр | В | Тип | Обяз. | Описание |\n|----------|---|-----|:-----:|----------|\n| `id` | path | string (UUID) | да | ID BLACKHOLE-сервера, `status: running`, `blackholeStatus: CONNECTED` |\n\n## Поля запроса (body)\n\n| Поле | Тип | Обяз. | Описание |\n|------|-----|:-----:|----------|\n| `port` | number | **да** | `0` (автоопределение) или `1024–65535`. Порты 1–1023 отклоняются с `PORT_RESTRICTED` |\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\n# Установить порт 8080\ncurl -X PATCH https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Fport \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"port\": 8080}'\n\n# Автоматическое определение\ncurl -X PATCH https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Fport \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"port\": 0}'\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -X PATCH https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Fport \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"port\": 8080}'\n```\n\n### JavaScript — личный ключ\n\n```javascript\nconst res = await fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Fport`,\n  {\n    method: 'PATCH',\n    headers: {\n      'X-Api-Key': 'YOUR_API_KEY',\n      'Content-Type': 'application\u002Fjson',\n    },\n    body: JSON.stringify({ port: 8080 }),\n  }\n)\nconst { data } = await res.json()\nconsole.log(`Порт приложения: ${data.port}`)\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nawait fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Fport`,\n  {\n    method: 'PATCH',\n    headers: {\n      'X-Api-Key': 'YOUR_APP_KEY',\n      'Authorization': 'Bearer USER_SESSION_TOKEN',\n      'Content-Type': 'application\u002Fjson',\n    },\n    body: JSON.stringify({ port: 0 }),\n  }\n)\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|----------|\n| `success` | boolean | Всегда `true` при успехе |\n| `data.port` | number | Итоговый порт. При `port: 0` вернётся `3000` (значение по умолчанию при автоопределении) |\n| `data.mode` | string | `manual` (задан конкретный порт) или `auto` (`port: 0`) |\n| `data.verified` | boolean | `true` — платформа подтвердила (probe), что агент уже проксирует на этот порт. `false` — порт сохранён, но маршрутизация ещё не подтверждена (см. `data.warning`) |\n| `data.warning` | string | Присутствует только при `verified: false`: маршрутизация не подтверждена, приложение может кратко (до ~30 с) отдавать страницу Black Hole, пока автоопределение не подтвердит порт |\n\n## Пример ответа\n\n```json\n{\n  \"success\": true,\n  \"data\": { \"port\": 8080, \"mode\": \"manual\", \"verified\": true }\n}\n```\n\n## Пример ответа при ошибке\n\n400 — системный порт запрещён:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"PORT_RESTRICTED\",\n    \"message\": \"System ports (1-1023) are not allowed. Use port >= 1024 or 0 for auto-detect\"\n  }\n}\n```\n\n409 — агент отклонил смену порта (фиксированный порт \u002F устаревший бинарь):\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"PORT_NOT_APPLIED\",\n    \"message\": \"The server agent runs in fixed-port mode and cannot change its port at runtime. Repair the server (POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Frepair) to switch the agent to port auto-detection, then retry.\",\n    \"agentError\": \"NO_SCANNER\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|----------|\n| 400 | `VALIDATION_ERROR` | `port` не число, вне диапазона 0–65535 |\n| 400 | `PORT_RESTRICTED` | Порт в диапазоне 1–1023 (системные порты) |\n| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |\n| 401 | `INVALID_API_KEY` | Неверный или просроченный API-ключ |\n| 404 | `NOT_FOUND` | Сервер не `BLACKHOLE + RUNNING`, удалён или принадлежит другому API-ключу |\n| 409 | `SERVER_NOT_READY` | Агент туннеля не в статусе `CONNECTED` |\n| 409 | `PORT_NOT_APPLIED` | Агент отклонил смену порта. `agentError: NO_SCANNER` — сервер в режиме фиксированного порта (см. ниже). Другой `agentError` — агент устарел. В обоих случаях помогает [`\u002Frepair`](\u002Fdocs\u002Finfra\u002Flifecycle\u002Frepair) |\n| 429 | `RATE_LIMITED` | Превышен общий лимит запросов платформы |\n| 502 | `GATEWAY_ERROR` | Gateway не смог доставить команду агенту |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n- **Системные порты (1–1023) запрещены не случайно.** SSH (22), HTTP (80), HTTPS (443), DNS (53), PostgreSQL (5432), MySQL (3306) — открытие туннеля на них создало бы риск перенаправления внешнего трафика на служебные процессы внутри виртуальной машины.\n- **Как работает `port: 0`.** Агент сканирует `\u002Fproc\u002Fnet\u002Ftcp` и `\u002Fproc\u002Fnet\u002Ftcp6`, находит процесс, слушающий на прикладном порту (≥1024), и проксирует туда. Полезно для приложений, выбирающих порт динамически при запуске.\n- **Значение сохраняется между перезапусками агента.** Платформа пишет `localPort` в базу сервера — после [`\u002Frepair`](\u002Fdocs\u002Finfra\u002Flifecycle\u002Frepair) или перезагрузки агент возьмёт то же значение. При `\u002Fdeploy` с явным `port` значение перезапишется.\n- **`port: 0` в ответе возвращается как `3000`.** Это не ошибка: «при автоопределении возвращаем 3000, если ничего подходящего не нашли». Реальный слушающий порт проверяйте через [`\u002Fexec`](.\u002Fexec.md) с командой `ss -tlnp`.\n- **Платформа подтверждает смену порта (`data.verified`).** После `set_port` платформа опрашивает агента и проверяет, что туннель действительно проксирует на запрошенный порт. `verified: true` — маршрутизация готова. `verified: false` + `data.warning` — порт сохранён, но агент ещё не подтвердил порт (автоопределение сработает в течение ~30 с). Если приложение остаётся недоступным дольше — [`\u002Frepair`](\u002Fdocs\u002Finfra\u002Flifecycle\u002Frepair). `409 PORT_NOT_APPLIED` — агент в принципе не принял смену порта: при `agentError: NO_SCANNER` сервер работает в режиме фиксированного порта (запустите приложение на текущем порту, либо `\u002Frepair` для перехода в автоопределение), при ином `agentError` — агент устарел (`\u002Frepair` обновит его).\n\n## Смотрите также\n\n- [Полный деплой](.\u002Fdeploy.md) — поле `port` в `\u002Fdeploy` также конфигурирует туннель.\n- [Метрики туннеля](.\u002Fmetrics.md) — есть ли HTTP-соединения и `lastRequestAt`.\n- [Выполнить команду](.\u002Fexec.md) — `ss -tlnp` для проверки слушающих портов.\n","2026-06-29",{}]