Блог Clearway

3x-ui не работает: пошаговая диагностика для оператора

Коротко

Фраза «3x ui не работает» скрывает четыре разных отказа, и лечатся они по-разному: (1) не открывается панель — сервис x-ui, порт, webBasePath или файрвол; (2) не стартует инбаунд — ядро Xray не поднялось из-за битого JSON, занятого порта или слишком старой версии core; (3) 3x ui не подключается у клиентов — расходятся path / mode / extra / security между инбаундом и ссылкой; (4) коннект встаёт и рвётся через минуту — рестарт ядра при сохранении, limitIp, буферизация на фронте, забитый диск или OOM. Порядок диагностики всегда один: systemctl status x-uijournalctl -u x-ui -n 200ss -ltnp | grep xray./xray-linux-amd64 run -test -config /usr/local/x-ui/bin/config.json → и только потом правки в GUI. Отдельный случай: локально всё зелёное, curl снаружи отвечает, а у части абонентов коннекта нет — это не ошибка 3x-ui, а блокировка IP ноды.

Сначала локализуйте слой, потом чините

Главная ошибка при разборе «3x ui не работает» — начинать с перезапуска панели и пересоздания инбаунда. В 3x-ui два независимых процесса: панель (Go-приложение, systemd-юнит x-ui) и ядро Xray, которое панель запускает дочерним процессом с собранным конфигом /usr/local/x-ui/bin/config.json. Панель может прекрасно открываться, пока ядро лежит, и наоборот.

Первые команды на сервере:

systemctl status x-ui --no-pager
journalctl -u x-ui -n 200 --no-pager
ss -ltnp | grep -E 'x-ui|xray' # видно сразу: слушает панель, слушают ли инбаунды
ls -la /usr/local/x-ui/bin/ # xray-бинарь, config.json, geo-файлы, логи

Если панель в Docker:

docker ps -a | grep 3x-ui
docker logs --tail 200 3x-ui

3x-ui пишет stderr ядра в свой systemd-журнал, поэтому реальная причина отказа инбаунда почти всегда там же, а не в UI. Строки failed to parse json config, address already in use, failed to load geoip — это ядро, а не панель.

Что видит операторСлойКуда смотреть
Браузер не открывает панельСервис x-ui / сетьsystemctl status x-ui, ss -ltnp, файрвол
Панель открыта, Xray «not running»Ядро Xrayjournalctl -u x-ui, run -test
Инбаунд зелёный, клиент не коннектитсяПараметры транспортасверка инбаунда и клиентской ссылки
Коннект есть, через 10–60 сек обрывЛимиты, рестарты, фронтlimitIp, access.log, буферизация
Локально работает, у абонентов нетБлокировка IPпроверка ноды из мобильной сети

Идите по таблице сверху вниз: правка extra не поможет, если ядро вообще не стартует. И до любых экспериментов сделайте бэкап базы — в ней все инбаунды, клиенты и настройки панели:

cp /etc/x-ui/x-ui.db /root/x-ui.db.$(date +%F).bak
# откат: systemctl stop x-ui && cp /root/x-ui.db.ДАТА.bak /etc/x-ui/x-ui.db && systemctl start x-ui

Панель 3x-ui не открывается

Текст ошибки в браузере почти однозначно указывает на причину — не игнорируйте его.

Ошибка браузераНаиболее вероятная причина
ERR_CONNECTION_REFUSEDСервис лежит или слушает другой порт
Бесконечная загрузка / таймаутПорт закрыт: ufw, iptables, security group хостера
404 page not foundНеверный webBasePath — в сборках 2.x он генерируется случайным
ERR_SSL_PROTOCOL_ERROR / «сайт не отправил данные»Заходите по https на панель без сертификата или по http на панель с TLS
Панель грузится, логин не принимаетСброшенные креды, реже — повреждённая SQLite-база

Посмотреть, что панель реально о себе думает:

/usr/local/x-ui/x-ui setting -show true

Набор флагов CLI отличается между сборками — если команда ругается, сверьтесь с /usr/local/x-ui/x-ui help или зайдите в интерактивное меню командой x-ui (пункты «показать настройки», «сбросить логин/пароль», «сбросить web base path»; нумерация пунктов от версии к версии меняется, ориентируйтесь по названиям).

URL собирайте строго по выводу: http(s)://IP:PORT/<webBasePath>/. Завершающий слэш обязателен — без него часть сборок отдаёт 404.

Восстановление доступа без переустановки:

/usr/local/x-ui/x-ui setting -port 2053
/usr/local/x-ui/x-ui setting -username admin -password 'НовыйПароль'
/usr/local/x-ui/x-ui setting -webBasePath /panel/
systemctl restart x-ui

Проверка изнутри сервера отделяет «панель мертва» от «сеть не пускает»:

curl -sI http://127.0.0.1:2053/panel/ | head -1

Локально 200/307, а снаружи таймаут — дело в файрволе. Открывать порт панели всему интернету не нужно: ограничьте его своим адресом или ходите через SSH-туннель, а наружу оставьте только порты инбаундов.

ufw allow from ВАШ_IP to any port 2053 proto tcp
# либо туннель, панель вообще не торчит наружу:
ssh -L 2053:127.0.0.1:2053 root@SERVER

Частые прикладные случаи: истёк сертификат панели (Let's Encrypt не продлился — панель по https не открывается, по http на том же порту тоже, пока не снимете TLS в настройках); контейнер в состоянии Restarting — почти всегда не примонтирован том с базой (./db/:/etc/x-ui/) или каталог создан с чужими правами. Если подозреваете битую базу: sqlite3 /etc/x-ui/x-ui.db 'PRAGMA integrity_check;'.

Инбаунд не стартует: один битый инбаунд роняет все

Ключевой факт про 3x-ui, который экономит часы: панель собирает из всех инбаундов один config.json и запускает одно ядро. Один невалидный инбаунд роняет процесс целиком — вместе с ним отваливаются все остальные инбаунды и все клиенты. Поэтому «у половины юзеров пропал доступ после того, как я добавил новый инбаунд» — это не совпадение.

Валидация конфига руками (имя бинаря — под вашу архитектуру):

cd /usr/local/x-ui/bin
./xray-linux-amd64 version
./xray-linux-amd64 run -test -config./config.json
jq../config.json > /dev/null # покажет строку с ошибкой JSON
Что в логеПричинаФикс
failed to parse json configБитый JSON после ручной правки в режиме </>jq. — почти всегда лишняя запятая
address already in useПорт занят nginx/caddy/другим инбаундом`ss -ltnp \grep:PORT`, сменить или освободить
unknown network type / инбаунд игнорируетсяЯдро не знает транспорт (xhttp на старой сборке)Обновить Xray в Panel Settings → Xray Configs
failed to load geoip / open geoip.datGeo-файлы не докачались после обновленияПункт меню x-ui с обновлением geo, затем рестарт
Ядро стартует и падает в циклеOOM или переполненный диск`dmesg -T \grep -i oom, df -h /`
exec format errorСкачан бинарь не под ту архитектуруuname -m, file./xray-linux-*

Про версии честно: транспорт xhttp появился в Xray-core ветки 24.11 (переименование splithttp), там же — режимы auto / packet-up / stream-up / stream-one. На ядре 1.8.x инбаунд с "network": "xhttp" не поднимется в принципе, и правки полей в GUI это не изменят. Поэтому version — раньше всего остального.

Вторая частая ловушка — поле flow. xtls-rprx-vision живёт только на raw/tcp с TLS или Reality. Проставили его на инбаунд с ws, grpc или xhttp (или потянули из старой клиентской ссылки) — соединение не установится. Для xhttp flow должен быть пустым.

И отдельно: если инбаунд создавали в JSON-режиме, храните эталонный streamSettings вне панели. При повторном сохранении через обычную форму 3x-ui нормализует структуру и, по наблюдениям, может потерять поля, которых в форме нет — в первую очередь содержимое xhttpSettings.extra. Общий разбор ошибок самого Xray-core (400/404, handshake, версии клиентов) у нас есть отдельной статьёй — здесь только то, что специфично для 3x-ui.

3x ui не подключается: рассинхрон инбаунда и ссылки

Панель зелёная, ядро живое, порт слушает — клиент висит на «connecting». По наблюдениям это почти всегда не ошибка 3x-ui, а расхождение параметров между инбаундом и ссылкой: Xray на ноде просто не узнаёт запрос и молчит, внятной ошибки пользователь не увидит.

ПараметрНа ноде (инбаунд)В клиентской ссылкеКомментарий
UUIDsettings.clients[].idчасть до @опечатка = тихий отказ
Портportпосле : (за фронтом — 443)за CDN клиент всегда идёт на 443
Транспортnetworktype=xhttpxhttp, без вариантов
ПутьxhttpSettings.pathpath= в URL-кодировкеслэши, регистр, завершающий /
РежимxhttpSettings.modemode=при аплинке через GET обязателен packet-up
extraxhttpSettings.extraодноимённые поля клиентадолжны совпадать полностью
Хост/SNIзависит от фронтаhost=, sni=за CDN — домен фронта, не IP
TLSsecuritysecurity=на origin за CDN — none, у клиента — tls

Про режим отдельно, потому что это самая дорогая по времени ошибка. Yandex CDN не пропускает POST, поэтому XHTTP-аплинк уходит методом GET, а GET у Xray разрешён только при явно указанном mode: packet-up. Не указали режим или оставили автоопределение — в одном приложении конфиг «работает», в другом молча нет, и выглядит это как плавающая ошибка 3x-ui. Так же критично совпадение extra: значения на ноде и в клиенте должны быть идентичны, а экзотические поля обфускации лучше не использовать вовсе — они ломают совместимость между версиями Xray и между клиентами.

Ловушка именно 3x-ui: панель исходит из того, что клиент подключается туда же, где стоит сервер, и генерирует ссылку/QR прямо на IP ноды. Если вход организован через CDN или reverse-proxy, эта ссылка не годится — она ведёт мимо фронта. Шаблон клиентского URL с доменом фронта собирается вручную один раз на инбаунд, дальше меняется только UUID.

Проверка живости инбаунда снаружи, до всяких клиентов:

curl -sv -o /dev/null --max-time 5 http://IP_НОДЫ:ПОРТ/ваш/путь/ 2>&1 | tail -5

Любой HTTP-ответ (400, 404) означает: порт открыт, ядро слушает. Connection refused — ядро не поднялось или порт закрыт. Таймаут — пакеты не доходят: security group хостера, DROP в iptables или фильтрация на пути.

Два частных случая, которые не про транспорт вообще:

  • Не подключается ровно один клиент. Смотрите его карточку в панели: исчерпанный лимит трафика или истёкший срок отключают клиента, ссылка при этом остаётся внешне валидной.
  • Не открывается подписка. Sub-сервис 3x-ui слушает свой порт (по умолчанию 2096) и включается отдельно от панели. Если у клиента «пустая подписка», проверьте ss -ltnp | grep 2096, открыт ли порт наружу и совпадает ли публичный URL подписки с тем, что раздаёте. Транспорт тут ни при чём.

Соединение поднимается и тут же рвётся

Отдельный класс отказов — диагностируется не там, где предыдущие.

  1. Рестарт ядра при каждом сохранении. 3x-ui пересобирает config.json и перезапускает Xray на любое изменение — добавили клиента, поправили инбаунд, и текущие сессии оборвались. Клиенты переподключаются сами за секунды, но десять правок подряд в час пик дают вал жалоб. Копите изменения и сохраняйте пачкой.
  2. Лимит по IP у клиента. limitIp считает адреса по access-логу Xray: если access-лог выключен, лимит либо не работает, либо ведёт себя непредсказуемо; если включён — пользователь с телефоном и ноутбуком одновременно отваливается. Симптом характерный: 30–60 секунд коннекта, отвал, потом снова работает. Проверяется обнулением лимита у конкретного клиента.
  3. Буферизация и idle-таймауты на фронте. Для xhttp это главный источник обрывов: промежуточный прокси копит поток вместо того, чтобы отдавать его сразу. На nginx нужны proxy_buffering off;, proxy_request_buffering off; и увеличенные proxy_read_timeout/proxy_send_timeout (300s и выше); на CDN-фронте — соответствующие параметры в extra, включая поведение SSE-заголовка.
  4. Диск, забитый логами. access.log Xray на нагруженной ноде растёт гигабайтами и лежит рядом с бинарём в /usr/local/x-ui/bin/. При No space left on device падает и ядро, и панель. Лечится logrotate либо уровнем warning и отключённым access-логом в Panel Settings → Xray Configs.
  5. OOM. VPS на 512–1024 МБ с сотней клиентов: ядро убивает процесс, systemd поднимает заново, у всех обрыв.
df -h /
du -sh /usr/local/x-ui/bin/*.log
dmesg -T | grep -i -E 'oom|killed process' | tail -10
journalctl -u x-ui --since '30 min ago' --no-pager | grep -iE 'restart|killed|panic'

Если в журнале ядро стартует каждые несколько минут без ваших действий — проблема в ресурсах или в падении процесса, а не в клиентах и не в транспорте. Лечить конфигом бесполезно.

Когда дело не в 3x-ui, а в блокировке IP

Последний по порядку, но не по частоте сценарий. Все проверки выше зелёные: панель открывается, ядро работает, curl снаружи отдаёт ответ, с домашнего Wi-Fi клиент подключается. А у части пользователей — глухо, чаще всего у тех, кто сидит с мобильного интернета или в регионе с ограничениями.

Это не ошибка 3x-ui. Пакеты до вашего IP не доходят, ядро о них не узнаёт — в логах Xray будет не «reject», а полное отсутствие соединений от этих пользователей. Отличительный признак именно асимметрия: одни сети работают, другие нет, при одном и том же конфиге.

# на ноде: приходят ли вообще входящие
journalctl -u x-ui -f | grep -i accepted
# со стороны клиента (мобильный интернет, режим модема)
curl -sv --max-time 5 http://IP_НОДЫ:ПОРТ/ 2>&1 | tail -3

Если из «здоровой» сети ответ есть, а с мобильной — таймаут, менять протокол, порт, SNI или пересоздавать ключи на том же адресе бесполезно: фильтруется IP, а не сигнатура. Вариантов два: переехать в подсеть, которая проходит фильтрацию (проверять каждую /24 отдельно — whitelist привязан к подсети, а не к хостеру целиком), либо поставить перед нодой вход на «белом» домене. Whitelist-CDN закрывает второй сценарий: нода остаётся на месте, клиенты идут на домен CDN-фронта, IP origin перестаёт быть точкой отказа. Настройку такого входа именно под 3x-ui — XHTTP-инбаунд, ручная сборка ссылки, файрвол на origin — мы разбирали отдельно.

Сводный чек-лист под руку:

СимптомОдна команда для проверкиКуда копать
Панель не открываетсяsystemctl status x-uiсервис, порт, webBasePath, файрвол, сертификат
Xray «not running»./xray-linux-amd64 run -test -config config.jsonJSON, порт, версия ядра, geo-файлы
Не подключается один клиенткарточка клиента в панелилимит трафика, срок, limitIp
Не подключаются всеcurl на порт инбаунда снаружитранспорт, path, mode, extra, TLS
Пустая подписка`ss -ltnp \grep 2096`sub-сервис, порт, публичный URL
Обрывы через минутуjournalctl -u x-ui --since '30 min ago'рестарты, OOM, диск, буферизация
Работает не во всех сетяхcurl с мобильного интернетаблокировка IP, /24, вход через CDN

Частые вопросы

3x-ui перестал работать сразу после обновления — что делать в первую очередь?

Разделите обновление панели и обновление ядра. Если после апдейта Xray инбаунды не поднимаются, в Panel Settings → Xray Configs можно вернуть предыдущую версию ядра — это самый быстрый откат; проверить результат сразу же: ./xray-linux-amd64 run -test -config /usr/local/x-ui/bin/config.json. Если сломалась панель, восстанавливайте базу: systemctl stop x-ui, положить бэкап в /etc/x-ui/x-ui.db, systemctl start x-ui. Бэкап делайте до обновления — cp /etc/x-ui/x-ui.db /root/x-ui.db.bak; в этом файле все инбаунды и клиенты, и переустановка панели с ним проходит без потерь.

Где в 3x-ui посмотреть логи Xray, а не панели?

Панель пишет в systemd: journalctl -u x-ui -n 200 --no-pager. Туда же попадает stderr ядра, поэтому ошибки старта Xray ищутся именно там. Отдельные access/error-логи включаются в Panel Settings → Xray Configs (секция log); путь по умолчанию относительный, файлы окажутся рядом с бинарём в /usr/local/x-ui/bin/. Уровень debug поднимайте только на время разбора и сразу возвращайте обратно — на нагруженной ноде он быстро съедает диск.

Инбаунд зелёный, порт слушает, но 3x ui не подключается ни у одного клиента. Почему?

Почти всегда рассинхрон между инбаундом и клиентской ссылкой: path, mode, содержимое extra или security. Сверьте по таблице из статьи, особенно mode=packet-up для XHTTP через CDN (у Yandex CDN нет POST, аплинк идёт GET, а GET разрешён только в packet-up) и полное совпадение extra на ноде и в клиенте. Вторая по частоте причина именно в 3x-ui — автогенерированная панелью ссылка при входе через CDN: она указывает на IP ноды и идёт мимо фронта.

Ошибка 3x ui «address already in use» — как найти, кто занял порт?

ss -ltnp | grep:ПОРТ покажет PID и имя процесса. Типовые виновники: nginx или caddy на 80/443, оставшийся от прошлой установки процесс xray, либо второй инбаунд в самой панели с тем же портом — 3x-ui не всегда предупреждает об этом при сохранении. Освободите порт (systemctl stop nginx или смена порта инбаунда) и перезапустите панель: systemctl restart x-ui — ядро поднимется вместе с ней.

Почему при добавлении одного клиента рвётся соединение у всех?

3x-ui на любое изменение конфигурации пересобирает единый config.json и перезапускает процесс Xray, поэтому активные сессии обрываются, а клиенты переподключаются автоматически за несколько секунд. Это штатное поведение, а не ошибка. Практический вывод: массовые правки инбаундов и добавление клиентов делайте пачками, а не по одному в час пик.

У клиента открывается панель, но подписка отдаёт пустую страницу — это тоже ошибка 3x-ui?

Обычно нет: sub-сервис в 3x-ui включается отдельно от панели и слушает свой порт (по умолчанию 2096). Проверьте, что он запущен (ss -ltnp | grep 2096), что порт открыт наружу и что публичный URL подписки совпадает с тем, что вы раздаёте пользователям. Если инбаунды при этом работают по прямой ссылке — транспорт и ядро ни при чём.

У меня всё работает на домашнем Wi-Fi, но не работает с мобильного интернета. Это баг 3x-ui?

Нет. Если конфиг один и тот же, а поведение зависит от сети абонента, дело в фильтрации на стороне оператора: до IP ноды пакеты не доходят, и в логах Xray этих попыток не будет вовсе. Смена порта, протокола или SNI на том же адресе ситуацию не меняет. Помогает либо переезд в подсеть, которая проходит фильтрацию (проверять конкретную /24, а не хостера целиком), либо вход через whitelist-CDN, когда клиент идёт на «белый» домен, а нода остаётся там, где стоит.

Whitelisted-вход для вашего VPN-сервиса

Clearway даёт «белый» CDN-вход перед вашей нодой — устойчивый к троттлингу операторов. Первые 10 ГБ бесплатно, без карты.

Попробовать →