# simple-updater Лёгкий self-hosted обновлятор для игры/приложения: HTTP-сервер, который раздаёт файлы клиентам, и Windows-обновлятор (`updater.py` → `updater.exe`), который сравнивает локальные файлы с манифестом на сервере и докачивает то, что изменилось. ## Возможности - **Раздача нескольких версий клиента** с одного сервера (например `Main` и `Test`) через отдельные access-ключи в URL. - **Подпись манифестов (Ed25519)** — сервер не может незаметно подменить список файлов или их хэши; обновлятор проверяет подпись публичным ключом перед тем, как довериться манифесту. - **Сжатие файлов** — при генерации манифеста каждый файл сжимается gzip'ом; если сжатая копия меньше оригинала, обновлятор скачивает её и разжимает локально. - **Self-update** — сам `updater.exe` умеет проверять и устанавливать собственные новые версии, без отдельной ручной раздачи. - **Единый `config.json`** — все настройки (сервер, клиенты, ключи, вид окна, лимиты) в одном файле. - **`quickstart.py`** — генерирует ключи, манифесты и (по флагу) собирает exe одной командой. ## Быстрый старт ```bash pip install -r requirements.txt # сгенерировать ключи + положить файлы игры в game_client/ + собрать манифесты python quickstart.py # то же самое, но и собрать updater.exe python quickstart.py --build-exe ``` Первый запуск создаст пустые папки клиентов (`game_client`, `game_client_test` — имена берутся из `config.json`'s `clients`), сгенерирует access-ключи и пару ключей для подписи манифестов. Положите файлы игры в `game_client/`, запустите `quickstart.py` ещё раз — манифест сгенерируется и подпишется автоматически. Запустить сервер: ```bash python server.py ``` ## config.json Все настройки проекта живут здесь, вложенными секциями: | Секция | Что настраивает | |---|---| | `server` | host, port, лимит соединений на IP | | `clients` | имя клиента → папка с файлами (`"Main": "game_client"`) | | `access_keys` | имя клиента → access-ключ (генерируется автоматически) | | `default_client` | какой клиент выбран в обновляторе по умолчанию | | `signing_keys` | публичный ключ подписи + имя файла с приватным ключом | | `require_signature` | обязательна ли подпись манифеста (по умолчанию да) | | `connection` | адрес и порт сервера, HTTPS вкл/выкл — то, к чему подключается обновлятор | | `updater_ui` | название игры, размеры окна и баннера | | `paths` | путь к exe игры, баннеру, иконке, файлу настроек | | `manifest` | имя файла манифеста, настройки сжатия, лимит размера файла | | `ignore` | какие файлы/папки/расширения не попадают в манифест | | `self_update` | включён ли self-update, текущая версия обновлятора | Чтобы что-то поменять — правьте `config.json` и перезапускайте `quickstart.py` (или `server.py` для настроек сервера). Ручное редактирование `updater.py`/`generate_manifest.py` не нужно — все они читают значения оттуда. ### Приватный ключ подписи Единственный настоящий секрет в проекте — приватный ключ подписи манифестов. Он **не хранится в `config.json`**, а лежит в отдельном файле `SIGNING_PRIVATE_KEY.txt` (имя настраивается через `signing_keys.private_key_file`). Публичный ключ — в `config.json`, его можно раскрывать сколько угодно, зашивать в exe и т.д. Держите `SIGNING_PRIVATE_KEY.txt` только на машине, где генерируются манифесты — не копируйте его вместе с остальным проектом, добавьте в `.gitignore`, если используете git. ## Как всё это работает вместе ``` config.json ──┬──> generate_key.py ────────> access-ключи в config.json │ приватный ключ в SIGNING_PRIVATE_KEY.txt │ публичный ключ в config.json │ ├──> generate_manifest.py ───> game_client/manifest.json + .sig │ ├──> generate_updater_manifest.py ──> game_client/updater_manifest.json + .sig │ └──> quickstart.py ──> запускает все шаги выше по порядку, патчит updater.py и собирает updater.exe server.py ──> раздаёт содержимое клиентских папок по HTTP(S) под access-ключом в URL updater.py / updater.exe ──> скачивает манифест, проверяет подпись, докачивает изменившиеся файлы, запускает игру ``` ## Ручной запуск отдельных шагов Если `quickstart.py` не подходит (например, генерация ключей и манифестов происходит на разных машинах), каждый скрипт можно запускать по отдельности: ```bash # access-ключ для клиента, сохранить в config.json python generate_key.py --client Main --save # пара ключей для подписи манифестов python generate_key.py --signing-keypair --save # сгенерировать и подписать манифест для одной клиентской папки python generate_manifest.py game_client # опубликовать новую версию updater.exe для self-update python generate_updater_manifest.py dist/updater.exe game_client --version 2 # запустить сервер python server.py ``` ## Требования ``` pip install -r requirements.txt ``` `cryptography` — подпись/проверка манифестов (Ed25519), нужен и при генерации манифестов, и при сборке `updater.exe`. `Pillow` — опционален, используется `updater.py` для качественного масштабирования баннера; без него баннер всё равно отрисуется, просто грубее. Для сборки `updater.exe` также нужен `pyinstaller` (`pip install pyinstaller`), если запускаете `quickstart.py --build-exe`.