Привет, Хабр! Мы — команда проекта ChameleonLab, и это история о том, как мы начали создавать полномасштабный образовательный центр по стеганографии и криптографии, отправной точкой которого стал наш desktop-инструмент.
По просьбам пользователей мы начали трансформацию в онлайн-сервис. Расскажем, как мы создали сайт на собственном микро-движке, который работает на JSON-файлах, почему отказались от популярных CMS и как планируем переносить сложную логику с Python в веб.

От Desktop-приложения к образовательному центру
ChameleonLab — это наша попытка сделать сложные концепции стеганографии доступными для всех. Это desktop-приложение для Windows и macOS, которое позволяет не просто прятать данные в файлы (от картинок до DOCX), но и анализировать их, визуализировать LSB-слои, оценивать стойкость паролей и даже слушать музыку, "зашитую" в изображение.

Проект тепло встретили, но почти сразу появился главный запрос от пользователей: "А будет ли онлайн-версия?". Люди хотели иметь доступ к инструментам без установки ПО. Это стало для нас главной мотивацией для создания сайта chalab.ru, который должен стать не просто визиткой, а полноценным образовательным центром.

Технологии: свой PHP-движок на JSON-файлах
Мы сразу отказались от готовых CMS.
Почему не WordPress или любая другая CMS?
Безопасность. Из нашего опыта разработки, взлом CMS — это просто бич. Из-за огромной кодовой базы и популярности, они становятся главной целью для атак. Сайты постоянно заражают вирусами через уязвимости в плагинах и темах. Наш подход с минималистичным движком и отсутствием базы данных на порядок снижает поверхность атаки.
Чистота кода. Готовые CMS несут в себе тонны унаследованного кода, тысячи настроек и функций, из которых нам понадобилось бы не больше 5%. Это лишний балласт, который замедляет сайт и усложняет поддержку.
Отказоустойчивость. Сайт, работающий на файлах, практически невозможно "положить" высокой нагрузкой. У него нет узкого горлышка в виде лимита подключений к базе данных. Каждый запрос обрабатывается независимо, что делает систему крайне стабильной. Такой сайт будет работать даже на самом дешевом хостинге. А его восстановление после сбоя — это простое копирование файлов, без необходимости возиться с дампами баз данных.
Наш собственный микро-движок на PHP построен на нескольких ключевых принципах:
1. Уникальная файловая структура
Весь контент сайта — статьи блога, статические страницы, категории и даже переводы — хранится в JSON-файлах. Это наша единственная "база данных".
/articles/
- содержит.json
файлы для каждой статьи./pages/
-.json
файлы для статичных страниц, таких как документация./data/
- здесь лежат категории, счётчики и другие глобальные данные./lang/
- файлы с переводами интерфейса.
Уникальность подхода в том, что для добавления новой статьи нам даже не нужна админ-панель (хотя она и есть для удобства). Достаточно просто создать новый JSON-файл с нужной структурой и загрузить его в папку /articles/
по FTP. Сайт тут же его "подхватит" и отобразит.
2. Мультиязычность "на лету"
Аналитика показала, что большинство пользователей нашего приложения — англоязычная аудитория. Поэтому мультиязычность стала для нас приоритетом №1. Мы создали систему, которая позволяет переключать язык сайта "на лету", без перезагрузки и сложных запросов.
Тексты интерфейса хранятся в файлах lang/ru.php
и lang/en.php
. А контент самих статей структурирован по языкам внутри JSON-файлов.
Главное преимущество такой технологии в том, что для добавления нового языка (например, немецкого или испанского) нам не нужно менять код движка. Достаточно просто добавить файлы lang/de.php
, lang/es.php
и перевести текстовое содержимое в JSON-файлах. Это позволяет в кратчайшие сроки сделать сайт по-настоящему международным.
3. Как это работает: фрагмент кода
Вот упрощенный пример того, как наш движок загружает статью. Всё предельно просто:
// Получаем ID статьи и язык
$article_id = $_GET['id'];
$lang = $_SESSION['lang'] ?? 'ru';
// Читаем нужный JSON-файл
$json_data = file_get_contents("articles/{$article_id}.json");
$article = json_decode($json_data, true);
// Извлекаем заголовок и контент для нужного языка
$title = $article[$lang]['title'];
$content = $article[$lang]['content'];
// ...дальше просто выводим переменные в HTML-шаблон
Никаких сложных запросов, ORM или кеширования. Просто и быстро.
4. SEO-функционал "из коробки"
Мы сразу реализовали несколько важных SEO-инструментов:
Генератор
sitemap.xml
: Скрипт, который автоматически сканирует папки с контентом и создает карту сайта для обеих языковых версий.RSS-ленты: Файл
rss.php
на лету создает RSS-поток для русского и английского языков (rss.php?lang=en
).robots.txt
: Правильно настроен для поисковиков.
Планы на будущее: Философия переноса в веб
Наша конечная цель — не просто сайт, а полноценное веб-приложение. Desktop-версия ChameleonLab написана на Python, и мы не собираемся переписывать всю сложную логику анализа изображений и криптографии на PHP. Наша философия — использовать правильный инструмент для каждой задачи.
Поэтому мы выбрали следующий путь:
Создание Web API на Python. Мы возьмем ключевые модули из нашего desktop-приложения и "обернем" их в API с помощью легкого фреймворка, такого как Flask. Этот API будет принимать файл, выполнять над ним операции и возвращать результат в формате JSON.
Интерактивный фронтенд. Наш существующий PHP-сайт будет дополнен JavaScript-компонентами. Пользователь будет загружать файл через интерфейс сайта, JavaScript будет отправлять его на наш Python API, получать результат и наглядно отображать его на странице.
Такой подход позволит нам сохранить всю мощь и производительность Python для сложных вычислений, используя при этом наш легкий PHP-движок для отображения контента. В нашем блоге мы обязательно опубликуем серию статей о технических деталях этого процесса, где подробно расскажем о создании API на Flask и его интеграции с сайтом.
Заключение
ChameleonLab 1.5 — это результат нашего стремления создать интуитивно понятный и мощный инструмент для работы с цифровыми файлами. Мы верим, что он будет полезен как профессионалам в области информационной безопасности, так и энтузиастам, которые только начинают свой путь в увлекательном мире стеганографии.
Спасибо, что остаетесь с нами. Мы постоянно получаем идеи и сообщения об ошибках в нашем Telegram-канале, что позволяет нам постоянно улучшать продукт.
Последнюю версию программы ChameleonLab для Windows и macOS можно скачать на нашем официальном сайте. Программа также доступна на популярных торрент-трекерах.
Комментарии (0)
nin-jin
21.09.2025 02:18$article_id = $_GET['id']; $json_data = file_get_contents("articles/{$article_id}.json"); // ...дальше просто выводим переменные в HTML-шаблон
Сразу видно экспертов по безопасности.
supercat1337
21.09.2025 02:18Тоже поржал. Надеюсь, что они просто валидацию не стали публиковать, иначе зашквар.
Lomakn Автор
21.09.2025 02:18Ваша надежда вас не обманула. Мы действительно опустили код валидации в статье, чтобы не перегружать пример и сфокусироваться на основной идее файлового подхода. В реальном проекте, само собой, все входящие данные проходят необходимую проверку.
Lomakn Автор
21.09.2025 02:18Спасибо за комментарий! Что касается
$_GET['id']
, вы абсолютно правы, что в статье показан упрощенный пример. В реальном коде мы, конечно же, используемbasename()
для защиты от directory traversal и другие методы валидации, чтобы обезопасить систему. Спасибо, что обратили на это внимание — возможно, стоило уточнить это в статье.
Pavel1114
21.09.2025 02:18поспорю с тезисами против CMS:
1. Безопасность. Из ваших слов несведущие читатели могут сделать вывод, что в популярные CMS все в дырах. Но это не так - уверен, работающий эксплот для wordpress можно продать за очень хорошие деньги. Конечно всё это подразумевает регулярные обновления и не установку подозрительных плагинов.
2. Чистота кода. У меня тоже когда то было такое ЭГО) Интересно, через сколько внедрённых фич в вашем коде даже вы не сможете разобраться.
3. Отказоустойчивость. Чем по вашему обусловлены лимита подключения к БД?) Не ограничениями ли файловой системы? Ну и тут вы (как и везде в статье) сравниваете ваш нано-движок с полноценными приложениями. Уверен, если бы вы перенесли ваши json структуры в какой нибудь postgres, оставив столь же минималистическую логику, то выиграли бы в производительности. А, попутно, сделали бы систему на порядки более гибкой.sunnybear
21.09.2025 02:18Если перенесли файлы на диск в памяти - выигрыш в производительности будет. Если просто в бд - не однозначно, появятся накладные расходы.
Pavel1114
21.09.2025 02:18согласен неоднозначно. Выигрыш может быть за счёт оптимизации доступа из коробки (кэширования в памяти), отказа от разбора json. Но в любом случае разница будет настолько минимальна, что и посчитать её сложно, не то что почувствовать.
Lomakn Автор
21.09.2025 02:18Мы согласны, что ядро популярных CMS достаточно защищено. Однако наша главная цель — интеграция с Python-бэкендом. Использование сторонних плагинов для такой кастомной задачи могло бы создать уязвимости. Имея полностью свой, минималистичный код, мы на 100% контролируем все точки входа и выхода, что критически важно для будущего API.
Lomakn Автор
21.09.2025 02:18Здесь речь не об ЭГО, а о подготовке к масштабированию. Мы сознательно держим PHP-часть максимально простой ("тонкой"), чтобы она служила лишь для отображения контента. Вся сложная бизнес-логика будет жить на стороне Python. Такой подход разделения ответственности (content rendering vs. application logic) не дал бы нам реализовать ни один готовый CMS без серьезных "костылей".
SerafimArts
21.09.2025 02:18Странно. Обычно делают ровно наоборот. Для MVP берут более простой и эффективный язык, вроде Python (ну или тот же PHP "в режиме Laravel"), а для полноценной комплексной разработки более enterprise-like, вроде PHP, C# или Java (Symfony, .NET или Spring соответственно).
Ну или наоборот можно уйти в "примитивизм" и логику "вырезать" в отдельные сервисы и тут уже Node или Go.
Я так понимаю просто команда из питонщиков? Иначе не понимаю смысла.
Lomakn Автор
21.09.2025 02:18Спасибо за комментарий, вы описали абсолютно классический и верный подход к веб-разработке!
Наш случай немного нестандартный, потому что мы не создаем веб-проект с нуля. Мы переносим в веб уже готовое desktop-приложение, вся сложная логика которого уже написана на Python.
Именно поэтому мы не стали брать Python/Flask для MVP сайта-визитки. Наша задача была — максимально быстро создать «обложку»: блог и документацию. Для этой цели PHP на простом хостинге — самое быстрое и дешевое решение, которое не требует сложной настройки.
Сейчас мы как раз и находимся на этапе, когда «вырезаем логику в отдельные сервисы», как вы и предложили. Наша PHP-часть останется простым сайтом для контента, а вся «магия» стеганографии будет работать как отдельный микросервис на Python/Flask, к которому мы будем обращаться через API.
Так что да, в команде действительно сильная экспертиза в Python, но выбор стека продиктован не только этим, а прагматичным подходом: использовать уже готовый, отлаженный код на Python для сложных задач и максимально простое и быстрое решение на PHP для контента.
Lomakn Автор
21.09.2025 02:18Отказоустойчивость: Вы правы, сравнение не совсем прямое. Но наш тезис в том, что для текущей задачи (блог и документация) файловая система — это оптимальное и невероятно стабильное решение. Оно позволяет нам не беспокоиться об обслуживании базы данных и сосредоточиться на главной задаче — разработке веб-версии нашего Python-приложения.
Pavel1114
21.09.2025 02:18После прочтения статьи у меня сложилось впечатление, что вы собрались самостоятельно пройти весь путь, который прошла вебразработка за последние лет 15-20. На примере хранения данных. Сейчас вы храните всё в файлах. Потом задумаетесь о бэкапах. Потом нужна будет индексация. Следом чуть более сложная структура. Где то между захотите внедрить сессии. Потом решите, что без админ панели всё же никак. Год-два и вы уже не сможете разобраться где что и как у вас храниться.
Lomakn Автор
21.09.2025 02:18Спасибо за отличный комментарий и фидбек! Вы подняли очень важный и, по сути, философский вопрос в веб-разработке: где грань между «изобретением велосипеда» и созданием инструмента, идеально заточенного под конкретную задачу?
Вы совершенно правы, если бы мы строили универсальную CMS, то мы бы действительно пошли по пути, который веб-разработка уже прошла. Но наша цель совершенно иная.
Наш PHP-движок — это не конечный продукт, а лишь временный, максимально простой «слой» для доставки контента. Его главная задача — позволить нам быстро запуститься, собрать аудиторию и подготовить плацдарм для основного блюда: полноценного веб-приложения на Python.
Давайте по пунктам:
Бэкапы: С файловой системой это как раз проще простого.
tar -czvf backup.tar.gz .
или простое копирование по FTP, и у вас полная, консистентная копия сайта. С базами данных всё немного сложнее (дампы, согласованность).Сессии и админ-панель: Они у нас уже есть, как и упоминалось в статье. Они очень простые, потому что наши задачи простые: аутентификация одного-двух авторов и редактирование текста.
Индексация и сложные структуры: Это справедливое замечание. Когда статей станет много,
glob()
перестанет быть эффективным. Но к тому моменту, когда это произойдет, наш основной бэкенд уже будет на Python, и задачи индексации и поиска мы решим специализированными инструментами (например, подключив легковесный поисковый движок), а не будем усложнять наш PHP-код.
Ключевой момент в том, что мы не планируем превращать PHP-часть в сложную систему. Её задача — оставаться «тонким» слоем для отображения. Вся «тяжелая» и сложная логика будет жить в Python API. Мы не дойдем до состояния «не сможем разобраться», потому что сознательно ограничиваем сложность на стороне PHP, готовя её к интеграции, а не к бесконечному развитию.
Pavel1114
21.09.2025 02:18tar -czvf backup.tar.gz и ftp не гарантируют консистентность. Не понятно в чём сложность обслуживания и бэкапа баз данных. Там вроде тоже одной командой всё делается. Иногда даже cron не нужен. И о каком "обслуживании" идёт речь?
И непонятно тогда зачем вам вообще какая то php прослойка - раз у вас есть python и вы собираетесь использовать flask. Добавляйте туда sqlite, jinja и готово.
Lomakn Автор
21.09.2025 02:18Спасибо за правильные вопросы! Мы много подчеркиваем идей благодаря Вам! Вы правы, для высоконагруженных систем с постоянной записью
tar
не идеален. Но для нашего сайта в данный момент, который обновляется несколько раз в неделю одним-двумя авторами, риск несогласованности практически нулевой. Для нас «обслуживание» — это полный цикл: настройка, управление пользователями, обновления. Наш файловый подход просто имеет меньше движущихся частей на данном этапе, что и было нашей целью для быстрого старта.По поводу: Зачем нужна PHP-прослойка?
Ответ — скорость запуска и разделение задач.
Быстрый старт: Мы развернули сайт на PHP на самом дешёвом хостинге буквально за пару дней. Полноценная настройка Python-окружения (с WSGI, Nginx и т.д.) заняла бы значительно больше времени.
Будущая архитектура: PHP у нас — это просто «тонкий» и быстрый слой для отображения контента (статей и документации). Вся сложная логика нашего приложения будет жить в отдельном Python/Flask API. Мы не смешиваем одно с другим. PHP-сайт будет просто обращаться к этому API.
Такой подход позволяет нам использовать сильные стороны каждого инструмента: PHP для быстрой отдачи страниц, а Python — для сложных вычислений, в которых он хорош.
Pavel1114
21.09.2025 02:18Радует что люди не разучились нормально воспринимать критику и просто вопросы.
supercat1337
21.09.2025 02:18Вот кстати не факт, что выигрыш в производительности будет: так-то и подключение к бд тоже несёт накладные расходы, в виде организации подключения по tcp, проверка прав пользователя и опять же чтения данных из группы файлов. Если необходимо работать с развесистыми данными, писать, читать, уделять внимание безопасности, то да, тут работа с СУБД лучше. А если выбирать между чтением и разбором мелкого json и использованием огромной махины СУБД для той же цели, то первое может быть более оптимальным выбором. Тем более, если чтение, то блокировки файлов не будет.
amvasiljev
21.09.2025 02:18Уникальность подхода в том, что для добавления новой статьи нам даже не нужна админ-панель (хотя она и есть для удобства). Достаточно просто создать новый JSON-файл с нужной структурой и загрузить его в папку /articles/ по FTP. Сайт тут же его "подхватит" и отобразит.
Звучит зловеще. Отдаленно напоминает Grav CMS, с twig и blueprints. Но там человеческая админка.
А как вы выводите навигацию? А формы? При смене родителя, если такое у Вас возможно, ресурс сменит родителя в URL? Вы реализовали ЧПУ для URL? Что именно дает пользователю json - это аналог blueprints из grav, или md-файла из vitepress?
Up: в grav тоже md, принты нужны как раз для админки. Все не просто. Ни у кого не просто.
Lomakn Автор
21.09.2025 02:18Спасибо за интересные вопросы и фидбек. На 4 ваших вопроса 4 ответа:
1. "Зловеще": На самом деле, всё довольно просто. Возможность добавить статью через FTP — это скорее бонус для нас как для разработчиков для быстрого деплоя. Для повседневной работы у нас есть простая админка с TinyMCE, как и упоминалось. Наш движок мы собрали буквально за два дня, так что его простота — это его главное преимущество.2.Навигация и формы: Меню навигации и другие сквозные блоки подгружаются из языковых PHP-файлов. Формы (например, обратной связи, если понадобится) обрабатываются отдельными PHP-скриптами.
3.ЧПУ и структура URL: На данный момент у нас простая структура (
/post.php?id=21
). Реализовать ЧПУ (человекопонятные URL) с помощью.htaccess
для такого движка — задача элементарная, как два байта передать. Мы просто добавим в JSON полеslug
и будем использовать его вместоid
.4.Роль JSON: В нашей системе JSON — это конечный источник данных, аналог записи в базе данных, а не
blueprints
илиmarkdown
-файлы для дальнейшей обработки. PHP просто читает его и сразу выводит в шаблон.
FireWind
21.09.2025 02:18Отсылка на небезопасность существующих десятилетиями CMS, которые внедрены в десятках миллионов экземпляров - очень натянутый аргумент. Практически все обнаруженные уязвимости у них - сторонние темы, плагины и криворукие доработки.
Использование (если я правильно понял) PHP, Python, JS одновременно, странное решение. Хотя - хозяин-барин
Lomakn Автор
21.09.2025 02:18Спасибо за комментарий! Вы абсолютно правы насчет CMS: ядро популярных систем действительно хорошо зашищено. Наш аргумент был как раз о том, что мы хотели избежать рисков, связанных с экосистемой сторонних плагинов и тем. Для реализации наших будущих планов нам бы потребовалось много кастомного функционала, а поиск и аудит безопасных плагинов — это отдельная большая работа. Наш собственный код проще и полностью контролируется нами.
Что касается стека (PHP, Python, JS) — это не странное решение, а, на наш взгляд, самое прагматичное. Мы используем каждый язык для той задачи, где он лучше всего себя показывает:
PHP: Идеально подходит для нашего простого и быстрого "движка" по отображению контента из файлов.
Python: На нём уже написана вся сложная логика нашего desktop-приложения (анализ, криптография). Переносить её на PHP было бы нецелесообразно. Гораздо эффективнее "обернуть" её в API.
JS: Будет служить "клеем" между нашим PHP-сайтом и Python API, обеспечивая интерактивность для пользователя без перезагрузки страниц.
Это классический подход с разделением на фронтенд (PHP+JS) и бэкенд (Python), который позволяет использовать сильные стороны каждого инструмента.
SolidSnack
21.09.2025 02:18Фронтенд на php сложно назвать классикой)) яб даже сказал это наоборот - изюминка))
MetaDone
21.09.2025 02:18если на php хотите не сильно заморачиваясь и без кучи велосипедов - берете laravel, sqlite как базу и filament для админки. и расширяемо будет, и все что уже приделали там есть. при этом сторонний специалист спокойно разберется если такой будет нужен
JBFW
21.09.2025 02:18Уникальность подхода в том, что для добавления новой статьи нам даже не нужна админ-панель (хотя она и есть для удобства). Достаточно просто создать новый JSON-файл
Миленниалы изобрели index
.html.json )Не обижайтесь, просто забавно как история идет по кругу.
Там еще были такие SSI, это когда часть сайта - footer-header etc. - вынесены в отдельные файлы, и подключаются автоматически при рендеринге страницы...Ну а в принципе, почему нет? JSON вместо HTML, и свой веб-сервер вместо Апача...
Lomakn Автор
21.09.2025 02:18Спасибо за отличный комментарий! Вы подняли очень важный и, по сути, философский вопрос в веб-разработке: где грань между «изобретением велосипеда» и созданием инструмента, идеально заточенного под конкретную задачу?
Вы совершенно правы, история веб-разработки циклична, и многие современные подходы уходят корнями в старые технологии, вроде SSI. Мы видим эти параллели.
Ключевое отличие нашего подхода не в том, чтобы изобрести что-то абсолютно новое, а в том, чтобы сознательно выбрать самый простой инструмент для очень специфической задачи. Наш PHP/JSON-слой не пытается заменить Apache или HTML; это легковесная система доставки контента, разработанная с первого дня для обслуживания будущего веб-приложения на Python.
Мы могли бы использовать генератор статичных сайтов, но это усложнило бы наш план по интеграции динамичного, интерактивного бэкенда на Python. Мы выбрали этот путь, потому что он дал нам невероятно быструю, безопасную и простую в управлении отправную точку, позволив сосредоточить основные усилия на более сложной задаче — переносе функций нашего десктопного приложения в веб.
udattsk
21.09.2025 02:18Вы без ГПТ не можете совсем? (
Lomakn Автор
21.09.2025 02:18Для любителей ГПТ и других у нас есть статья https://habr.com/ru/articles/941996/
slavabars
21.09.2025 02:18Если вам понадобится добавить ещё одно поле на странице к статьям, вы будете перестраивать все свои json или вам это не важно и все нововведение поля в json будут только для новых файлов, а на стороне валидации вы будете просто проверять существование поля? Массовую замену по json уже делали, если вдруг нужно будет в статьях найти и поменять какое то слово?
JBFW
21.09.2025 02:18Ну, технически это несложно. Пишем скрипт, который считывает JSON, добавляет поле, сохраняет обратно, и так по группе файлов.
Та же CMS, только оффлайн и возможно оффсайт. Попробуй сломай такое...
ZiggiPop
Есть же Jekyll, Gatsby и другие генераторы статических сайтов. Для чего нужно изобретать велосипед?
supercat1337
Видимо им в своем велосипеде будет проще разобраться, чем в чужом. Ну, и уверенность в безопасности своего кода.
Lomakn Автор
Нам было важно создать максимально простую панель управления, заточенную именно под нашу структуру контента (статьи, документация, категории). Разбираться в чужой архитектуре, плагинах и шаблонизаторах заняло бы больше времени, чем написать своё решение с нуля. Мы начали этот проект, чтобы сэкономить время и запуститься быстро, а не писать сайт годами.
Lomakn Автор
Наша главная цель — перенести основной функционал нашего desktop-приложения (написанного на Python) в веб. Для этого мы планируем использовать Python-фреймворк (например, Flask) для бэкенда. Нам нужен был максимально чистый и контролируемый фронтенд на PHP, в который будет легко интегрировать API. Готовые генераторы и CMS добавили бы лишний слой абстракции, который только усложнил бы эту задачу.