Bun-приложение выкладывается в сеть без аренды сервера: вы отдаёте исходники, платформа видит рядом с package.json файл bun.lock, ставит зависимости через bun install, запускает приложение и выдаёт публичную HTTPS-ссылку. Bun задумывался как быстрая замена Node.js: он сам исполняет TypeScript, сам ставит пакеты и умеет поднимать HTTP-сервер без фреймворка. Проблема в том, что платформ, которые понимают Bun «из коробки», заметно меньше, чем для Node, поэтому большинство гайдов заканчиваются ручной настройкой на VPS. Ниже — что проверить в проекте, чтобы первая же публикация на Dockbox закончилась рабочей ссылкой, и где Bun-проекты спотыкаются чаще всего.
Почему Bun-проект по умолчанию тащат на VPS
Привычный сценарий начинается с аренды машины и установки рантайма вручную, а дальше начинается та часть, ради которой обычно и берут платформу.
Bun не ставят из системных пакетов. В большинстве дистрибутивов его до сих пор нет в репозиториях, поэтому установка идёт отдельной командой или скриптом. Обновлять рантайм на живой машине тоже придётся вам.
Автозапуск и перезапуск. Чтобы процесс поднялся после падения и после перезагрузки сервера, нужен systemd-юнит или супервизор — и отдельный навык его отладки.
Обратный прокси и сертификат. Без nginx приложение не отдаёт HTTPS, а сертификат нужно продлевать каждые три месяца.
Оплата независимо от нагрузки. Машина стоит денег все 30 дней, даже если сервис дёргают раз в сутки.
Платформа деплоя снимает эту часть: она находит признак Bun, ставит зависимости, запускает приложение и отдаёт публичную HTTPS-ссылку. Ни сервера, ни nginx, ни ручного сертификата.
Шаг 1. Оставьте bun.lock рядом с package.json
Локфайл — главный признак того, что проект нужно собирать именно на Bun. В старых версиях это бинарный bun.lockb, в новых — текстовый bun.lock. Если файла нет, сначала установите зависимости у себя и заберите его вместе с кодом:
bun install
Локфайл ещё и фиксирует точные версии пакетов, поэтому сборка на сервере совпадёт с той, которую вы тестировали локально. Если получить файл никак не выходит, назовите Bun прямо в package.json: подойдёт либо start-скрипт, начинающийся с bun, либо поле engines со значением bun. Без любого из этих сигналов проект уедет как обычное Node-приложение на npm — и, скорее всего, не запустится.
Шаг 2. Оставьте одну понятную команду запуска
Добавьте в раздел scripts файла package.json запись start — например, bun run index.ts или bun run src/server.ts:
{
"scripts": {
"start": "bun run src/server.ts"
}
}
Одна команда вместо трёх способов запуска снимает любые сомнения о точке входа. Если проект работает и на Node — это не страшно: важно, что команда запуска ровно одна и она очевидна.
Шаг 3. Читайте порт из PORT и слушайте 0.0.0.0
Порт задаёт платформа, а не вы. Значение приходит в переменной окружения PORT, и его нужно прочитать в рантайме. Слушать нужно адрес 0.0.0.0, а не 127.0.0.1: иначе приложение отвечает только внутри контейнера, и ссылка остаётся пустой. Жёстко вписанный в код порт — причина номер один, по которой ссылка не открывается.
Плохой вариант — и порт, и адрес зафиксированы числами:
Bun.serve({
port: 3000,
hostname: "127.0.0.1",
fetch(req) {
return new Response("ok");
}
});
Правильный — значения берутся из окружения:
const port = Number(Bun.env.PORT) || 3000;
Bun.serve({
port,
hostname: "0.0.0.0",
fetch(req) {
return new Response("ok");
}
});
Elysia принимает порт в своём вызове listen, Hono экспортирует объект с полями fetch и port — в обоих случаях подставляйте значение из PORT, а не константу:
import { Elysia } from "elysia";
new Elysia()
.get("/", () => "ok")
.listen(Number(Bun.env.PORT) || 3000);
Фреймворк роли не играет: чистый Bun.serve, Elysia и Hono работают одинаково хорошо. Важно только одно — слушать правильный порт и правильный адрес.
Шаг 4. Ключи и токены — в переменные окружения
Строки подключения к базе, токены и ключи API читайте из окружения через Bun.env (или привычный process.env), а не держите константами в коде. Код вы почти наверняка зальёте в Git или кому-то покажете, и секреты уедут вместе с ним.
const token = Bun.env.API_TOKEN;
if (!token) throw new Error("API_TOKEN is not set");
В настройках проекта Dockbox такие значения задаются отдельно и передаются в контейнер в зашифрованном виде, поэтому в архиве и в репозитории они не появляются. Файл .env при этом включать не нужно.
Шаг 5. Не везите node_modules и результат сборки
Зависимости ставятся на нашей стороне из package.json и локфайла, поэтому папку node_modules в архив не кладите — загрузка останется маленькой, а версии пакетов совпадут с зафиксированными. Готовый бандл тоже не нужен: Bun исполняет TypeScript напрямую, отдельный шаг компиляции для этого не требуется. Если у проекта есть собственная сборка, просто вызовите её из команды запуска.
Шаг 6. Загрузите код и получите ссылку
Проект попадает на платформу архивом или импортом репозитория GitHub, включая приватный. Дальше платформа ставит зависимости, запускает ваше Bun-приложение и выдаёт публичный HTTPS-адрес. Логи и статус публикации видны в панели в реальном времени, поэтому ошибка старта проявляется сразу, а не молчаливой пустой страницей. Обновление — тем же путём: свежий архив или синхронизация из GitHub, и ссылка остаётся прежней.
Сколько это стоит и как работают контейнеры
Администрировать сервер и следить за процессом не нужно: контейнеры работают постоянно, без ограничения по часам и без «засыпания». Упавший контейнер платформа перезапускает сама, а логи остаются в панели.
Starter — 990 ₽/мес. 1 vCPU, 2 GB RAM, 20 GB SSD, один проект. Первый месяц бесплатный. Для одного Bun-сервиса этого достаточно.
Pro — 2 490 ₽/мес. 2 vCPU, 4 GB RAM, до пяти проектов — если приложений несколько или нужен запас ресурсов.
Team — 4 990 ₽/мес — для команд, которым нужен запас и SLA.
Свой Dockerfile поддерживается, но не обязателен: язык и стек платформа определяет по коду сама.
Частые вопросы
Как платформа понимает, что проект надо запускать на Bun, а не на Node?
По локфайлу. bun.lock или bun.lockb рядом с package.json означает, что зависимости ставятся и приложение запускается через Bun. Если локфайла нет, годится упоминание Bun внутри package.json — start-скрипт, начинающийся с bun, или поле engines. Без этих сигналов проект уедет как обычное Node-приложение. Рантайм вручную в панели выбирать не нужно.
Что делать, если в проекте нет bun.lock?
Выполните bun install у себя и заберите созданный локфайл вместе с кодом: он заодно зафиксирует версии пакетов, чтобы сборка на сервере совпала с локальной. Если получить файл не удаётся, назовите Bun прямо в package.json — сработает и start-скрипт вида bun run index.ts. Когда нет ни того ни другого, зависимости поставятся через npm, и проект запустится как Node-приложение.
Работают ли Elysia и Hono?
Да, оба, как и приложение напрямую на Bun.serve. Требование ко всем одинаковое: слушать адрес 0.0.0.0 и порт из переменной окружения PORT. Специфичной настройки под конкретный фреймворк не требуется.
Ссылка не открывается. С чего начать?
В первую очередь проверьте порт и адрес: чаще всего порт вписан в код числом, а сервер слушает 127.0.0.1 вместо 0.0.0.0, и снаружи до него не достучаться. Вторая распространённая причина — падение на старте, например из-за незаданного секрета. И то и другое видно в логах панели в течение нескольких секунд после публикации.
Нужно ли компилировать TypeScript перед загрузкой?
Нет. Bun исполняет .ts-файлы напрямую, так что отдельный шаг сборки для этого не нужен. Если у проекта есть собственная сборка, оставьте одну команду запуска, которая делает всё необходимое, а готовый результат не загружайте — он создаётся при публикации.