Введение
Привет, Хабр! Являюсь давним пользователем маршрутизаторов Keenetic/Netcraze. В свое время подкупили надежность устройств, широкие возможности программного обеспечения, оперативная техническая поддержка, большое сообщество пользователей возможность установки дополнительных пакетов через среду Entware. В относительно недавнем прошлом производитель строил свои устройства на базе mips/mipsel чипов, таким образом, несколько таких устройств оказались у меня в руках.
Дополнительные пакеты в репозитории среды Entware позволяют решать массу задач. Я в свою очередь решил использовать ее для решения проблем деградации сети Интернет в текущем месте проживания.

В своих поисках остановился на программе Xray. Помимо исходного кода, авторы любезно предоставляют свой продукт собраным в виде консольной программы под различные платформы и архитектуры, включая mips на linux. Ничего не имею против консоли, но необходимость редактировать достаточно большие json-файлы в поике работоспособной конфигурации, при появлении нововых деградаций, немного удрачает. Особенно когда знаешь, что графические приложения, основанные на исходном коде Xray, умеют конфигурироваться с помощью url-ов или qr-кодов. Поэтому решил найти решение с графическим веб-инфтерфейсом в репозиториях на которые ссылаются авторы Xray. Подавляющее их большинство написано на языке Go и в бинарном виде поставляется только для архитектур x86_64, arm, s390. Что вполне достаточно для типового VPS/VDS, но не для нашего встраивоемого устройства. Исправим эту оплошность :-)
Идеальный вариант
Первая попытка
Среди многообразия вышеупомянутых приложений, было выбрано tx-ui из-за минимизации зависимостей от внешних СУБД и скриптов по настройке, которые по-умолчанию рассчитаны на использование systemd.
Компилятор Go предоставляет возможности по кросс-компиляции из коробки для большого количества архитектур через выставление переменных окружения GOARCH и GOOS. На момент написания статьи есть проблемы с компиляцией под MIPS на версии 1.26, поэтому пользоваться будем версией 1.27.8. Устанавливаем, воспользовавшись инструкцией с официального сайта.
Скачиваем архив с исходным кодом со страницы релизов в github, распаковываем, переходим в директорию:
mkdir habr_mipscd habr_mips/wget https://github.com/AghayeCoder/tx-ui/archive/refs/tags/v0.6.9.tar.gztar -xzf v0.6.9.tar.gz cd tx-ui-0.6.9/
Выставляем переменные окружения, собираем:
GOOS=linux GOARCH=mipsle go build 'main.go'
Проверяем формат собранного файла:
file mainmain: ELF 32-bit LSB executable, MIPS, MIPS32 version 1 (SYSV), statically linked, BuildID[sha1]=e539635e58a2b8b87f24e4590d1109ed8e0eb99c, with debug_info, not stripped
32-bit LSB executable, MIPS, MIPS32 – сообщает о том что ELF-файл собран для little endian 32-разрядной архитектуры MIPS.
Переносим файл любым доступным способом на маршрутизатор, выполняем его и натыкаемся на ошибку:
./main 2026/03/15 12:11:00 Starting x-ui 0.6.9 2026/03/15 12:11:00 Error initializing database: Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work. This is a stub
Поверхностный поиск проблемы сообщает о том, что мы должны выставить переменную окружения CGO_ENABLED=1 и убедиться в том, что компилятор gcc установлен. Наверное самым простым способом будет установить обертку над gcc для сборки mips приложений на x86. Но на текущий момент нет ясности в том, что нам не понадобиться собирать зависимости с динамическим подключением библиотек. Этот момент важен, так как система Entware установлена по пути /opt, что не даст нам найти /opt/bin/ld по пути /bin/ld для поиска библиотек из Entware.
Вторая попытка
Подготовительный этап
Для исключения проблем, которые могут гипотетически возникнуть при необходимости подключения зависимостей динамически, перейдем к более консервативному варианту получения обертки над компилятором gcc. Для этого воспользуемся инструкцией по сборке OpenWRT-пакетов из исходных кодов из репозитория Entware, а также ссылками на построение SDK с сайта OpenWRT: 1, 2.
Для сборки я использовал LXC-контейнер с окружением Debian 11, так как вероятно Entware базируется на OpenWRT 19.07 или ниже и ему для сборки требуется Python 2.7.
Сборка toolchain
Устанавливаем следующие зависимости для сборки:
sudo apt install build-essential ccache ecj fastjar file g++ gawk \gettext git java-propose-classpath libelf-dev libncurses5-dev \libncursesw5-dev libssl-dev python python2.7-dev python3 unzip wget \python3-distutils python3-setuptools python3-dev rsync subversion \swig time xsltproc zlib1g-dev g++-multilib p7zip-full
Скачиваем репозиторий и открываем его директорию:
git clone https://github.com/Entware/Entware.git && cd Entware
Обновляем скрипты сборки:
make package/symlinks
Копируем конфигурационный файл для сборки под архитектуру mipsel:
cp -iv configs/mipsel-3.4.config .config
Собираем оставшиеся инструменты для хост-системы:
make -j$(nproc) tools/install
Тулчейн:
make -j$(nproc) toolchain/install
Системные пакеты для целевой системы:
make -j$(nproc) target/compile
Если на каком-то из предыдущих 3 этапов возникает ошибка, следует перезапустить команду с параметром -j1 вместо -j$(nproc) и дополнительным параметром V=sc, например:
make -j1 target/compile V=sc
Если такая замена не помагает, то придется разбираться с проблемой с помощью поисковых систем.
При успешном выполнении команд, в директории staging_dir/toolchain-mipsel_mips32r2_gcc-8.4.0_glibc-2.27/bin будут располагаться исполняемые файлы с префиксом mipsel-openwrt-linux*.
Список исполняемых файлов
~/Entware/staging_dir/toolchain-mipsel_mips32r2_gcc-8.4.0_glibc-2.27/bin$ ls | grep mipsmipsel-openwrt-linux-addr2linemipsel-openwrt-linux-armipsel-openwrt-linux-asmipsel-openwrt-linux-c++mipsel-openwrt-linux-c++filtmipsel-openwrt-linux-cppmipsel-openwrt-linux-elfeditmipsel-openwrt-linux-g++mipsel-openwrt-linux-gccmipsel-openwrt-linux-gcc-8.4.0mipsel-openwrt-linux-gcc-armipsel-openwrt-linux-gcc-nmmipsel-openwrt-linux-gcc-ranlibmipsel-openwrt-linux-gcovmipsel-openwrt-linux-gcov-dumpmipsel-openwrt-linux-gcov-toolmipsel-openwrt-linux-gnu-addr2linemipsel-openwrt-linux-gnu-armipsel-openwrt-linux-gnu-asmipsel-openwrt-linux-gnu-c++mipsel-openwrt-linux-gnu-c++filtmipsel-openwrt-linux-gnu-cppmipsel-openwrt-linux-gnu-elfeditmipsel-openwrt-linux-gnu-g++mipsel-openwrt-linux-gnu-gccmipsel-openwrt-linux-gnu-gcc-8.4.0mipsel-openwrt-linux-gnu-gcc-armipsel-openwrt-linux-gnu-gcc-nmmipsel-openwrt-linux-gnu-gcc-ranlibmipsel-openwrt-linux-gnu-gcovmipsel-openwrt-linux-gnu-gcov-dumpmipsel-openwrt-linux-gnu-gcov-toolmipsel-openwrt-linux-gnu-gprofmipsel-openwrt-linux-gnu-ldmipsel-openwrt-linux-gnu-ld.bfdmipsel-openwrt-linux-gnu-nmmipsel-openwrt-linux-gnu-objcopymipsel-openwrt-linux-gnu-objdumpmipsel-openwrt-linux-gnu-ranlibmipsel-openwrt-linux-gnu-readelfmipsel-openwrt-linux-gnu-sizemipsel-openwrt-linux-gnu-stringsmipsel-openwrt-linux-gnu-stripmipsel-openwrt-linux-gprofmipsel-openwrt-linux-ldmipsel-openwrt-linux-ld.bfdmipsel-openwrt-linux-nmmipsel-openwrt-linux-objcopymipsel-openwrt-linux-objdumpmipsel-openwrt-linux-ranlibmipsel-openwrt-linux-readelfmipsel-openwrt-linux-sizemipsel-openwrt-linux-stringsmipsel-openwrt-linux-strip
Теперь когда необходимые компиляторы получены, вернемся к сборке Go приложения.
Сборка
Модифицируем команду которую использовали выше для сборки Go приложения, добавив в нее следующие параметры:
GOMIPS=softfloat – добавляем программную эмуляцию вычислений с плавающей точкой
CGO_ENABLED=1 – переменная окружения, которая включает поддержку cgo в Go, позволяя коду Go взаимодействовать с библиотеками C.
CC=/home/user/Entware/staging_dir/toolchain-mipsel_mips32r2_gcc-8.4.0_glibc-2.27/bin/mipsel-openwrt-linux-gnu-gcc – переменная окружения, которая задает путь до компилятора gcc (нужен для работы CGO_ENABLED)
CXX=/home/user/Entware/staging_dir/toolchain-mipsel_mips32r2_gcc-8.4.0_glibc-2.27/bin/mipsel-openwrt-linux-gnu-g++ – переменная окружения, которая задает путь до компилятора g++ (нужен для работы CGO_ENABLED)
-ldflags=‘-s -w’ – флаги компиляторам: отключение таблицы символов и генерации отладочной информации в исполняемом файле.
GOOS=linux GOARCH=mipsle GOMIPS=softfloat CGO_ENABLED=1 CC=/home/user/Entware/staging_dir/toolchain-mipsel_mips32r2_gcc-8.4.0_glibc-2.27/bin/mipsel-openwrt-linux-gnu-gcc CXX=/home/user/Entware/staging_dir/toolchain-mipsel_mips32r2_gcc-8.4.0_glibc-2.27/bin/mipsel-openwrt-linux-gnu-g++ go build -ldflags='-s -w' 'main.go'
На выходе получаем файл main:
file mainmain: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /opt/lib/ld.so.1, BuildID[sha1]=2e0163cb60d026a4edd6d5a8dfe227001a2675cb, for GNU/Linux 3.2.0, stripped
Конфигурация приложения на устройстве
Переносим собранный файл любым удобным способом на конечное устройство (или можно использовать эмулятор – про него возможно то же стоит статью написать) и переименовываем его в оригинальное название:
mv main x-ui
Первоначальный запуск выполняем для уточнения доступа к веб-панели
./x-ui setting -showcurrent panel settings as follows:Warning: Panel is not secure with SSLhasDefaultCredential: trueport: 2053webBasePath: /
По информации [из github] (https://github.com/AghayeCoder/tx-ui/blob/main/README.ru_RU.md), defaultCredential следующие:
Имя пользователя: admin Пароль: admin
Запуск приложения производим вместе с заданием переменной окружения XUI_DB_FOLDER=/opt/etc/x-ui, так как путь к директории с файлом БД по умолчанию /etc/x-ui ведет в read-only для Entware раздел.
XUI_DB_FOLDER=/opt/etc/x-ui ./x-ui
Далее в открываем браузер, вводим туда адрес устройства, порт и webBasePath (если задан) и видим следующую страницу


Считаем, что приложение работоспособно. Конфигурирование приложения не буду затрагивать, так как оно происходит похожим образом как для 3x-ui или аналогичных (примеры можно найти на различных сетевых ресурсах, включая Хабр).
Добавляем скрипт автозапуска в /opt/etc/init.d. Файл должен называться SXXимя, где XX -- приоритет запуска службы (чем больше номер -- тем позже запуск).
#!/bin/sh ENABLED=yes PROCS=x-ui ARGS="run" PREARGS="XUI_DB_FOLDER=/opt/etc/x-ui" DESC=$PROCS PATH=/opt/sbin:/opt/bin:/opt/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/opt/tx-ui #. /opt/etc/init.d/rc.func #OPID=$(pgrep x-ui) #echo $OPID daemon_status () { [ -n "`pidof x-ui`" ] } start() { echo "starting tx-ui..." cd /opt/opt/tx-ui export $PREARGS $PROCS $ARGS & } stop() { echo "stopping tx-ui..." PID=$(pidof x-ui) kill $PID } status() { if daemon_status; then echo "PID of tx-ui is $(pidof x-ui)" else echo "tx-ui is not running" fi } case "$1" in start) start ;; stop) stop ;; restart) stop sleep 3 start ;; status) status ;; *) echo "Usage: $0 (start|stop|restart|status)" exit 1 ;; esac exit 0
Таким образом мы собрали и развернули Go приложение для архитектуры mips.
