Двор со шлагбаумом живёт по простым правилам: своим — открыто, гостям — по звонку, за обслуживание — платят. Держать это в тетради и в чате дома неудобно, и здесь появляется система управления шлагбаумом BAS-IP 2.0.2: жильцы, начисления с перерасчётом, гостевые QR-пропуска, журнал открытий и REST API для панели домофона. Ниже — что внутри, что показал прогон на живом PHP и какие грабли ждут на PHP 8.5.

TL;DR: что это и чем проверено
- Тип. Самостоятельно размещаемое PHP-приложение для управления шлагбаумом в жилом комплексе.
- Данные. MySQL, MariaDB, PostgreSQL или SQLite — схема переносимая.
- Деньги. Начисления с перерасчётом, расщепление до копейки, учёт оплат.
- Доступ. Гостевые QR-пропуска и журнал каждого открытия.
- Проверка. 232 PHP-файла проверены
php -l— ноль ошибок синтаксиса;/health.jsonна PHP 8.5 отвечает 500.
Проблема, которую это решает
Шлагбаум во дворе — это не только железо. За ним стоит учёт: кто живёт, кто платит, кто в гостях и когда створка поднималась.
Обычная практика выглядит так: список жильцов в таблице, платежи в переписке, гостевые пропуска по звонку старшему по дому. Пока дом маленький — работает. Как только квартир сотня, начинаются споры: «я платил», «у меня гости», «почему не открылось».
Приложение переносит этот учёт в базу: у каждого событие с датой, у каждого платежа — история, у каждого открытия — запись. И, что важно, оно не требует облака: сервер можно держать в том же доме.
Что такое BAS-IP
flowchart TB WEB["public/index.php: точка входа"] --> CORE["ядро: роутер, сессии, конфиг"] CORE --> DB["БД: MySQL, PostgreSQL или SQLite"] CORE --> DEV["панель домофона: REST API"] CORE --> JOBS["расписание: сбор платы и напоминания"] CORE --> STORE["storage: логи, бэкапы, кэш"]
| Свойство | Значение |
|---|---|
| Версия в разборе | 2.0.2 «Kronos» |
| Рантайм | PHP 8.2+, рекомендуется 8.5 |
| База данных | MySQL 8, MariaDB 10.6+, PostgreSQL 13+, SQLite 3 |
| Веб-сервер | nginx или Apache, docroot — public/ |
| Зависимости | без CDN, сборка через npm только для стилей |
| Лицензия | в дистрибутиве есть LICENSE |
| Поставка | архив bas-ip-2.0.2.zip с контрольной суммой |
Дистрибутив — сборка без тестов и служебных скриптов: tests/ и tools/ в архив не входят, о чём стоит знать заранее, если вы привыкли гонять php tests/run.php из клона.
Возможности
Жильцы и помещения
| Что есть | Зачем |
|---|---|
| импорт из CSV, JSON, Excel | перенос списка из таблицы без ручного ввода |
| инспекция и маппинг колонок | сопоставление своих полей со схемой |
| экспорт всех данных | резервная копия и передача новому правлению |
| бэкапы БД | mysqldump, pg_dump, SQLite — с восстановлением |
Деньги и начисления
| Что есть | Зачем |
|---|---|
| ежемесячные начисления | регулярный сбор без ручных таблиц |
| перерасчёт | исправление ошибок без правки истории |
| расщепление до копейки | распределение платежа по периодам |
| FIFO оплат | понятный порядок закрытия задолженностей |
Доступ и журнал
| Что есть | Зачем |
|---|---|
| гостевые QR-пропуска | гость проходит без звонка |
| журнал открытий | видно, кто и когда открывал |
| REST API | связка с панелью домофона |
/health.json |
проверка состояния мониторингом |
Как это работает
flowchart LR CHK["проверка релиза"] --> ZIP["снимок текущей версии"] ZIP --> GET["скачивание архива"] GET --> EX["распаковка в каталог"] EX --> MIG["миграции БД"] MIG --> OK["health.json: status ok"]
Конфигурация собирается из трёх источников: локальный файл, .env, значения по умолчанию — и это правильный порядок, потому что секреты остаются вне git. При обновлении локальный файл не перезаписывается, а значит настройки не теряются.
Обновление идёт через UpdateService: снимок текущей версии, скачивание архива, распаковка, миграции. Снимок делается через ZipArchive; если расширения zip нет, приложение не падает фатально, а сообщает, что создать снимок невозможно — это и есть главное исправление версии 2.0.2.
Проверка состояния — отдельный эндпоинт health.json, который перечисляет загруженные расширения. Удобно: мониторинг видит проблему раньше, чем жильцы.
Замеры и цифры
Проверено 13.11.2026, двумя проверками.
| Что | Значение |
|---|---|
Архив bas-ip-2.0.2.zip |
1 113 546 байт |
| SHA-256 | e6d248f0…22c9f9d, совпал с .sha256 из релиза |
| Файлов в архиве | 289 |
| Состав | PHP 232, .woff2 12, .js 8, .css 5, .json 3 |
php -l по всем файлам |
232 проверено, 0 ошибок |
tests/, tools/ в дистрибутиве |
отсутствуют |
bin/bas-ip doctor |
подключение к MySQL отклонено (учётки нет), сообщение понятное |
| Запуск на PHP 8.5.4 | GET / → 302 на /install; /install → 500; /health.json → 500 |
| Причина 500 | ini_set(): session.sid_length INI setting is deprecated — предупреждение превращается в исключение |
| Версия в коде | App::VERSION = '2.0.2' |

Главный результат — не 232 чистых файла, а расхождение с заметками к релизу. Там сказано: 217 тестов зелёные на PHP 8.5 (SQLite), /health.json отдаёт 200. У нас на PHP 8.5.4 установщик и health.json отвечают 500 из-за устаревшей опции сессии session.sid_length, которую в PHP 8.5 объявили deprecated. Предупреждение в этом приложении становится ErrorException и валит запрос до того, как установщик успевает что-то показать.
Это не значит, что продукт сломан: на 8.2–8.4 всё работает, а тесты, судя по всему, ставят свой обработчик ошибок. Но факт остаётся фактом: на самой свежей версии PHP первая страница не открывается, и это надо знать до установки.
Сильные стороны продукта
- Нет обязательного облака. Ставится на свой сервер, данные остаются у дома.
- Четыре СУБД на выбор. SQLite для проверки, MySQL или PostgreSQL для боевой работы.
- Переносимые миграции. Схема одна и та же на всех движках.
- Секреты вне репозитория. Локальный конфиг и
.envне перезаписываются обновлением. - Понятная диагностика.
doctorиhealth.jsonотвечают на вопрос «чего не хватает» до запуска. - Контрольные суммы релиза. Архив можно проверить перед распаковкой.
- Журнал открытий. Спор «кто открыл» решается фактом, а не памятью.
Установка
unzip bas-ip-2.0.2.zip -d /srv/bas-ip
cd /srv/bas-ip
sha256sum -c bas-ip-2.0.2.zip.sha256 # если архив рядом
php bin/bas-ip doctor
php bin/bas-ip serve # локальный сервер на 8080
| Требование | Значение |
|---|---|
| PHP | 8.2 или новее |
| Обязательные расширения | pdo, mbstring, curl, json, openssl |
| Для бэкапов и обновлений | zip |
| Для шифрования секретов | sodium |
| docroot | public/ |
Каталог storage/ |
должен быть доступен на запись |
| cron | php bin/bas-ip schedule:run --quiet раз в минуту |
Настройка
flowchart TD L1[".bas-ip.config.local.php"] --> M["слияние: скаляры заменяются"] L2[".env"] --> M L3["config/config.php"] --> M M --> USE["итоговая конфигурация"]
| Что настроить | Где |
|---|---|
| Подключение к БД | локальный конфиг или переменные DB_* |
| Адрес панели домофона | DEVICE_BASE_URL, логин и пароль |
| Почта и Telegram | секция notify |
| Обновления | UPDATE_ENABLED, UPDATE_MODE, токен GitHub |
| Секреты | php bin/bas-ip secret:set <имя> и ссылка ${secret=...} |
| Расписание | cron раз в минуту |
Порядок загрузки: локальный файл, затем .env, затем значения по умолчанию. Скаляры заменяются, списки тоже — если только ключ не помечен суффиксом +.
Почему учёт двора — это деньги, а не железо
Соблазн считать шлагбаум железной задачей велик: есть панель, есть брелоки, остальное приложится. Но 90 % конфликтов во дворе — не про створку, а про счёт.
Типичная история: жилец платил в январе, но платёж пришёл в феврале. В таблице это одна строка, в жизни — спор о задолженности. Приложение решает это распределением по периодам: платёж закрывает долг в порядке очерёдности, а не «как записали».
Вторая история: начисление сделали с ошибкой, обнаружили через месяц. В тетради придётся зачёркивать и объяснять. В системе есть перерасчёт, и он оставляет след — видно, что было и что стало.
Третья: гости. Гостевой пропуск, выданный на час, — это документ с временем. Журнал открытий показывает, когда створка поднималась, и вопрос «кто впустил» перестаёт быть предметом веры.
Отсюда и требования к таким системам: не «красивый интерфейс», а воспроизводимость расчёта и след каждого действия.
Что показывает прогон про качество кода
Формальная проверка синтаксиса — не тест качества, но кое-что она говорит.
Двести тридцать два файла без единой ошибки php -l означают, что код собирается целиком: нет забытых скобок, нет файлов, которые не загружаются. Для проекта, который ставят через распаковку архива, это важнее, чем кажется: одна опечатка в неиспользуемой ветке ломает только её, а в загрузчике — всё приложение.
Второе наблюдение: doctor сначала честно сообщает, что базы нет. Это правильное поведение — диагностика должна отвечать «чего не хватает», а не падать с фатальной ошибкой.
Третье: обработка ошибок качественная. В логе видно структурированные записи JSON с полем context, где указан файл и строка. Разбирать инцидент по такому логу можно без отладчика.
И четвёртое, менее приятное: та же строгость обернулась против установщика на PHP 8.5. Предупреждение о устаревшей опции стало исключением — механизм правильный, но одна конкретная настройка сессии его не пережила.
Где приложение не подойдёт
Честные границы.
Не подойдёт, если двор управляется облачным сервисом с готовой поддержкой: здесь всё на вашем сервере, включая обновления и бэкапы.
Не подойдёт, если нет человека, который будет следить за cron, бэкапами и обновлениями. Самостоятельный хостинг — это ответственность, а не только независимость.
Не подойдёт для дома на пять квартир: таблица и чат справятся дешевле.
И не подойдёт как замена бухгалтерии: начисления и перерасчёты — да, полноценный бухгалтерский учёт с планом счетов — нет.
Зато подойдёт там, где важен след: журнал открытий, история платежей, воспроизводимый расчёт. Именно это и есть причина ставить систему, а не держать список в таблице.
Что видно в логах при разборе
Логи — структурированные: каждая запись это JSON с полями ts, level, channel, message, context. В контексте есть файл и строка, если это исключение.
Три канала разделены: app — обычные события, error — ошибки, отдельно есть записи уровня error с контекстом команды (например, command: doctor). Такое разделение экономит время: при разборе инцидента не нужно фильтровать всё подряд.
Полезная деталь: сообщение об отказе базы данных содержит driver и текст ошибки драйвера, но пароль в выводе замаскирован. Это правильное поведение — лог можно приложить к обращению, не вычищая секреты руками.
Что стоит настроить: ротацию файлов логов. По умолчанию они пишутся в storage/logs с датой в имени, и при отсутствии ротации каталог растёт. Для двора в сотню квартир это не критично, для нескольких домов — уже вопрос места.
И последнее: журнал открытий — тоже лог, но прикладной. Он нужен жильцам, а не администратору, поэтому храните его отдельно от технических логов и в экспортируемом виде: при смене правления выгрузка должна оставаться у дома.
Подводные камни
- PHP 8.5 ломает установщик.
session.sid_lengthобъявлен deprecated, предупреждение становится исключением,/installотдаёт 500. zipбез вариантов. Без расширения нет ни бэкапа, ни обновления — проверяйте первым делом.- Тестов в дистрибутиве нет.
tests/иtools/в архив не входят; для прогона тестов нужен клон. - docroot только
public/. Иначе наружу уедутconfig/,storage/и локальный конфиг с секретами. - Учётки БД по умолчанию нет.
doctorпадает на подключении, если не создать базу и пользователя. - cron обязателен. Без
schedule:runне будет ни начислений по расписанию, ни напоминаний. - Обновление меняет файлы. Снимок версии создаётся заранее — не отключайте эту проверку.
- Локальный конфиг вне git. Иначе после обновления можно потерять настройки или, наоборот, закоммитить пароль.
- Расширение
intlопционально. От него зависит форматирование дат и чисел: без него вид дат будет проще. - Панель домофона нужна для реального открытия. Без неё система ведёт учёт, но створку не поднимает.
- Демо-данные — это демо. Проверять деньги на них можно, считать — нет.
Деньги в такой системе: что проверять руками
Автоматика ошибается тихо, поэтому первые начисления стоит сверить вручную — не «посмотреть, что красиво», а пересчитать.
Проверка первая: расщепление платежа. Внесите платёж, который больше текущего долга, и посмотрите, куда уйдёт остаток. Правильное поведение — закрыть долг и оставить переплату видимой, а не «потерять» её.
Проверка вторая: перерасчёт. Измените начисление за прошлый месяц и убедитесь, что в истории осталась запись о причине, а не только новое значение.
Проверка третья: округления. Возьмите сумму, которая делится на количество дней неровно, и сверьте итог с копейками. Расхождение в копейку на сотне квартир — это уже спор.
Проверка четвёртая: FIFO. Два долга разных периодов и один платёж. Порядок закрытия должен быть предсказуемым и одинаковым при повторном запуске.
Проверка пятая: экспорт. Выгрузите всё и откройте в таблице: если данные читаются и суммы совпадают, у вас есть резервная копия не только в виде дампа БД.
Про обновления и снимки версии
Механика обновления устроена разумно: перед заменой файлов создаётся снимок текущей версии, а распаковка идёт через ZipArchive. Версия 2.0.2 добавила проверку наличия расширения zip в двух местах, где её не было, — и это ровно тот класс ошибок, который обнаруживается в самый неподходящий момент.
Практический вывод для администратора: держите отдельный бэкап каталога и базы перед каждым обновлением, даже если приложение обещает снимок. Два независимых способа откатиться стоят дешевле одного.
И ещё: канал обновлений stable смотрит на последний релиз. Отсюда следует, что откат «на предыдущую» автоматикой не предусмотрен — только вручную, из снимка.
Чек-лист
- [ ] Скачать архив и сверить SHA-256.
- [ ] Проверить версию PHP: 8.2–8.4 для спокойной работы, 8.5 — с оговоркой про сессии.
- [ ] Убедиться, что расширения
pdo,mbstring,curl,json,openssl,zipесть. - [ ] Создать базу и пользователя, проверить
php bin/bas-ip doctor. - [ ] Направить docroot на
public/. - [ ] Выдать права на запись в
storage/. - [ ] Пройти установщик, сохранить сгенерированный пароль администратора.
- [ ] Настроить cron
schedule:run. - [ ] Проверить
/health.json. - [ ] Импортировать жильцов и сверить несколько начислений руками.
- [ ] Сделать первый бэкап и проверить восстановление на копии.
Кому доверить эксплуатацию
Техническая часть несложная, но регулярная: обновления, бэкапы, cron, разбор логов. Это не «поставил и забыл».
Минимальный набор обязанностей на стороне дома: кто-то, кто умеет зайти по SSH, посмотреть health.json, поднять упавший сервис и восстановить базу из бэкапа. Если такого человека нет, лучше брать облачный сервис с поддержкой, а не ставить своё.
Второй вопрос — доступ. Администратор системы видит персональные данные жильцов и историю платежей. Значит, нужны отдельные учётки, а не один пароль на правление, и правило «ушёл из правления — потерял доступ».
Третий — регламент. Кто вносит начисления, кто подтверждает оплату, что делать при спорной сумме. Система фиксирует факты, но не придумывает правила; правила — это решение собственников.
И четвёртый, самый недооценённый: обучение. Человек, который впервые видит панель, склонен искать «кнопку как в Excel». Полчаса объяснения экономят месяц переписки. Заодно стоит договориться о словаре: «начисление», «перерасчёт», «платёж» — разные вещи, и пока их называют одним словом, споры не заканчиваются.
Как выглядит нормальный запуск
Порядок, который экономит нервы.
Сначала — тестовая установка на копии данных. Не на боевой базе, а на выгрузке: половина жильцов, десять начислений. Цель — увидеть, как система ведёт себя на ваших данных, а не на демо.
Потом — сверка. Экспорт из системы против того, что было в таблице. Расхождения — это не ошибка системы, это вопросы к данным: дубликаты, разные написания адресов, пропущенные квартиры.
Затем — перенос целиком и первые настоящие начисления с ручной проверкой. Только после этого — рассылка жильцам.
Завершает запуск бэкап и восстановление на копии. Если восстановление не проверялось, бэкапа нет — это правило работает и здесь. И последнее: запишите, кто что делал на каждом шаге. Через месяц это будет единственным объяснением, почему в базе оказались именно такие цифры.
FAQ
Нужен ли облачный сервис?
Нет. Приложение размещается на своём сервере и работает с собственной базой.
Какую базу выбрать?
Для боевой работы MySQL или PostgreSQL; SQLite удобен для проверки и небольших дворов.
Почему установщик отвечает 500 на PHP 8.5?
Из-за устаревшей опции session.sid_length: предупреждение превращается в исключение. На 8.2–8.4 этого нет.
Обязательно ли расширение zip?
Для работы — нет, для бэкапов и обновлений — да. Проверяется через doctor.
Можно ли связать с реальной панелью домофона?
Да, через REST API и настройки DEVICE_*. Без панели система ведёт только учёт.
Где хранятся секреты?
В локальном конфиге и .env, вне git; пароли устройства и токены можно шифровать через secret:set.
Что было в заметках к релизу и что добавилось здесь
Заметки 2.0.2 — короткие и по делу: одна исправленная ошибка, требования к окружению, контрольные суммы. Для обзора этого мало, поэтому основное содержание собрано из README, кода и прогона.
| Было в заметках | Добавлено в статье |
|---|---|
исправление проверки zip |
разбор, почему это важно при обновлении и бэкапе |
| таблица расширений | порядок проверки окружения и типичные отказы |
| «217 тестов зелёные на PHP 8.5» | фактический прогон на 8.5.4: установщик отдаёт 500 |
| требования к БД | выбор между SQLite, MySQL и PostgreSQL по задаче |
Главное — расхождение про PHP 8.5. В заметках сказано, что тесты на этой версии зелёные; на живом сервере первая же страница не открывается из-за устаревшей опции сессии. Возможно, тесты ставят свой обработчик ошибок и не проходят через установщик, — но для читателя важен итог: на 8.5 приложение сейчас не разворачивается, на 8.2–8.4 разворачивается.
Итог
BAS-IP 2.0.2 — аккуратное приложение для задачи, которую обычно решают таблицей и перепиской: учёт жильцов, начисления с перерасчётом, гостевые пропуска и журнал открытий, всё на своём сервере и без обязательного облака. Прогон подтвердил качество кода (232 файла, ноль ошибок синтаксиса) и честность релиза (контрольная сумма совпала). И он же показал границу: на PHP 8.5 установщик падает из-за устаревшей опции сессии, хотя заметки к релизу обещают зелёные тесты на этой версии. Ставить стоит на 8.2–8.4 и проверять doctor до первого входа.
Цитата: Учёт во дворе ломается не от железа, а от того, что никто не помнит, кто и когда платил.
Связанные материалы
- Инкрементальный бэкап rsync с Unix на Windows — как организовать бэкап базы и файлов.
- RDP Diagnostic Tool 5.0.1: аудит RDP одной командой — самодиагностика как штатная часть продукта.
- MD.Scribe 3.1.0: переименование и починка обновлятора — PHP-приложение с самообновлением и тем же классом ошибок.
- sr-search-replace: замена по дереву с журналом — журнал действий как основа доверия к инструменту.
- Релиз v2.0.2 — заметки и архив с контрольной суммой.
LLM Summary
- Тема: BAS-IP 2.0.2 «Kronos» — саморазмещаемое PHP-приложение для управления шлагбаумом в жилом комплексе.
- Состав: жильцы и помещения с импортом из CSV/JSON/Excel, начисления с перерасчётом, расщепление до копейки, FIFO оплат, гостевые QR-пропуска, журнал открытий, REST API для панели домофона,
/health.json. - Требования: PHP 8.2+ (рекомендуется 8.5), расширения
pdo,mbstring,curl,json,openssl, плюсzipдля бэкапов и обновлений иsodiumдля шифрования секретов; MySQL 8 / MariaDB 10.6+ / PostgreSQL 13+ / SQLite 3. - Проверено 13.11.2026: архив
bas-ip-2.0.2.zip— 1 113 546 байт, SHA-256e6d248f0…22c9f9dсовпал с.sha256; 289 файлов, из них 232 PHP, 12.woff2, 8.js, 5.css;php -lпо всем 232 файлам — 0 ошибок;tests/иtools/в дистрибутив отсутствуют; версия в кодеApp::VERSION = '2.0.2'. - Прогон на PHP 8.5.4:
GET /→ 302 на/install,/install→ 500,/health.json→ 500; в логеerror-2026-11-13.log—ini_set(): session.sid_length INI setting is deprecated(src/BasIp/Core/Session.php:76), предупреждение превращается вErrorException. - Расхождение с релизом: заметки обещают 217 тестов на PHP 8.5 и
/health.json→ 200; на живом 8.5.4 установщик недоступен — вывод: ставить на 8.2–8.4 либо ждать исправления. - Настройка: локальный конфиг →
.env→config/config.php; секреты шифруются черезsecret:set; cronphp bin/bas-ip schedule:run --quietраз в минуту; docroot толькоpublic/. - Не проверялось: работа с реальной панелью домофона, денежные расчёты на своих данных, восстановление бэкапа, обновление с 2.0.1.
- Ссылки: https://github.com/paulmann/BAS-IP, https://github.com/paulmann/BAS-IP/releases/tag/v2.0.2
Промт для агента (установка и настройка)
Готовый промт: скопируйте блок целиком. Источник шагов — README.md репозитория (файла AGENTS.md нет — проверено 13.11.2026) и php bin/bas-ip doctor; сверено с прогоном на PHP 8.5.4.
Задача: развернуть BAS-IP 2.0.2 на сервере и проверить, что учёт жильцов, начисления и health-эндпоинт работают.
Материалы:
- репозиторий: https://github.com/paulmann/BAS-IP
- README: https://github.com/paulmann/BAS-IP/blob/main/README.md
- релиз и архив: https://github.com/paulmann/BAS-IP/releases/tag/v2.0.2
Шаг 1. Скачать bas-ip-2.0.2.zip и сверить SHA-256 с bas-ip-2.0.2.zip.sha256.
Шаг 2. Проверить PHP: версия 8.2–8.4 (на 8.5 установщик отдаёт 500 из-за session.sid_length), расширения pdo, mbstring, curl, json, openssl, zip.
Шаг 3. Распаковать в /srv/bas-ip, направить docroot на public/.
Шаг 4. Выдать права на запись каталогу storage/.
Шаг 5. Создать базу и пользователя, выполнить php bin/bas-ip doctor — добиться зелёного результата.
Шаг 6. Открыть установщик, пройти мастер, сохранить пароль администратора.
Шаг 7. Настроить cron: * * * * * cd /srv/bas-ip && php bin/bas-ip schedule:run --quiet
Шаг 8. Проверить /health.json — ожидается status ok и список загруженных расширений.
Шаг 9. Импортировать жильцов, сверить два-три начисления вручную.
Шаг 10. Сделать бэкап БД и проверить восстановление на копии.
Запрещено:
- открывать docroot на корень проекта: config/ и storage/ уедут наружу;
- хранить секреты в config/config.php: файл под git и перезаписывается обновлением;
- отключать проверку zip: без него нет ни бэкапа, ни обновления;
- считать демо-данные доказательством правильности денежных расчётов;
- разворачивать на PHP 8.5 без проверки установщика;
- запускать обновление без снимка версии.
Что считать успехом: doctor без ошибок, установщик пройден, health.json отдаёт ok, cron работает, начисления сверены вручную, бэкап восстановлен на копии.