Браузер OpenClaw на VPS: чому не працює і як виправити
«Маю величезні проблеми з VPS. Перевстановлюю OpenClaw вже 3-й чи 4-й раз.»
Це повідомлення з’явилося в OpenClaw Discord минулого місяця. Користувач був не єдиний. Прогортайте канали спільноти, і знайдете десятки варіацій на ту саму тему: інструмент браузера не працює, агент не може досягти Chromium, на VPS закінчується пам’ять, вчора все працювало, а сьогодні ні.
Якщо ви читаєте це, бо щойно шукали «OpenClaw браузер не працює VPS», ви в правильному місці. Ця стаття пояснює п’ять речей, що ламаються, чому вони взаємодіють у фруструючий спосіб, і як ми всі їх вирішили в Kubernetes-операторі OpenClaw.rocks, щоб вам більше ніколи не довелося займатися налаштуванням браузера.
Помилка, яку бачать усі
Найпоширеніше повідомлення про помилку в спільноті OpenClaw:
Can't reach the OpenClaw browser control service
(timed out after 15000ms)
Воно з’являється на Ubuntu, Debian, у Docker, на Hetzner, Hostinger, GCP та всюди, де намагаються запустити OpenClaw з автоматизацією браузера. Логи gateway кажуть «Browser control service ready.» Але коли агент намагається використати браузер, настає тайм-аут.
Помилка загальна. Причини ні. Є щонайменше п’ять різних режимів відмови, і ззовні вони виглядають ідентично.
Відмова 1: Snap Chromium і стіна AppArmor
На свіжовстановленому сервері Ubuntu 22.04+ команда which chromium-browser повертає /usr/bin/chromium-browser. Виглядає правильно. Але ні.
З Ubuntu 22.04 стандартний пакет Chromium це snap. Коли gateway OpenClaw намагається запустити цей бінарний файл через службу systemd, обмежувальний шар AppArmor блокує його. Snap-пакет не може відкрити порти налагодження Chrome DevTools Protocol (CDP) через пісочницю. Бінарний файл запускається, здається працює, а потім тихо не відкриває порт, який потрібен OpenClaw.
У логах побачите «Failed to start Chrome CDP on port 18800» або іноді нічого. Процес браузера запускається і вмирає до того, як напише хоч один рядок логу.
Рішення: встановити пакет .deb Google Chrome або використати автономний бінарний файл Chromium від Playwright з ~/.cache/ms-playwright/. Обидва обходять snap-пісочницю. Але рішення не очевидне. Виявлення браузера в OpenClaw сканує стандартні шляхи по порядку, знаходить snap-бінарний файл першим і намагається його використати. GitHub issue #4978 містить повний опис.
Відмова 2: Headless-налаштування за замовчуванням, що припускають дисплей
OpenClaw поставляється з headless: false та noSandbox: false як стандартними налаштуваннями браузера. Це має сенс на Mac або Windows з дисплеєм. На VPS дисплея немає. Без явної конфігурації Chromium намагається відкрити вікно на сервері відображення, якого не існує.
Дві зміни конфігурації вирішують проблему:
openclaw config set browser.headless true
openclaw config set browser.noSandbox true
Більшість VPS-посібників це згадують. Але якщо слідуєте стандартним інструкціям з встановлення OpenClaw, жоден з цих рядків не з’являється. Встановлюєте, пробуєте браузер, не працює. Шукаєте помилку. Знаходите статтю в блозі. Змінюєте конфігурацію. Перезапускаєте. І переходите до відмови номер три.
Відмова 3: Невидимий OOM kill
Одна вкладка Chromium з кількома відкритими сторінками споживає від 2 до 4 ГБ ОЗП. На VPS з 4 ГБ майже нічого не залишається для самого OpenClaw, операційної системи та інших запущених служб.
Коли в Linux закінчується пам’ять, OOM killer ядра завершує процес, що споживає найбільше пам’яті. Це Chromium. Процес гине. OpenClaw записує тайм-аут браузера. Немає звіту про збій, немає стеку викликів, немає ознаки, що пам’ять була проблемою.
Є й тонша версія цієї проблеми. Chromium запускає дочірні renderer-процеси для кожної вкладки. Якщо їх не очистити належним чином, вони накопичуються. Одна GitHub issue задокументувала 39 осиротілих renderer-процесів, що споживали 3,8 ГБ ОЗП на VPS, який мав мати достатньо запасу.
Можете перевірити постфактум командою dmesg | grep -i "oom\|killed\|chromium", але більшість людей не думає туди дивитися. Вони перезапускають OpenClaw, він працює кілька хвилин, і потім це повторюється.
Офіційна сторінка вимог до сервера рекомендує мінімум 4 ГБ для базового налаштування. Але це число передбачає відсутність автоматизації браузера. З увімкненим браузером 8 ГБ це реалістичний мінімум. На Hetzner це різниця між cpx22 (5 $/міс.) та cpx42 (17 $/міс.).
Відмова 4: Відсутня спільна пам’ять Docker
Якщо запускаєте OpenClaw у Docker (типово для розгортання на VPS), є ще одна пастка. Стандартний /dev/shm Docker складає 64 МБ. Chromium використовує спільну пам’ять для міжпроцесної комунікації. Коли вона закінчується, вкладки тихо падають або відображають порожні сторінки.
Рішення: один рядок у docker-compose.yml:
shm_size: '2gb'
Або змонтуйте явно:
volumes:
- /dev/shm:/dev/shm
Це не задокументовано в посібнику з налаштування OpenClaw. Це специфічна для Docker поведінка, яка впливає на будь-який додаток, що використовує Chromium, але якщо ви ніколи не розгортали headless-браузери в Docker, ви б не знали, що це шукати.
Відмова 5: Зіткнення портів, про які ніхто не попередив
Служба керування браузером OpenClaw працює на окремому порту від gateway. За замовчуванням це порт gateway плюс 2. Якщо ваш gateway на 18789, служба керування браузером має бути на 18791, а релей розширень на 18792.
У Docker, якщо відкриваєте лише порт 18789, служба керування браузером недоступна ззовні контейнера. Гірше того, gateway записує «Browser control service ready» навіть коли порт 18791 ніколи фактично не прив’язується. Issue #17584 простежив це до gateway, що імпортував неправильний модуль: такий, що записує повідомлення «ready» без запуску HTTP-сервера. Лог каже, що все добре. Порт мертвий.
У Kubernetes, якщо інший контейнер у тому ж pod вже використовує порт 9222 (стандартний CDP-порт), функція ensurePortAvailable() OpenClaw виявляє порт як зайнятий і відмовляється підключатися, навіть якщо зайняв саме той екземпляр Chromium, з яким OpenClaw має спілкуватися.
GitHub issue #10994 документує випадок, коли VPS-налаштування користувача працювало правильно. Потім, після кількох автоматизованих дій, CDP-порт застряг. Єдиним рішенням було знайти та вбити блукаючі процеси Chromium, що тримали порт.
Чому ці відмови накопичуються
Кожна з цих п’яти проблем має відоме рішення. Але вони взаємодіють. Вирішуєте проблему snap і натрапляєте на headless-налаштування за замовчуванням. Виправляєте конфігурацію і Chromium запускається. Працює десять хвилин, потім OOM killer вбиває. Додаєте swap, і тепер ліміт спільної пам’яті Docker спричиняє тихі помилки рендерингу. Виправляєте це і виявляєте, що порт 18791 не відкритий.
Цикл налагодження виглядає так: шукати помилку, знайти часткове виправлення, застосувати виправлення, натрапити на наступну помилку, повторити. Один користувач Discord описав перевстановлення всієї операційної системи «вже 3-й чи 4-й раз». Інший повідомив, що браузер був «нестабільний» після того, що вважав повним налаштуванням. Третій відкрив issue з простою назвою «Browser tool consistently fails on VPS».
Проблема не в тому, що кожне окреме виправлення складне. Проблема в тому, що їх п’ять, вони залежать від вашої конкретної операційної системи, менеджера пакетів, середовища виконання контейнерів і провайдера VPS, і одна помилка в ланцюжку означає, що браузер не працює.
Команда OpenClaw заслуговує на визнання за постійне виправлення пов’язаних помилок. Оманливий лог «ready», очищення осиротілих рендерерів та обробка CDP-порту покращилися в останніх версіях. Але upstream-виправлення адресують симптоми в коді OpenClaw. Вони не можуть встановити правильний Chromium на ваш сервер, налаштувати спільну пам’ять Docker або виділити достатньо ОЗП для автоматизації браузера. Це залишається вашою відповідальністю.
Як ми зламали Chromium тричі (і що ми дізналися)
Ми запускаємо кожного агента OpenClaw.rocks на Kubernetes з нашим відкритим оператором. Sidecar браузера зайняв у нас тижні. Ми зіткнулися з власною версією кожної описаної проблеми, плюс кілька, що з’являються лише в контексті оркестрації контейнерів.
Ідея була простою: запустити Chromium як окремий контейнер поруч з OpenClaw, з’єднаний через CDP. Один рядок у Custom Resource і браузер просто працює.
spec:
chromium:
enabled: true
Ось як цей один рядок насправді з’явився.
Збій 1: Неправильний користувач, файлова система лише для читання
Перша спроба запустила контейнер Chromium як UID 1001 з файловою системою root лише для читання. Найкраща практика безпеки. І повністю зламано. Образ browserless очікує UID 999 (blessuser), а Node.js при запуску викликає os.userInfo(), що завершується помилкою ENOENT, коли UID не має запису в /etc/passwd. Навіть після виправлення UID файлова система лише для читання блокувала Chrome від запису тимчасових файлів. Sidecar падав при кожному запуску до написання одного рядка логу. Issue #12 містить повну історію.
Збій 2: Стіна безпеки WebSocket
З контейнером, що нарешті працює, Chromium був активний, CDP відповідав на порті 9222, але OpenClaw відмовлявся його використовувати. Gateway прив’язався до LAN IP pod (потрібно для маршрутизації Kubernetes Service), а шар безпеки OpenClaw блокував нешифровані ws:// з’єднання до не-loopback адрес: «SECURITY ERROR: Gateway URL uses plaintext ws:// to a non-loopback address. Both credentials and chat data would be exposed to network interception.»
Легітимна перевірка безпеки. Але в Kubernetes pod всі контейнери ділять мережевий простір імен. Трафік між ними ніколи не залишає вузол. Ми не могли змінити перевірку безпеки OpenClaw, тому додали nginx reverse proxy sidecar, що слухає на всіх інтерфейсах і перенаправляє на gateway через loopback. Gateway залишається захищеним. Service залишається доступним. Issue #135 документує налагодження.
Збій 3: Зіткнення порту 3000
Chromium працював. Gateway мав proxy. Але браузер все ще не підключався. Образ browserless використовує порт 3000 за замовчуванням, що зіткнувся з внутрішньою службою керування браузером OpenClaw. Коли ми перемкнулися на порт 9222, ensurePortAvailable() OpenClaw виявила його як «використовуваний чимось іншим» і відмовилася підключатися, бо в спільному мережевому просторі імен порт sidecar виглядає локальним.
Рішення: використати IP-адресу pod (через Kubernetes Downward API) замість localhost для CDP URL. Не-loopback адреса каже OpenClaw використовувати режим remote/attach-only: підключитися до того, що вже працює, замість спроби запустити власний браузер. PR #183 вирішив це.
Результат: п’ять виправлень, застосованих автоматично
Кожен збій навчив нас чогось. Поточний оператор кодує все це:
Ізоляція sidecar. Chromium працює у власному контейнері. Без snap. Без Playwright. Без headless-прапорців. Образ browserless піклується про все.
Виділені ресурси. Sidecar отримує власні ліміти CPU та пам’яті (250m-1000m CPU, 512Mi-2Gi RAM за замовчуванням, налаштовується). Якщо Chromium перевищить ліміт пам’яті, Kubernetes перезапускає лише контейнер браузера. Ваш агент продовжує працювати.
Спільна пам’ять. Оператор автоматично монтує 1 ГБ том на основі пам’яті в /dev/shm. Без налаштування Docker shm_size.
Маршрутизація портів. IP pod для CDP URL активує віддалений режим. OpenClaw підключається до sidecar замість спроби зайняти порт. Конфлікт ensurePortAvailable() зникає.
Вбудоване виявлення анти-ботів. Багато сайтів виявляють headless Chromium за замовчуванням і блокують автоматизацію. Оператор підтримує extraArgs на Chromium sidecar, тож ви можете передавати прапорці як --disable-blink-features=AutomationControlled та користувацькі user agent без створення користувацького образу контейнера:
spec:
chromium:
enabled: true
extraArgs:
- "--disable-blink-features=AutomationControlled"
- "--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
- "--window-size=1920,1080"
Безпека без компромісів. Усі Linux-можливості видалені, ескалація привілеїв вимкнена, seccomp RuntimeDefault, non-root UID 999. Без --no-sandbox як root.
Що це означає для вас
Якщо запускаєте OpenClaw на VPS і браузер працює, вітаємо. Ви пройшли через п’ять різних режимів відмови і вийшли з іншого боку. Збережіть налаштування. Зробіть резервну копію конфігурації.
Якщо браузер не працює, або працює періодично, або вам набридло налагоджувати Chromium на VPS за 5 доларів, подумайте, скільки коштує ваш час.
OpenClaw.rocks запускає кожного агента на Kubernetes з оператором, описаним вище. Sidecar браузера попередньо налаштований. Пам’ять виділена. Порти маршрутизовані. Безпека посилена. Ви нічого не встановлюєте, нічого не налаштовуєте і нічого не налагоджуєте.
Ваш агент отримує браузер, що працює. Щоразу. Одразу готовий до використання.
П’ять виправлень коротко
Якщо хочете залишитися на самостійному хостингу, ось повний список:
- Замініть snap Chromium пакетом
.debGoogle Chrome або автономним бінарним файлом Playwright - Увімкніть headless-режим:
openclaw config set browser.headless trueтаbrowser.noSandbox true - Виділіть 8 ГБ+ ОЗП або додайте 4 ГБ swap для автоматизації браузера
- Змонтуйте спільну пам’ять у Docker:
shm_size: '2gb' - Відкрийте всі три порти: gateway, керування браузером (gateway + 2) та релей розширень (gateway + 3)
Або пропустіть список. Отримайте свого асистента на OpenClaw.rocks і залиште інфраструктуру нам.