• routerforge-v0.14.0 5f081a7a7b

    RouterForge 0.14.0
    Some checks failed
    CI / CI change scope (push) Has been cancelled
    CI / Fast release contracts (push) Has been cancelled
    CI / Publish validated stable promotion (push) Has been cancelled
    CI / test (push) Has been cancelled
    CI / Beta package build (aarch64-3.10) (push) Has been cancelled
    CI / Beta package build (mips-3.4) (push) Has been cancelled
    CI / Beta package build (mipsel-3.4) (push) Has been cancelled
    CI / Publish verified multiarch Beta (push) Has been cancelled
    CI / Publish rolling ARM64 Dev channel (push) Has been cancelled
    Stable

    FifthAce released this 2026-10-26 17:50:25 +03:00 | 0 commits to main since this release

    RouterForge — Stable 0.14.0

    Великие архитекторы собственного пиздеца

    Или как мы исправили собственные ошибки и почти убедили себя, что это достижение

    Знаете, что самое прекрасное в разработке программного обеспечения? Возможность бесконечно исправлять то, что ты сам же и нахуевертил. Это поистине уникальная профессия. Представьте себе хирурга, который сначала пришивает пациенту третью ногу, затем полгода разрабатывает инновационный метод её удаления, выпускает пресс-релиз о повышении качества медицинских услуг и получает профессиональную награду. В мире медицины его, вероятно, посадили бы. В IT ему повысили бы зарплату, назначили ведущим архитектором и предложили выступить на конференции с докладом «Наш путь к трёхногой микросервисной архитектуре».

    Вот примерно этим мы и занимались.

    В предыдущем Stable RouterForge получил новых менеджеров, новые возможности, улучшенную безопасность и достаточно инструментов, чтобы пользователь мог самостоятельно превратить домашний роутер в небольшой центр управления полётами. Мы были довольны. Пользователи тоже. Особенно мы. Потому что ничто так не укрепляет самооценку разработчика, как успешно завершившаяся сборка программы, которую он ещё не успел проверить в условиях, хотя бы отдалённо напоминающих реальную жизнь.

    А потом пользователи совершили совершенно непростительный поступок. Они начали пользоваться программой. Не просто устанавливать её ради красивых скриншотов, а действительно нажимать кнопки, менять настройки и ожидать результатов. Некоторые даже перезагружали роутеры, словно не понимали, насколько хрупким произведением искусства является современное программное обеспечение. Никакого уважения к психическому здоровью разработчика.

    Мы, разумеется, немедленно приступили к диагностике. Сначала изучили журналы. Потом исходники. Потом снова журналы. Потом документацию Keenetic. Потом документацию Entware. Потом начали подозревать, что документация тоже написана какими-то долбоёбами. Это было довольно смелое обвинение со стороны людей, которые сами регулярно объясняют собственный код фразой «ну там всё очевидно».

    Вскоре выяснилось самое неприятное: пользователи оказались правы. Более того, многие ошибки воспроизводились с совершенно оскорбительной стабильностью. Такой стабильности мы, собственно, и добивались от самой программы.

    Пришлось снова открывать редактор кода. И начался очередной сезон нашего любимого сериала — «Разработчик против последствий собственных решений». Предыдущие сезоны, напомним, закончились не столько победой, сколько временным прекращением огня.

    1. DNS Manager — великие архитекторы собственного пиздеца

    Знаете, почему пользователи так любят перезагружать роутеры? Потому что, в отличие от нас, они почему-то уверены, что после перезагрузки компьютер должен продолжать работать. Наивные люди. Они ещё не знают, что где-то между KeeneticOS и Entware сидит группа самопровозглашённых инженеров, которая способна написать несколько тысяч строк кода для управления DNS, но не способна с первого раза сообразить, что системная служба может быть ещё не готова.

    И когда на KN-1910 DNS Manager очередной раз отказался нормально запускаться, мы, конечно же, немедленно приступили к диагностике. То есть сначала обвинили Keenetic. Потом Entware. Потом ndmc. Потом порядок запуска служб. Потом, на всякий случай, законы термодинамики. И лишь спустя некоторое время начали осторожно подозревать, что проблема может заключаться в тех долбоёбах, которые всё это написали. Неприятная гипотеза. Крайне разрушительная для самооценки. Особенно когда выясняется, что эти долбоёбы — мы.

    Мы добавляли проверки, задержки, повторные запросы, восстановление состояния. Проводили испытания. Получали PASS. Радовались. А потом пользователь перезагружал роутер, и наша инженерная гордость снова отправлялась нахуй. В какой-то момент стало очевидно: если для запуска DNS требуется больше ритуалов, чем для вызова древнего шумерского демона, то проблема, возможно, не в роутере.

    Казалось бы, сама задача не представляет особой интеллектуальной сложности. Устройство включается, операционная система загружается, системные службы становятся доступны, DNS Manager начинает работать. Четыре последовательных действия. Даже микроволновая печь способна выполнить подобную последовательность, а ведь у неё нет собственного репозитория, системы непрерывной интеграции и команды разработчиков, которые регулярно употребляют выражение «архитектурный контракт», чтобы не произносить вслух «мы опять не предусмотрели очевидную хуйню».

    Но ndmc имел собственное представление о времени. Пока системная служба просыпалась и собиралась с мыслями, наш менеджер уже стоял у её двери, стучал ногами и требовал сведения о DNS. Это примерно как прийти к человеку домой в четыре утра, вышибить дверь, включить свет и заорать: «НАЗОВИ ВСЕ ПОДКЛЮЧЁННЫЕ УСТРОЙСТВА!» После чего записать в журнал: «Человек неисправен. Ответ не получен».

    Разумеется, мы могли бы просто признать, что процессу иногда необходимо дождаться готовности системы. Но зачем выбирать прямой путь, если можно пройти через несколько сборок, десятки проверок и небольшое экзистенциальное потрясение? В итоге мы переработали ожидание ndmc, добавили задержку холодного запуска, повторное получение DNS Info, обновление устаревшего кэша и восстановление данных после загрузки. Заодно улучшили обнаружение клиентов Mesh, предусмотрев резервное получение сведений через ARP.

    Исправления прошли проверку на проблемных моделях Keenetic. Особое место в нашей коллективной травме, конечно, занимает KN-1910, но приключения не ограничились одним устройством. В результате DNS Manager наконец освоил удивительную концепцию: если система ещё не загрузилась, возможно, стоит немного подождать, прежде чем объявлять её мёртвой.

    Пользователям теперь достаточно просто включить устройство. А разработчики наконец могут заняться чем-нибудь полезным. Например, изучить разницу между состояниями «процесс запущен» и «сука, оно действительно работает». На следующем занятии рассмотрим ещё более сложную концепцию: «Не надо ломать то, что уже работало». Но это программа второго семестра. До неё нам ещё расти и расти.

    1. CrowdSec Manager — параноики, которые начали бояться собственной охраны

    В предыдущем релизе мы представили CrowdSec Manager — инструмент, который должен помогать защищать роутер от подозрительных подключений. Идея была великолепная. Пользователь включает защиту, система анализирует состояние, применяет блокировки, и вся эта история заканчивается счастливым финалом, где злоумышленники идут нахуй, а владелец спокойно занимается своими делами.

    Но затем выяснилось, что Keenetic уже обладает собственными механизмами управления firewall. Более того, некоторые пользователи, окончательно потеряв страх перед сложными технологиями, настраивают собственные NDM hook, цепочки и правила. Представляете степень наглости? Люди покупают оборудование, изучают его возможности и используют их по собственному усмотрению. Совершенно неприемлемое поведение с точки зрения разработчика, который предусмотрел ровно один идеальный сценарий — собственный.

    В результате несколько систем безопасности начали выяснять, кто из них главный. Это напоминало ситуацию, когда на входе в здание стоят два охранника. Первый не пускает посетителей, второй не пускает первого, а третий, назначенный начальником службы безопасности, замуровывает дверь кирпичами. Формально объект защищён великолепно. Незаконных проникновений нет. Законных тоже. Да и самого объекта с точки зрения практической эксплуатации больше не существует. Зато в отчёте можно написать: «Количество инцидентов снижено на 100%».

    Мы доработали определение пользовательских NDM hook, поддержку нестандартной _CROWDSEC_CHAIN, проверку переходов через FORWARD и _NDM_FORWARD, а также определение правильного расположения правил относительно уже существующей конфигурации Keenetic. Теперь менеджер учитывает порядок обработки соединений, не дублирует переходы и не пытается переставить чужие правила только потому, что нашему коду захотелось продемонстрировать власть.

    Заодно улучшили диагностику состояния NOT VERIFIED. Раньше этот статус мог означать примерно следующее: «Мы не смогли подтвердить, что защита работает». Очень содержательно. С тем же успехом врач мог бы после трёхчасового обследования вручить пациенту заключение: «Состояние организма вызывает вопросы». Какие вопросы? Чьи? Насколько серьёзные? А хуй его знает, обращайтесь в регистратуру.

    Теперь причин отказа от полной проверки видно больше. А для подключений к CrowdSec LAPI добавлена возможность явно принять риск, связанный с TLS. Причём мы не отключаем шифрование, не подменяем сертификаты и не переписываем конфигурацию Bouncer ради красивого зелёного статуса. Исключение влияет на оценку состояния RouterForge, сохраняет предупреждение и не отменяет проверок самой защиты. При выполнении остальных условий интерфейс может показать ACTIVE · TLS RISK.

    И вот здесь особенно приятно наблюдать наш профессиональный рост. Мы наконец научили программу отличать реальную работу защиты от собственного представления о том, как эта защита должна быть организована. Для индустрии, которая десятилетиями продаёт пользователям безопасность в виде трёх зелёных галочек и годовой подписки, это практически акт гражданского неповиновения.

    1. Port Access Manager — как закрыть дверь и не оставить хозяина на морозе

    Port Access Manager продолжил своё знакомство с реальным миром, где сетевые пакеты почему-то не обязаны двигаться исключительно по маршруту, который разработчик нарисовал в голове. В теории система контроля доступа должна решать две простые задачи: посторонних не пускать, владельцу разрешать вход. Но мы, как всегда, решили не ограничиваться элементарной логикой и построили вокруг неё достаточно сложную систему, чтобы обычное открытие порта приобрело черты международной дипломатической операции.

    Особенно любопытно получилось с odin, цепочками NDM и существующими правилами Keenetic. Иногда механизм активации сталкивался с конфликтами. Иногда требовалась дополнительная предварительная проверка. А иногда пользователь видел сообщение об ошибке ровно столько времени, сколько требовалось интерфейсу для следующего автоматического обновления. Это была, пожалуй, самая изящная из наших инноваций. Если удалять сообщения об ошибках достаточно быстро, пользователь просто перестанет их замечать. По той же логике можно полностью победить преступность, уничтожив все полицейские отчёты.

    Мы исправили потерю сообщений при обновлении интерфейса, добавили проверки цепочек NDM и расширили диагностику конфликтов активации, включая HTTP 409. Доработали взаимодействие odin с механизмами фильтрации и сохранили действующую логику port knocking и watchdog. Теперь система лучше объясняет, почему действие не было выполнено, вместо того чтобы молча демонстрировать пользователю результаты нашего внутреннего архитектурного творчества.

    Вся эта работа напомнила нам об одной фундаментальной истине: задача системы безопасности заключается не в том, чтобы сделать доступ невозможным для всех без исключения. Хотя с точки зрения статистики атак такой подход невероятно привлекателен. Нет подключений, нет злоумышленников, нет жалоб, нет необходимости поддерживать сервис. Можно вообще отключить роутер от электричества и назвать это «режимом абсолютной защиты с нулевой поверхностью атаки».

    Уверен, где-нибудь в мире уже готовится стартап с подобной концепцией. Мы же решили оставить пользователям возможность пользоваться собственным оборудованием. Не самый прибыльный бизнес-план, зато довольно человечный.

    1. Мониторинг — если процессор не нагревается, назначим процессором Wi-Fi

    Отдельная история приключилась с аппаратным мониторингом. Некоторые модели Keenetic не предоставляют доступных показаний температуры CPU, зато позволяют узнать температуру беспроводных модулей. И в определённых условиях RouterForge мог отобразить температуру Wi-Fi как температуру процессора. С инженерной точки зрения решение было почти безупречным: оба компонента находятся внутри одного корпуса, оба потребляют электричество, оба способны нагреваться. Чего вам ещё, блядь, надо? Точности?

    Представьте врача, который измеряет температуру пациента, прикладывая градусник к батарее отопления. «У вас сорок семь градусов». «Доктор, но я прекрасно себя чувствую!» — «Не спорьте с диагностическим оборудованием. Оно сертифицировано». Именно такой уровень научной строгости мы некоторое время демонстрировали в отдельных сценариях мониторинга.

    Теперь при отсутствии достоверного датчика CPU/SoC интерфейс честно сообщает, что соответствующие данные недоступны. Температуры Wi-Fi отображаются отдельно, как и положено самостоятельным аппаратным компонентам. Заодно улучшили представление событий и системных состояний.

    Получилось весьма полезное исправление, из которого мы извлекли поразительно глубокий философский урок: отсутствие информации не является достаточным основанием для её выдумывания. Надеемся, однажды этот принцип распространится на политику, журналистику и корпоративную отчётность. Но начнём с сетевого оборудования. Там хотя бы датчики можно проверить.

    1. Центр приложений — научное открытие: фоновые процессы могут работать в фоне

    Раньше проверка доступных обновлений была тесно связана с пользовательским интерфейсом. Человек открывал RouterForge, система обновляла сведения, и все были довольны. Пока однажды мы не задались вопросом: а что происходит с обновлениями, когда пользователь закрывает браузер? Они исчезают? Перестают существовать? Переходят в квантовое состояние неопределённости до следующего наблюдения?

    После непродолжительного философского кризиса мы обнаружили, что программное обеспечение способно выполнять действия без присутствия зрителей. Оказалось, можно просто добавить фоновую синхронизацию каталога. Теперь Core периодически проверяет сведения об обновлениях с интервалом 30 минут, даже если пользователь не сидит перед интерфейсом и не смотрит на кнопку с надеждой увидеть там чудо.

    Также исправили доступность Stable-каталога для архитектур MIPS и MIPSEL, продолжили доработку управления источниками, установкой, удалением и жизненным циклом модулей. При этом автоматическая проверка не означает автоматическую установку пакетов. Мы вполне допускаем, что человек, который владеет роутером, имеет право самостоятельно решать, когда и что на нём обновлять.

    Возможно, однажды это станет общепринятым принципом программной индустрии. Хотя пока отрасль предпочитает считать, что лучше пользователя знает, какие изменения ему необходимы, особенно если они требуют немедленной перезагрузки в самый неподходящий момент. Мы решили не участвовать в этом празднике насильственного прогресса.

    1. Телеметрия — мы построили целую платформу, но забыли посчитать посетителей

    На протяжении множества релизов мы развивали RouterForge, создавали модули, собирали пакеты, запускали CI, исправляли ошибки и спорили с операционной системой, которая не желала подчиняться нашей инженерной воле. При этом у нас отсутствовал нормальный механизм, позволяющий понять, сколько устройств вообще используют проект. То есть мы построили достаточно сложную систему управления роутерами, но забыли реализовать элементарный учёт её установок.

    Представьте владельца ресторана, который закупил дорогостоящее оборудование, нанял поваров, разработал меню из ста блюд, автоматизировал склад и установил систему контроля температуры холодильников. А на вопрос о количестве посетителей отвечает: «Ну, наверное, кто-нибудь приходит». Примерно на таком уровне находилась наша аналитическая зрелость. Зато архитектура, разумеется, была продумана до мельчайших деталей. Особенно тех, которые никого не интересовали.

    Мы добавили регистрацию установок, периодический учёт присутствия и отдельную необязательную техническую диагностику. Для каждого экземпляра создаётся случайный идентификатор, сохраняющийся при обновлениях. Core передаёт фактическую версию и канал установленной сборки, а дополнительная диагностика позволяет учитывать архитектуру устройства и версии официальных модулей RouterForge. Для этого реализовали собственный HTTPS Collector, обработку повторных событий, совместимость с прежней схемой и хранение агрегированных сведений.

    Разумеется, возник вопрос о приватности. И здесь мы решили не превращать небольшой некоммерческий проект в ещё одну корпорацию, которая под видом улучшения пользовательского опыта собирает информацию обо всём, что человек делал со своим устройством с момента рождения. Диагностические данные не включают пароли, подписки, пользовательские конфигурации, DNS-трафик, посещённые домены, журналы, серийные номера и аппаратные показатели нагрузки. Дополнительную диагностику можно отключить; базовый учёт регистрации и присутствия работает отдельно. При этом абсолютную анонимность мы не обещаем, поскольку принимающий HTTPS-сервер технически видит сетевой адрес соединения.

    И вот теперь мы хотя бы сможем понять, какие версии используются и какие модули действительно востребованы. Мы не собираемся выяснять, почему конкретный человек устанавливает DNS Manager в субботу в четыре утра. Хотя это, безусловно, интересный вопрос. Особенно с учётом того, что в это же время где-то может сидеть разработчик и пытаться понять, почему после холодной загрузки опять не работает ndmc.

    Возможно, им даже стоит познакомиться. У них явно есть общие психологические травмы.

    1. Интерфейс — федерация независимых прямоугольников объявляет о капитуляции

    Постепенно RouterForge превратился в небольшую конфедерацию программных княжеств. Core имел собственное представление о прекрасном. Каждый менеджер — своё. У разных страниц существовали разные взгляды на цвета, кнопки, переключатели, отступы и заголовки. Причём каждый отдельный компонент был абсолютно убеждён, что его визуальная философия представляет собой вершину человеческой цивилизации.

    Один интерфейс напоминал строгую административную панель. Другой — систему управления атомной электростанцией. Третий производил впечатление, что его проектировали люди, которым выдали три CSS-переменные и приказали построить демократию. Пользователь перемещался между разделами, словно пересекал государственные границы, каждый раз сталкиваясь с новыми обычаями, законами и местной валютой в виде уникальных кнопок.

    Мы решили объединить этот цирк. Добавили общую систему UI-примитивов и семантических цветов, переработали страницу настроек, распределив функции между разделами «Система», «Интерфейс», «Журналы» и «Безопасность». Унифицировали переключатели ON/OFF, состояния выполнения, отключения и взаимодействия с клавиатурой. В Antiscan Manager привели к общему виду семь двоичных элементов управления, сохранив их действующую логику. Продолжили совершенствовать оболочку приложения, элементы навигации и согласованность отдельных разделов.

    Но самым выдающимся архитектурным достижением стало совершенно неожиданное решение: перестать переписывать то, что уже работает нормально. Да, мы понимаем, насколько революционно это звучит. Ведь современная разработка требует регулярно уничтожать исправные компоненты, чтобы заменить их новыми, выполняющими ровно те же функции, только с дополнительными зависимостями и более внушительным количеством строк кода.

    Мы решили проявить редкую для себя интеллектуальную сдержанность. Если элемент уже удобен, соответствует общей теме и не создаёт проблем, его можно оставить в покое. Вероятно, в этот момент где-то в мире умер маленький консультант по цифровой трансформации. Но зато пользовательский интерфейс стал последовательнее, а действующая функциональность не принесена в жертву нашему желанию срочно продемонстрировать профессиональную занятость.

    1. Локализация — раздвоение личности теперь хотя бы на двух языках

    Параллельно продолжилась работа над русским и английским интерфейсами. Оказалось, что отдельные компоненты RouterForge могут называться по-разному в разных разделах. Пользователь открывает одну страницу — видит знакомое название. Переходит в другую — получает новое. Возвращается назад — и начинает подозревать, что программа проходит сложный период самоопределения.

    Впрочем, для IT-индустрии подобное поведение совершенно нормально. Крупные корпорации способны ежегодно переименовывать один и тот же продукт, постепенно теряя связь между названием, функциональностью и здравым смыслом. Мы решили не достигать такого уровня зрелости и просто привести терминологию в порядок.

    Обновили переводы общих элементов, Monitoring, Admin, Terminal, File Manager, диагностики, обслуживания и Service Inspector. Унифицировали названия менеджеров, в том числе Port Access Manager, и связанные подписи NFQWS2 Manager. Доработали сообщения файловых операций и различные пользовательские состояния.

    При этом технические идентификаторы и API оставили в покое. Потому что если надпись на кнопке переведена неправильно, разумный инженер исправляет надпись. А не переписывает половину программной системы, создаёт двенадцать миграций и затем полгода объясняет пользователям, почему старые настройки больше не работают.

    Мы, конечно, вполне способны на второй вариант. Но решили проявить неожиданную человечность.

    1. Файловый менеджер и терминал — революция, которой никто не просил

    Доработали административные инструменты RouterForge: файловый менеджер, редактор, окно свойств, терминал, элементы управления службами и связанные сообщения. Основной упор сделали на понятность, согласованность оформления и локализацию. Никаких торжественных заявлений о том, что теперь пользователь получит принципиально новый опыт взаимодействия с файловой системой.

    Потому что опыт взаимодействия с файловой системой должен быть до неприличия скучным. Открыл файл. Посмотрел содержимое. Изменил необходимое. Сохранил. Всё. Не требуется переосмысление цифровой реальности, участие в интерактивном обучающем путешествии или семинар на тему «Как современный человек переживает эмоциональный контакт с кнопкой Save».

    Впрочем, современная программная индустрия давно научилась продавать перестановку трёх кнопок как фундаментальную революцию пользовательского опыта. Мы решили отказаться от подобного героизма и просто сделать инструменты удобнее. Возможно, это не обеспечит нам приглашение на международную конференцию по инновациям. Зато позволит людям выполнять свою работу, не задаваясь вопросом, какой долбоёб спрятал необходимую функцию в очередное архитектурное откровение.

    1. NFQWS Manager — старые раны, свежие воспоминания

    В предыдущих релизах NFQWS Manager пережил такое количество исправлений, проверок, откатов и защитных механизмов, что заслуживает отдельного мемориального комплекса. Мы учились безопасно работать со списками, контролировать зависимости, защищать пользовательские изменения и восстанавливать состояние после неудачных операций. Каждый новый тест открывал очередное удивительное свойство файловой системы, которое разработчики почему-то не предусмотрели заранее.

    Например, оказалось, что файл может измениться между чтением и записью. Что удаляемый список иногда используется в настройках. Что параллельные операции могут конфликтовать. Что откат тоже способен завершиться ошибкой. Настоящий университет фундаментальной информатики для взрослых людей, которые, казалось бы, должны были знать всё это ещё до того, как получили доступ к клавиатуре.

    Эти изменения уже вошли в предыдущий Stable, поэтому мы не станем повторно продавать их как новые. В конце концов, RouterForge — не производитель смартфонов, который ежегодно меняет расположение камеры на три миллиметра и приглашает журналистов наблюдать за революцией.

    Но кое-чему эта эпопея нас всё-таки научила. Перед изменением конфигурации полезно проверить условия, после изменения — подтвердить результат, а при ошибке — иметь возможность восстановить предыдущее состояние. Если сформулировать это достаточно серьёзно и добавить пару диаграмм, получится полноценная инженерная методология.

    Хотя обычный системный администратор, вероятно, назвал бы всё это «не делать хуйню на живом оборудовании». Краткость — сестра таланта.

    1. Три архитектуры, тридцать пакетов и один коллективный нервный тик

    Разработка продолжалась сразу для ARM64, MIPS и MIPSEL. Полная проверяемая матрица Beta включала десять компонентов на каждую архитектуру — тридцать IPK, отдельные индексы, установочные скрипты и достаточно условий для того, чтобы любой нормальный человек задумался о смене профессии.

    Особое место в наших сердцах занимает GitHub Actions. Удивительная система, позволяющая автоматически убедиться, что программа не работает, прежде чем передать её пользователю. Мы запускали сборки, проверяли пакеты, исправляли индексы, согласовывали версии и наблюдали, как очередной зелёный PASS сменяется красным FAIL по причине, которая ещё вчера казалась физически невозможной.

    То не совпадёт индекс архитектуры. То скрипт сборки оказывается неисполняемым. То тест внезапно обнаруживает, что реальность несколько отличается от наших представлений о ней. И каждый раз разработчик смотрит на экран с выражением человека, который только что узнал, что ему снова предстоит оплатить собственные похороны.

    Мы продолжили совершенствовать сборку, проверку состава пакетов и согласованность версий. При этом сохранили принцип независимого версионирования компонентов: если один модуль не менялся, незачем изображать, что он пережил грандиозную техническую революцию исключительно ради красивой цифры.

    Странная мысль для индустрии, где изменение номера версии порой считается более значимым событием, чем изменение самой программы. Но мы постепенно привыкаем к тому, что программное обеспечение существует не ради релизной церемонии, а ради людей, которые собираются им пользоваться.

    1. Баг-репорты — благодарим людей, которые обнаружили нашу хуйню раньше нас

    Самая неприятная особенность пользовательских баг-репортов заключается в том, что пользователи слишком часто оказываются правы. Они устанавливают программу, выполняют совершенно нормальные действия, сталкиваются с ошибкой и сообщают о ней. Причём делают это без малейшего уважения к количеству часов, которые разработчик потратил на создание соответствующего дефекта.

    Человек пишет: «После перезагрузки DNS не восстановился». Мы немедленно думаем: «Не может быть, мы же всё проверили». Потом открываем журналы и обнаруживаем, что действительно не может быть — исключительно в той вымышленной вселенной, где разработчик никогда не ошибается, все службы запускаются одновременно, а конфигурации пользователей полностью совпадают с нашими тестовыми стендами.

    Другой пользователь сообщает об ошибке CrowdSec. Третий обнаруживает проблему активации Port Access. Четвёртый замечает странные показатели температуры. И каждый раз реальность аккуратно подносит к лицу разработчика зеркало, в котором отражается не великий инженер-новатор, а уставший мудак, который опять не предусмотрел очевидную ситуацию.

    Поэтому отдельная благодарность всем, кто проверял RouterForge на реальном оборудовании, воспроизводил ошибки, присылал результаты и помогал доводить исправления до рабочего состояния. Благодаря этим людям проект становится лучше, а разработчики получают возможность регулярно корректировать собственную самооценку в сторону большей научной достоверности.

    Пользователи здесь не виновники наших проблем. Они — свидетели, потерпевшие, добровольные испытатели и временами единственные люди, способные убедительно доказать нам очевидное. И именно благодаря их обратной связи RouterForge постепенно превращается из набора амбициозных инженерных идей в инструмент, которому можно доверять.

    За это действительно огромное спасибо. Даже если иногда ваши баг-репорты заставляют нас произносить слова, которые не рекомендуется использовать в присутствии несовершеннолетних и сотрудников отдела кадров.

    Вместо заключения — героизм, которого лучше бы вообще не было

    Итак, что мы имеем? Мы исправили холодный запуск DNS, улучшили взаимодействие CrowdSec с firewall, доработали Port Access, научили мониторинг отличать процессор от Wi-Fi, добавили фоновую проверку обновлений, реализовали статистику установок, привели в порядок интерфейс, продолжили локализацию и укрепили систему сборки.

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

    В этом и заключается самая прекрасная комедия разработки программного обеспечения. Никто не выходит на сцену с гордым заявлением: «Дамы и господа! Сегодня мы не допустили появления четырнадцати ошибок!» Нет. Сначала мы должны их создать. Потом обнаружить. Потом несколько раз неправильно исправить. Потом написать тест. Потом исправить тест. Потом исправить исправление. И только после этого торжественно объявить: «Представляем новую версию с повышенной стабильностью!»

    Если бы строители работали по такой модели, каждый новый дом сначала сдавали бы без крыши. Через месяц выпускали обновление с защитой от дождя, спустя полгода представляли Premium Roof Experience 2.0 с поддержкой снега, а ещё через год объявляли масштабную модернизацию кровельной инфраструктуры, в рамках которой вода наконец перестала бы стекать жильцам прямо на голову.

    И самое омерзительное — это действительно прогресс.

    Потому что надёжность не возникает из красивой презентации. Она появляется из сотен маленьких исправлений, реальных проверок и неприятной готовности признать, что вчерашнее гениальное решение сегодня оказалось полной хуйнёй.

    Мы не обещаем, что RouterForge больше никогда не столкнётся с ошибками. Такое обещание способен дать только человек, который никогда не писал программное обеспечение. Или руководитель отдела маркетинга. Что, в сущности, довольно близкие категории с точки зрения практического опыта отладки.

    Мы обещаем другое: когда обнаружим очередную собственную глупость, не будем делать вид, что это уникальная инновационная функция, за которую пользователь должен испытывать благодарность. Мы просто её исправим. А потом, разумеется, напишем об этом ещё один патчноут, потому что нужно же как-то оправдывать существование раздела Releases.

    До следующего обновления, друзья. Продолжайте пользоваться RouterForge. Нажимайте кнопки. Меняйте настройки. Перезагружайте роутеры. И если опять что-нибудь сломается — обязательно расскажите нам.

    Мы откроем журналы, посмотрим исходники, проведём три совещания с собственным здравым смыслом и рано или поздно выясним, какой именно долбоёб это написал. С высокой вероятностью далеко ходить не придётся.

    А пока — спасибо, что испытываете наше терпение значительно реже, чем мы испытываем ваше.

    Команда RouterForge.

    Технически подкованные. Архитектурно самоуверенные. Регулярно охуевающие от результатов собственной работы.

    P.S. Если после этого релиза DNS снова не запустится после перезагрузки, мы официально переименуем ndmc в «Спящую красавицу», а разработчиков отправим целовать исходный код до полного восстановления работоспособности.

    Хотя, судя по количеству допущенных ошибок, некоторым из нас придётся провести с ним остаток жизни.


    RouterForge — Stable 0.14.0

    The Great Architects of Our Own Fucking Disaster

    Or How We Fixed Our Own Mistakes and Almost Convinced Ourselves It Was an Achievement

    You know what's truly wonderful about software development? The opportunity to endlessly fix things you fucked up yourself. It's a genuinely unique profession. Imagine a surgeon who first sews a third leg onto a patient, then spends six months developing an innovative technique for removing it, issues a press release about improving the quality of medical care, and wins a professional award. In medicine, he'd probably go to prison. In IT, he'd get a raise, become lead architect, and be invited to speak at a conference about “Our Journey Toward Three-Legged Microservice Architecture.”

    That's roughly what we've been doing.

    In the previous Stable release, RouterForge gained new managers, new capabilities, improved security, and enough tools for users to turn their home routers into miniature mission-control centers. We were happy. The users were happy, too. Especially us. Because nothing boosts a developer's confidence quite like a successful build of software they haven't yet tested under conditions even remotely resembling real life.

    And then the users committed an absolutely unforgivable act: they started using the software. Not merely installing it for pretty screenshots, but actually pressing buttons, changing settings, and expecting results. Some even rebooted their routers, as if they had no idea what a fragile work of art modern software really is. Absolutely no respect for developers' mental health.

    Naturally, we immediately began diagnosing the problems. First we studied logs. Then source code. Then logs again. Then Keenetic documentation. Then Entware documentation. Then we started suspecting that the documentation, too, had been written by a bunch of idiots. That was a rather bold accusation from people who regularly explain their own code with “well, it's all obvious.”

    Before long, we discovered the most unpleasant truth: the users were right. Worse, many bugs reproduced with downright insulting consistency. That, incidentally, was the kind of stability we had wanted from the program itself.

    So we had to open the code editor again. And thus began another season of our favorite series, “Developer Versus the Consequences of Their Own Decisions.” Previous seasons, you may recall, ended not so much in victory as in a temporary ceasefire.

    1. DNS Manager — The Great Architects of Our Own Fucking Disaster

    Do you know why users love rebooting their routers? Because, unlike us, they somehow believe a computer ought to keep working afterward. Sweet summer children. They don't yet know that somewhere between KeeneticOS and Entware sits a group of self-appointed engineers capable of writing thousands of lines of DNS-management code but incapable of realizing, on the first attempt, that a system service might not be ready yet.

    And when DNS Manager once again failed to start properly on a KN-1910, naturally we diagnosed the issue immediately. Meaning we blamed Keenetic first. Then Entware. Then ndmc. Then service startup order. Then, just to be safe, the laws of thermodynamics. Only after a while did we cautiously consider the possibility that the problem might lie with the fucking morons who wrote the thing. An unpleasant hypothesis, profoundly damaging to our self-esteem. Particularly once it turned out those morons were us.

    We added checks, delays, retries, state restoration. We ran tests. Got PASS. Celebrated. Then a user rebooted their router and our engineering pride went straight to hell again. At some point it became obvious: if starting DNS requires more rituals than summoning an ancient Sumerian demon, perhaps the router isn't the problem.

    The task itself hardly seems intellectually demanding. The device powers on, the operating system boots, system services become available, and DNS Manager starts working. Four sequential steps. Even a microwave can follow a sequence like that, and it doesn't have its own repository, continuous integration system, or development team constantly saying “architectural contract” so they won't have to admit “we failed to account for this obvious shit again.”

    But ndmc had its own understanding of time. While the system service was waking up and collecting its thoughts, our manager was already at its door, kicking it and demanding DNS information. It's like showing up at someone's house at four in the morning, breaking down the door, switching on the lights, and shouting, “NAME EVERY CONNECTED DEVICE!” Then writing in the log: “Human malfunctioning. No response received.”

    Of course, we could simply have acknowledged that a process sometimes needs to wait until the system is ready. But why take the direct route when you can go through several builds, dozens of checks, and a minor existential crisis? In the end we reworked the wait for ndmc, added a cold-start delay, retried DNS Info retrieval, refreshed stale cache data, and restored information after boot. We also improved Mesh client discovery, with ARP as a fallback source of information.

    The fixes were tested on problematic Keenetic models. The KN-1910 naturally holds a special place in our collective trauma, but the adventures weren't limited to a single device. As a result, DNS Manager finally mastered an astonishing concept: when the system hasn't finished booting, maybe wait a little before declaring it dead.

    Now users need only switch on their devices. And developers can finally do something useful, like learn the difference between “the process is running” and “holy shit, it actually works.” Next class will cover an even more advanced concept: “Don't break what already worked.” But that's second-semester material. We still have a long way to go.

    1. CrowdSec Manager — Paranoids Who Became Afraid of Their Own Security Guards

    In the previous release we introduced CrowdSec Manager, a tool meant to help protect routers from suspicious connections. The idea was magnificent. The user turns on protection, the system analyzes its state, applies blocks, and the story ends happily: attackers fuck off and the owner gets on with their life.

    Then it turned out Keenetic already has its own firewall-management mechanisms. Worse still, some users, having completely lost their fear of complex technology, configure their own NDM hooks, chains, and rules. Can you imagine the nerve? People buy hardware, study its capabilities, and use it however they see fit. Totally unacceptable to a developer who envisioned exactly one perfect use case: their own.

    As a result, several security systems began fighting over who was in charge. Picture two security guards at a building entrance. The first keeps visitors out, the second keeps the first guard out, and a third, appointed head of security, bricks up the door. Formally the building is superbly protected. No illegal entries. No legal entries either. From a practical standpoint, the building itself might as well no longer exist. But the report can proudly claim: “Incidents reduced by 100%.”

    We improved detection of custom NDM hooks, support for nonstandard _CROWDSEC_CHAIN configurations, checks of transitions through FORWARD and _NDM_FORWARD, and correct rule positioning relative to existing Keenetic configurations. The manager now respects connection-processing order, avoids duplicate jumps, and doesn't try to rearrange somebody else's rules merely because our code feels like asserting dominance.

    We also improved diagnostics for the NOT VERIFIED state. Previously it could mean something like “We couldn't confirm protection is working.” Extremely informative. A doctor could just as well hand someone a report after a three-hour examination saying “The patient's condition raises questions.” Which questions? Whose questions? How serious? Fuck knows. Ask at reception.

    Now more reasons for failed full verification are visible. And for connections to CrowdSec LAPI we've added an option to explicitly accept the TLS-related risk. We do not disable encryption, substitute certificates, or rewrite Bouncer configuration to get a pretty green status. The exception affects RouterForge's state assessment, preserves the warning, and doesn't bypass the protection's own checks. When the other conditions are satisfied, the UI may display ACTIVE · TLS RISK.

    And this is where our professional growth becomes particularly delightful to watch. We've finally taught the program to distinguish actual protection from our ideas about how protection ought to be organized. For an industry that has sold security for decades as three green checkmarks and an annual subscription, that's practically an act of civil disobedience.

    1. Port Access Manager — How to Lock the Door Without Leaving the Owner Out in the Cold

    Port Access Manager continued its introduction to the real world, where network packets, for some reason, aren't obliged to follow the path a developer drew in their head. In theory, access control has two simple jobs: keep strangers out and let the owner in. As always, we refused to stop at elementary logic and built a system complicated enough to make opening a port resemble an international diplomatic negotiation.

    The interaction with odin, NDM chains, and existing Keenetic rules proved especially entertaining. Sometimes activation ran into conflicts. Sometimes additional preliminary checks were needed. And sometimes an error message remained on screen for exactly as long as it took the interface to perform its next automatic refresh. Perhaps our most elegant innovation yet. If you delete error messages quickly enough, users simply stop noticing them. By the same logic you could eliminate crime by destroying every police report.

    We fixed error messages disappearing during UI refreshes, added NDM chain checks, and expanded diagnostics for activation conflicts, including HTTP 409. We improved odin's interaction with filtering mechanisms while preserving existing port-knocking and watchdog behavior. Now the system does a better job of explaining why an action couldn't be completed, instead of silently exhibiting the results of our internal architectural artistry.

    All this reminded us of a fundamental truth: a security system's job is not to make access impossible for absolutely everyone. Although, statistically, that approach looks awfully appealing. No connections, no attackers, no complaints, no need to maintain the service. You could just unplug the router and call it “absolute protection mode with zero attack surface.”

    Somewhere in the world, I'm sure, a startup is already preparing exactly that pitch. We decided to let people keep using their own equipment. Not the most lucrative business model, but a fairly humane one.

    1. Monitoring — If the CPU Isn't Getting Hot, Let's Appoint Wi-Fi as the CPU

    Hardware monitoring provided its own adventure. Some Keenetic models do not expose usable CPU temperature readings but do report temperatures for wireless modules. Under certain conditions, RouterForge could display a Wi-Fi temperature as the CPU temperature. From an engineering perspective, almost flawless: both parts live in the same enclosure, both use electricity, both can get hot. What the fuck else do you want? Accuracy?

    Imagine a doctor measuring a patient's temperature by pressing a thermometer against a radiator. “You've got a temperature of forty-seven degrees.” “Doctor, but I feel fine!” “Don't argue with certified diagnostic equipment.” That's about the level of scientific rigor we were demonstrating in certain monitoring scenarios.

    Now, if there is no trustworthy CPU/SoC sensor, the interface honestly reports that the data is unavailable. Wi-Fi temperatures appear separately, as proper independent hardware components should. We also improved how events and system states are presented.

    It was a useful fix, from which we extracted a profoundly philosophical lesson: a lack of information is not sufficient grounds for making it up. We hope the principle eventually spreads to politics, journalism, and corporate reporting. But let's start with networking hardware. At least its sensors can be checked.

    1. App Center — Scientific Discovery: Background Processes Can Run in the Background

    Previously, checking for available updates was tightly coupled to the user interface. A person opened RouterForge, the system refreshed its data, and everyone was happy. Until one day we asked ourselves: what happens to updates when the user closes the browser? Do they vanish? Stop existing? Enter a quantum state of uncertainty until the next observation?

    After a brief philosophical crisis, we discovered that software can perform actions even without an audience. Apparently you can just add background catalog synchronization. Core now periodically checks update information every 30 minutes, even when the user isn't sitting in front of the interface staring hopefully at the update button.

    We also fixed Stable catalog availability for MIPS and MIPSEL architectures and continued improving source management, installation, removal, and module lifecycle handling. Automatic checking does not mean automatic package installation, though. We fully acknowledge that someone who owns a router should be allowed to decide for themselves when and what to update.

    Perhaps one day this will become an accepted principle in the software industry. For now, the industry prefers to think it knows better than users what changes they need, especially when those changes require an immediate reboot at the worst possible moment. We decided not to join this festival of compulsory progress.

    1. Telemetry — We Built an Entire Platform but Forgot to Count the Visitors

    Across many releases, we developed RouterForge, created modules, built packages, ran CI, fixed bugs, and argued with an operating system that refused to submit to our engineering will. Yet we had no proper way to tell how many devices actually used the project. We built a fairly elaborate router-management platform but forgot the most elementary count of its installations.

    Imagine a restaurant owner who buys expensive equipment, hires chefs, designs a hundred-dish menu, automates inventory, and installs fridge-temperature monitoring. When asked how many customers visit, the answer is: “Well, I suppose somebody probably comes in.” That was roughly our level of analytics maturity. The architecture, needless to say, was meticulously designed, especially the details nobody cared about.

    We added installation registration, periodic presence reporting, and separate optional technical diagnostics. Each installation receives a random identifier that survives updates. Core reports the actual version and channel of the installed build, and optional diagnostics allow the device architecture and versions of official RouterForge modules to be counted. We built our own HTTPS Collector, repeat-event processing, compatibility with the previous schema, and storage of aggregated information.

    Naturally, privacy came up. We decided not to turn a small nonprofit project into yet another corporation that, under the guise of improving user experience, collects everything a person has done with their device since birth. Diagnostic data does not include passwords, subscriptions, user configurations, DNS traffic, visited domains, logs, serial numbers, or hardware load readings. Optional diagnostics can be disabled; baseline registration and presence reporting operate separately. We don't promise absolute anonymity, however, because the receiving HTTPS server can technically see the connection's network address.

    At least now we can see which versions are used and which modules people actually need. We have no intention of finding out why someone installs DNS Manager at four in the morning on a Saturday. Although that's unquestionably an interesting question. Especially considering that somewhere at the very same time a developer may be wondering why ndmc has failed to work after a cold boot yet again.

    Perhaps the two should meet. They clearly share some psychological trauma.

    1. Interface — The Federation of Independent Rectangles Announces Its Surrender

    Gradually, RouterForge became a small confederation of software principalities. Core had its own idea of beauty. Every manager had another. Different pages had different opinions about colors, buttons, switches, spacing, and headings. Each component was completely convinced that its visual philosophy represented the pinnacle of human civilization.

    One interface resembled a strict administration panel. Another looked like the control room of a nuclear power plant. A third suggested its designers had been given three CSS variables and ordered to build a democracy. Users traveled between sections as though crossing national borders, encountering unfamiliar customs, laws, and a local currency made of unique buttons.

    We decided to unite this circus. We added a shared system of UI primitives and semantic colors and redesigned Settings, dividing features between System, Interface, Logs, and Security. We standardized ON/OFF switches, execution states, disabled states, and keyboard interactions. In Antiscan Manager, we unified seven binary controls while preserving their existing behavior. We continued refining the app shell, navigation elements, and consistency across individual sections.

    But the most remarkable architectural achievement was an utterly unexpected decision: stop rewriting things that already work fine. Yes, we realize how revolutionary this sounds. Modern software development, after all, demands periodically destroying functioning components and replacing them with new ones that do exactly the same thing, only with extra dependencies and a much more imposing line count.

    We decided to practice a rare form of intellectual restraint. If an element is already convenient, matches the shared theme, and causes no problems, it may be left alone. Somewhere in the world, a tiny digital-transformation consultant probably died at that very moment. But the interface became more consistent, and existing functionality wasn't sacrificed to our urgent desire to demonstrate professional busyness.

    1. Localization — Split Personality, Now in at Least Two Languages

    In parallel, we continued work on Russian and English interfaces. It turned out some RouterForge components could be called different things in different sections. A user opens one page and sees a familiar name. Moves to another and gets a new one. Goes back and begins suspecting that the program is going through a complicated identity crisis.

    For the IT industry, of course, this is perfectly normal. Major corporations can rename the same product every year, gradually losing any connection between its name, function, and common sense. We chose not to reach that level of maturity and simply standardized terminology.

    We updated translations for shared elements, Monitoring, Admin, Terminal, File Manager, diagnostics, maintenance, and Service Inspector. We standardized manager names, including Port Access Manager, and the associated NFQWS2 Manager labels. We improved file-operation messages and various user-facing states.

    Technical identifiers and APIs, however, were left alone. Because when a button's label is mistranslated, a reasonable engineer fixes the label. They don't rewrite half the software, create twelve migrations, and spend six months explaining why old settings no longer work.

    We are, of course, perfectly capable of the second option. But we decided to show an unexpected degree of humanity.

    1. File Manager and Terminal — The Revolution Nobody Asked For

    We improved RouterForge's administrative tools: the file manager, editor, properties dialog, terminal, service controls, and related messages. The focus was on clarity, visual consistency, and localization. No grand declarations that users would now enjoy a fundamentally new experience of interacting with a filesystem.

    Because dealing with a filesystem should be indecently boring. Open a file. Look at its contents. Change what needs changing. Save. That's it. There is no need to reinvent digital reality, participate in an interactive learning journey, or attend a seminar on “How Modern Humans Experience Emotional Contact with the Save Button.”

    The modern software industry has long learned to sell rearranging three buttons as a fundamental revolution in user experience. We chose to abandon that heroism and simply make the tools more convenient. Perhaps that won't earn us an invitation to an international innovation conference. But it will let people get their work done without wondering which fucking idiot hid the function they needed inside another architectural revelation.

    1. NFQWS Manager — Old Wounds, Fresh Memories

    In previous releases, NFQWS Manager survived so many fixes, checks, rollbacks, and safeguards that it deserves its own memorial complex. We learned to handle lists safely, control dependencies, protect user changes, and recover state after failed operations. Every new test revealed another astonishing property of the filesystem that the developers somehow hadn't anticipated.

    For example, it turned out a file can change between reading and writing. A list being deleted might be referenced by settings. Concurrent operations can conflict. Even a rollback can fail. A real university course in fundamental computer science for adults who really ought to have known all this before being allowed near a keyboard.

    Those changes were already included in the previous Stable, so we won't try to sell them again as new features. After all, RouterForge isn't a smartphone maker that moves a camera three millimeters every year and invites journalists to witness the revolution.

    Still, that whole saga taught us something. Before changing a configuration, check the preconditions; afterward, verify the result; and if something fails, have a way to restore the previous state. Phrase that seriously enough and add a couple of diagrams, and you've got a complete engineering methodology.

    An ordinary system administrator would probably call it “don't do stupid shit on production hardware.” Brevity is the soul of wit.

    1. Three Architectures, Thirty Packages, and One Collective Nervous Tic

    Development continued across ARM64, MIPS, and MIPSEL. The complete verifiable Beta matrix included ten components for each architecture: thirty IPK packages, separate indexes, installation scripts, and enough conditions to make any sensible person consider changing careers.

    GitHub Actions occupies a special place in our hearts. An amazing system that lets you automatically confirm your program doesn't work before handing it to users. We ran builds, checked packages, fixed indexes, aligned versions, and watched one green PASS turn into a red FAIL for a reason that had seemed physically impossible only yesterday.

    Sometimes an architecture index wouldn't match. Sometimes a build script wasn't executable. Sometimes a test suddenly discovered that reality was a little different from our assumptions. And each time the developer stared at the screen like someone who had just learned they'd once again have to pay for their own funeral.

    We continued improving builds, package-content checks, and version consistency. At the same time, we preserved independent component versioning: if a module hasn't changed, there's no reason to pretend it has undergone some grand technological revolution just for the sake of a pretty version number.

    A strange idea in an industry where changing a version number is sometimes considered more significant than changing the software itself. But we're gradually getting used to the notion that software exists for the people who intend to use it, not for the release ceremony.

    1. Bug Reports — Thank You to the People Who Found Our Fuckups Before We Did

    The most unpleasant thing about user bug reports is how often users turn out to be right. They install a program, perform perfectly normal actions, encounter a bug, and report it, with absolutely no respect for the number of hours a developer spent creating that particular defect.

    Someone writes, “DNS didn't recover after reboot.” Our immediate thought is, “Impossible, we tested everything.” Then we open the logs and discover that, indeed, it is impossible — but only in an imaginary universe where developers never make mistakes, every service starts at the same time, and every user's configuration perfectly matches our test environment.

    Another user reports a CrowdSec error. A third finds a Port Access activation issue. A fourth notices strange temperature readings. And every time, reality politely holds a mirror to the developer's face, revealing not a great innovative engineer but a tired asshole who has once again failed to anticipate an obvious situation.

    So we owe special thanks to everyone who tested RouterForge on real hardware, reproduced errors, sent results, and helped bring fixes to a working state. Thanks to these people, the project gets better, and developers regularly get an opportunity to adjust their self-esteem toward greater scientific accuracy.

    Users aren't the perpetrators of our problems. They're witnesses, victims, volunteer testers, and sometimes the only people capable of proving the obvious to us convincingly. Their feedback is exactly what is gradually turning RouterForge from a collection of ambitious engineering ideas into a tool people can trust.

    For that, thank you very much indeed. Even if your bug reports sometimes make us utter words best avoided around minors and HR personnel.

    Instead of a Conclusion — Heroism We Would Have Been Better Off Without

    So what have we achieved? We fixed DNS cold starts, improved CrowdSec's interaction with the firewall, refined Port Access, taught monitoring to distinguish CPU from Wi-Fi, added background update checks, implemented installation statistics, tidied up the interface, continued localization, and strengthened the build system.

    On paper, it looks impressive. Especially if you don't think too hard about how much of it consists of fixing problems that should never have existed in the first place.

    This is the finest comedy in software development. Nobody walks onto the stage to proudly announce, “Ladies and gentlemen! Today we prevented fourteen bugs from happening!” No. First we have to create them. Then discover them. Then fix them incorrectly several times. Then write a test. Then fix the test. Then fix the fix. And only after that can we solemnly announce, “Introducing a new version with improved stability!”

    If builders worked this way, every new house would initially ship without a roof. A month later there would be an update adding rain protection, six months after that a Premium Roof Experience 2.0 with snow support, and a year later a major roofing-infrastructure modernization that finally stopped water from pouring directly onto residents' heads.

    And the most disgusting thing is that this really is progress.

    Because reliability doesn't spring from a pretty presentation. It emerges from hundreds of small fixes, real tests, and the unpleasant willingness to admit that yesterday's brilliant solution has turned out to be complete fucking nonsense today.

    We won't promise that RouterForge will never encounter another bug. Only someone who has never written software could make that promise. Or a marketing director. Which, in terms of hands-on debugging experience, are fairly similar categories.

    We promise something else: when we discover another stupid mistake of our own, we won't pretend it's an innovative new feature for which users should feel grateful. We'll simply fix it. Then, naturally, write another patch note about it, because we have to justify the existence of the Releases section somehow.

    Until the next update, friends. Keep using RouterForge. Press buttons. Change settings. Reboot your routers. And if something breaks again, please tell us.

    We'll open the logs, inspect the source code, hold three meetings with our own common sense, and sooner or later find out which fucking idiot wrote it. Chances are, we won't have to look very far.

    For now, thank you for testing our patience significantly less often than we test yours.

    The RouterForge Team.

    Technically capable. Architecturally overconfident. Regularly fucking astonished by the results of our own work.

    P.S. If DNS fails to start after rebooting again following this release, we'll officially rename ndmc “Sleeping Beauty” and send the developers to kiss the source code until everything works again.

    Although, judging by the number of mistakes we've made, some of us may have to spend the rest of our lives with it.

    Downloads