Развёртывание на Fly.io
Цель: OpenClaw Gateway, работающий на машине Fly.io с постоянным хранилищем, автоматическим HTTPS и доступом к Discord/каналам.
Что вам потребуется
- Установленный flyctl CLI
- Аккаунт Fly.io (бесплатный тариф подойдёт)
- Авторизация модели: API-ключ выбранного провайдера
- Учётные данные каналов: токен Discord-бота, токен Telegram и т.д.
Быстрый путь для начинающих
- Клонируйте репозиторий, настройте
fly.toml - Создайте приложение + volume, задайте секреты
- Разверните через
fly deploy - Подключитесь по SSH для создания конфигурации или используйте Control UI
1) Создание приложения Fly
# Клонируйте репозиторий
git clone https://github.com/openclaw/openclaw.git
cd openclaw
# Создайте приложение Fly (выберите своё имя)
fly apps create my-openclaw
# Создайте постоянный volume (1 ГБ обычно достаточно)
fly volumes create openclaw_data --size 1 --region iad
Совет: Выберите ближайший регион. Популярные варианты: lhr (Лондон), iad (Вирджиния), sjc (Сан-Хосе).
2) Настройка fly.toml
Отредактируйте fly.toml под ваше имя приложения и требования.
Замечание о безопасности: Конфигурация по умолчанию предоставляет публичный URL. Для защищённого развёртывания без публичного IP см. Приватное развёртывание или используйте fly.private.toml.
app = "my-openclaw" # Имя вашего приложения
primary_region = "iad"
[build]
dockerfile = "Dockerfile"
[env]
NODE_ENV = "production"
OPENCLAW_PREFER_PNPM = "1"
OPENCLAW_STATE_DIR = "/data"
NODE_OPTIONS = "--max-old-space-size=1536"
[processes]
app = "node dist/index.js gateway --allow-unconfigured --port 3000 --bind lan"
[http_service]
internal_port = 3000
force_https = true
auto_stop_machines = false
auto_start_machines = true
min_machines_running = 1
processes = ["app"]
[[vm]]
size = "shared-cpu-2x"
memory = "2048mb"
[mounts]
source = "openclaw_data"
destination = "/data"
Ключевые параметры:
| Параметр | Зачем |
|---|---|
--bind lan | Привязка к 0.0.0.0, чтобы прокси Fly мог достучаться до шлюза |
--allow-unconfigured | Запуск без файла конфигурации (создадите позже) |
internal_port = 3000 | Должен совпадать с --port 3000 (или OPENCLAW_GATEWAY_PORT) для health checks |
memory = "2048mb" | 512 МБ слишком мало; рекомендуется 2 ГБ |
OPENCLAW_STATE_DIR = "/data" | Сохранение состояния на volume |
3) Настройка секретов
# Обязательно: токен шлюза (для non-loopback привязки)
fly secrets set OPENCLAW_GATEWAY_TOKEN=$(openssl rand -hex 32)
# API-ключи провайдеров моделей
fly secrets set ANTHROPIC_API_KEY=sk-ant-...
# Опционально: другие провайдеры
fly secrets set OPENAI_API_KEY=sk-...
fly secrets set GOOGLE_API_KEY=...
# Токены каналов
fly secrets set DISCORD_BOT_TOKEN=MTQ...
Замечания:
- Non-loopback привязка (
--bind lan) требуетOPENCLAW_GATEWAY_TOKENдля безопасности. - Обращайтесь с токенами как с паролями.
- Используйте переменные окружения вместо файла конфигурации для всех API-ключей и токенов. Так секреты не попадут в
openclaw.json, откуда могут быть случайно раскрыты или залогированы.
4) Развёртывание
fly deploy
Первое развёртывание собирает Docker-образ (~2-3 минуты). Последующие — быстрее.
Проверка после развёртывания:
fly status
fly logs
Ожидаемый вывод:
[gateway] listening on ws://0.0.0.0:3000 (PID xxx)
[discord] logged in to discord as xxx
5) Создание файла конфигурации
Подключитесь к машине по SSH:
fly ssh console
Создайте каталог и файл конфигурации:
mkdir -p /data
cat > /data/openclaw.json << 'EOF'
{
"agents": {
"defaults": {
"model": {
"primary": "anthropic/claude-opus-4-6",
"fallbacks": ["anthropic/claude-sonnet-4-5", "openai/gpt-4o"]
},
"maxConcurrent": 4
},
"list": [
{
"id": "main",
"default": true
}
]
},
"auth": {
"profiles": {
"anthropic:default": { "mode": "token", "provider": "anthropic" },
"openai:default": { "mode": "token", "provider": "openai" }
}
},
"bindings": [
{
"agentId": "main",
"match": { "channel": "discord" }
}
],
"channels": {
"discord": {
"enabled": true,
"groupPolicy": "allowlist",
"guilds": {
"YOUR_GUILD_ID": {
"channels": { "general": { "allow": true } },
"requireMention": false
}
}
}
},
"gateway": {
"mode": "local",
"bind": "auto"
},
"meta": {
"lastTouchedVersion": "2026.1.29"
}
}
EOF
Примечание: При OPENCLAW_STATE_DIR=/data путь к конфигурации — /data/openclaw.json.
Примечание: Токен Discord можно задать двумя способами:
- Переменная окружения:
DISCORD_BOT_TOKEN(рекомендуется для секретов) - Файл конфигурации:
channels.discord.token
При использовании переменной окружения добавлять токен в конфигурацию не нужно. Шлюз автоматически читает DISCORD_BOT_TOKEN.
Перезапуск для применения:
exit
fly machine restart <machine-id>
6) Доступ к шлюзу
Control UI
Откройте в браузере:
fly open
Или перейдите на https://my-openclaw.fly.dev/
Вставьте токен шлюза (из OPENCLAW_GATEWAY_TOKEN) для авторизации.
Логи
fly logs # Логи в реальном времени
fly logs --no-tail # Недавние логи
SSH-консоль
fly ssh console
Решение проблем
«App is not listening on expected address»
Шлюз привязывается к 127.0.0.1 вместо 0.0.0.0.
Исправление: Добавьте --bind lan в команду процесса в fly.toml.
Health checks не проходят / connection refused
Fly не может достучаться до шлюза на настроенном порту.
Исправление: Убедитесь, что internal_port совпадает с портом шлюза (задайте --port 3000 или OPENCLAW_GATEWAY_PORT=3000).
OOM / проблемы с памятью
Контейнер постоянно перезапускается или завершается. Признаки: SIGABRT, v8::internal::Runtime_AllocateInYoungGeneration или тихие перезапуски.
Исправление: Увеличьте память в fly.toml:
[[vm]]
memory = "2048mb"
Или обновите существующую машину:
fly machine update <machine-id> --vm-memory 2048 -y
Примечание: 512 МБ слишком мало. 1 ГБ может работать, но возможен OOM под нагрузкой или с подробным логированием. Рекомендуется 2 ГБ.
Проблемы с lock-файлом шлюза
Шлюз отказывается запускаться с ошибкой «already running».
Это происходит при перезапуске контейнера, когда PID lock-файл остался на volume.
Исправление: Удалите lock-файл:
fly ssh console --command "rm -f /data/gateway.*.lock"
fly machine restart <machine-id>
Lock-файл находится в /data/gateway.*.lock (не в подкаталоге).
Конфигурация не читается
При использовании --allow-unconfigured шлюз создаёт минимальную конфигурацию. Ваш файл /data/openclaw.json должен быть прочитан при перезапуске.
Проверьте наличие конфигурации:
fly ssh console --command "cat /data/openclaw.json"
Запись конфигурации через SSH
Команда fly ssh console -C не поддерживает перенаправление shell. Для записи файла:
# echo + tee (pipe с локального на удалённый)
echo '{"your":"config"}' | fly ssh console -C "tee /data/openclaw.json"
# Или через sftp
fly sftp shell
> put /local/path/config.json /data/openclaw.json
Примечание: fly sftp может не сработать, если файл уже существует. Сначала удалите:
fly ssh console --command "rm /data/openclaw.json"
Состояние не сохраняется
Если учётные данные или сессии теряются после перезапуска, каталог состояния записывается в файловую систему контейнера.
Исправление: Убедитесь, что OPENCLAW_STATE_DIR=/data задан в fly.toml, и переразверните.
Обновление
# Получить последние изменения
git pull
# Переразвернуть
fly deploy
# Проверить состояние
fly status
fly logs
Обновление команды машины
Если нужно изменить команду запуска без полного переразвёртывания:
# Получить ID машины
fly machines list
# Обновить команду
fly machine update <machine-id> --command "node dist/index.js gateway --port 3000 --bind lan" -y
# Или с увеличением памяти
fly machine update <machine-id> --vm-memory 2048 --command "node dist/index.js gateway --port 3000 --bind lan" -y
Примечание: После fly deploy команда машины может сброситься к значению из fly.toml. Если вы вносили ручные изменения, примените их заново после развёртывания.
Приватное развёртывание (защищённое)
По умолчанию Fly выделяет публичные IP, делая шлюз доступным по адресу https://your-app.fly.dev. Это удобно, но означает, что ваше развёртывание обнаруживается интернет-сканерами (Shodan, Censys и др.).
Для защищённого развёртывания без публичного доступа используйте приватный шаблон.
Когда использовать приватное развёртывание
- Вы делаете только исходящие вызовы/сообщения (без входящих webhook)
- Вы используете ngrok или Tailscale для webhook-callback’ов
- Вы обращаетесь к шлюзу через SSH, прокси или WireGuard
- Вы хотите скрыть развёртывание от интернет-сканеров
Настройка
Используйте fly.private.toml вместо стандартной конфигурации:
# Развёртывание с приватной конфигурацией
fly deploy -c fly.private.toml
Или переведите существующее развёртывание:
# Просмотр текущих IP
fly ips list -a my-openclaw
# Освобождение публичных IP
fly ips release <public-ipv4> -a my-openclaw
fly ips release <public-ipv6> -a my-openclaw
# Переход на приватную конфигурацию
fly deploy -c fly.private.toml
# Выделение приватного IPv6
fly ips allocate-v6 --private -a my-openclaw
После этого fly ips list должен показывать только IP типа private:
VERSION IP TYPE REGION
v6 fdaa:x:x:x:x::x private global
Доступ к приватному развёртыванию
Публичного URL нет, поэтому используйте один из этих методов:
Вариант 1: Локальный прокси (проще всего)
# Проброс локального порта 3000 к приложению
fly proxy 3000:3000 -a my-openclaw
# Затем откройте http://localhost:3000 в браузере
Вариант 2: WireGuard VPN
# Создание конфигурации WireGuard (однократно)
fly wireguard create
# Импортируйте в клиент WireGuard, затем обращайтесь по внутреннему IPv6
# Пример: http://[fdaa:x:x:x:x::x]:3000
Вариант 3: Только SSH
fly ssh console -a my-openclaw
Webhook’и с приватным развёртыванием
Если нужны webhook-callback’и (Twilio, Telnyx и др.) без публичного доступа:
- Туннель ngrok — запустите ngrok внутри контейнера или как sidecar
- Tailscale Funnel — откройте определённые пути через Tailscale
- Только исходящие — некоторые провайдеры (Twilio) работают для исходящих вызовов без webhook’ов
Пример конфигурации голосовых вызовов с ngrok:
{
"plugins": {
"entries": {
"voice-call": {
"enabled": true,
"config": {
"provider": "twilio",
"tunnel": { "provider": "ngrok" },
"webhookSecurity": {
"allowedHosts": ["example.ngrok.app"]
}
}
}
}
}
}
Туннель ngrok работает внутри контейнера и предоставляет публичный URL для webhook без раскрытия самого приложения Fly. Задайте webhookSecurity.allowedHosts с публичным хостом туннеля, чтобы forwarded host headers принимались.
Преимущества безопасности
| Аспект | Публичное | Приватное |
|---|---|---|
| Интернет-сканеры | Обнаруживают | Скрыто |
| Прямые атаки | Возможны | Блокированы |
| Доступ к Control UI | Браузер | Прокси/VPN |
| Доставка webhook | Прямая | Через туннель |
Замечания
- Fly.io использует архитектуру x86 (не ARM)
- Dockerfile совместим с обеими архитектурами
- Для onboarding WhatsApp/Telegram используйте
fly ssh console - Постоянные данные хранятся на volume в
/data - Signal требует Java + signal-cli; используйте собственный образ и выделите минимум 2 ГБ памяти.
Стоимость
При рекомендуемой конфигурации (shared-cpu-2x, 2 ГБ RAM):
- ~$10-15/месяц в зависимости от использования
- Бесплатный тариф включает некоторый лимит
Подробности — Fly.io pricing.