Загрузить файл
POST /v1/infra/servers/:id/upload
Записывает файл на BLACKHOLE-сервер через агент туннеля. Два варианта источника: встроенное base64-содержимое в теле запроса (до 500 МБ) или URL, с которого агент скачает файл сам (до 500 МБ). Поддерживается автоматическая распаковка архивов tar.gz / tar.bz2 / zip — формат определяется по сигнатуре файла (magic bytes) или по расширению URL.
Параметры
| Параметр | В | Тип | Обяз. | Описание |
|---|---|---|---|---|
id |
path | string (UUID) | да | ID BLACKHOLE-сервера, status: running, blackholeStatus: CONNECTED |
Поля запроса (body)
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
path |
string | да | Путь на сервере, 1–500 символов. Для архивов — куда положить загруженный архив до распаковки |
content |
string | да (или url) |
Base64-содержимое файла. Максимум 500 МБ на тело запроса |
url |
string | да (или content) |
HTTPS-URL, откуда агент скачает файл. До 500 МБ |
mode |
string | нет | Права файла в восьмеричном формате: 0644, 0755. Применяется к файлу по пути path |
extract |
boolean | нет | Распаковать архив после загрузки. По умолчанию false. Требует content или url с архивом |
extractTo |
string | нет | Директория для распаковки (при extract: true). По умолчанию — директория из path |
Нужно передать ровно одно из: content или url.
Примеры
curl — личный ключ
# Загрузка файла по URL с автоматической распаковкой
curl -X POST https://vibecode.bitrix24.tech/v1/infra/servers/SERVER_ID/upload \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://github.com/user/repo/archive/main.tar.gz",
"path": "/opt/app/source.tar.gz",
"extract": true,
"extractTo": "/opt/app"
}'
# Встроенное base64-содержимое — маленький файл (package.json)
CONTENT=$(echo '{"name":"my-app","version":"1.0.0"}' | base64)
curl -X POST https://vibecode.bitrix24.tech/v1/infra/servers/SERVER_ID/upload \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"content\":\"$CONTENT\",\"path\":\"/opt/app/package.json\",\"mode\":\"0644\"}"
curl — OAuth-приложение
curl -X POST https://vibecode.bitrix24.tech/v1/infra/servers/SERVER_ID/upload \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/config.json","path":"/etc/myapp/config.json"}'
JavaScript — личный ключ
// Загрузка архива и распаковка
const res = await fetch(
`https://vibecode.bitrix24.tech/v1/infra/servers/${serverId}/upload`,
{
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
url: 'https://github.com/user/app/archive/main.tar.gz',
path: '/opt/app/source.tar.gz',
extract: true,
extractTo: '/opt/app',
}),
}
)
const { data } = await res.json()
console.log(`Записано ${data.size} байт по пути ${data.path}${data.extracted ? ', распаковано' : ''}`)
JavaScript — OAuth-приложение
// Встроенное base64-содержимое — маленький конфиг
const content = Buffer.from('NODE_ENV=production\n').toString('base64')
await fetch(
`https://vibecode.bitrix24.tech/v1/infra/servers/${serverId}/upload`,
{
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
content,
path: '/opt/app/.env',
mode: '0600',
}),
}
)
Поля ответа
| Поле | Тип | Описание |
|---|---|---|
success |
boolean | true при успешной записи |
data.path |
string | Итоговый путь файла на сервере |
data.size |
number | Размер в байтах |
data.extracted |
boolean | true если архив был распакован после загрузки |
Пример ответа
{
"success": true,
"data": {
"path": "/opt/app/source.tar.gz",
"size": 1048576,
"extracted": true
}
}
Пример ответа при ошибке
403 — путь запрещён для загрузки:
{
"success": false,
"error": {
"code": "UPLOAD_PATH_DENIED",
"message": "Upload to system path is not allowed"
}
}
Ошибки
| HTTP | Код | Описание |
|---|---|---|
| 400 | VALIDATION_ERROR |
Нарушена схема: одновременно content и url, либо ни одного, неверный path, тело больше 500 МБ |
| 400 | NOT_BLACKHOLE |
Сервер в режиме OPEN — Deploy API недоступен |
| 401 | MISSING_API_KEY |
Не передан заголовок X-Api-Key |
| 401 | INVALID_API_KEY |
Неверный или просроченный API-ключ |
| 403 | UPLOAD_PATH_DENIED |
Загрузка в системные директории (/root/.ssh, /etc/passwd, /boot, …) запрещена |
| 404 | NOT_FOUND |
Сервер не существует, удалён или принадлежит другому API-ключу |
| 409 | SERVER_NOT_READY |
Сервер не готов к операции: не запущен или туннель не подключён. В ответе — поле hint с причиной и следующим шагом. Разбудите сервер или вызовите `/repair` и повторите запрос. Случай «числится подключённым, но у Gateway нет живого туннеля» на этом маршруте приходит как 502 TUNNEL_NOT_FOUND (см. ниже) |
| 429 | RATE_LIMITED |
Превышен лимит 10 операций в минуту на сервер |
| 429 | DEPLOY_BACKEND_BUSY |
Слишком много одновременных загрузок с телом запроса. Платформа ограничивает число одновременных /upload и /deploy со встроенным содержимым, чтобы не исчерпать память. Ответ несёт заголовок Retry-After: 30 — повторите через 30 секунд. Либо передайте архив ссылкой (url): для загрузок по ссылке ограничения на одновременность нет |
| 502 | UNZIP_PREFLIGHT_FAILED |
Не удалось установить unzip на сервере перед распаковкой zip-архива. Чтобы не зависеть от этого шага, используйте архив .tar.gz |
| 500 | код агента | Ошибка записи файла на сервере: нехватка места, права доступа и т. п. Конкретный код приходит от агента в поле error.code |
| 502 | TUNNEL_NOT_FOUND / GATEWAY_UNREACHABLE: … |
Нет живого туннеля до сервера либо Gateway недоступен — вызовите `/repair` и повторите. GATEWAY_UNREACHABLE несёт детали после двоеточия — сопоставляйте error.code по префиксу |
| 503 | GATEWAY_TIMEOUT: … |
Gateway не ответил вовремя. Код несёт детали после двоеточия — сравнивайте по префиксу |
Полный список общих ошибок API — Ошибки.
Известные особенности
- Автоопределение формата архива при
extract: true. Агент определяет формат по сигнатуре файла (magic bytes, функцияdetectArchiveExt()): поддерживает.tar.gz,.zip,.tar.bz2. Формат можно не указывать явно. Для URL — агент также проверяет расширение. - macOS-архивы чистятся автоматически. Если архив содержит AppleDouble-сайдкары (
._*) или.DS_Store, агент удаляет их после распаковки — это предотвращает ложные срабатывания сканеров вроде Tailwind v4 oxide. При создании архива на macOS советуем использоватьCOPYFILE_DISABLE=1 tar -czf ...чтобы сайдкары вообще не попадали в архив. - Windows PowerShell ZIP — работает на агенте ≥ 1.2.3.
Compress-Archiveв Windows пишет ZIP с литеральными\в именах файлов. Агент с версии 1.2.3 автоматически нормализует эти пути через шагnormalize_windows_paths. Для старых версий агента используйтеtar.gz(через WSL / Git Bash) либо выкладывайте готовый tar-архив и загружайте черезurl. - Список запрещённых путей. Агент блокирует загрузку в:
/root/.ssh/(защита SSH-ключей),/boot,/etc/shadow,/etc/passwd, системные сервис-файлы. Для приложения используйте/opt/<app>/или/var/lib/<app>/. modeприменяется к архиву, не к распакованным файлам. Приextract: trueправа распакованных файлов определяются содержимым архива, аmodeзадаётся только сохранённому архиву. Если нужно изменить права внутри — сделайте через `/exec` cchmod.- Таймаут 10 минут на загрузку через
url. Для 500 МБ должно уложиться. Если источник медленный — предзагрузите архив, положите на свой CDN.
Смотрите также
- Полный деплой — за один запрос вместо цепочки
upload+exec. - Выполнить команду — после загрузки можно распаковать/установить вручную.
- Логи сервиса — проверить, что сервис применил новые файлы.