UNRUIN
документация · v1.0

Компаньон

Компаньон на компьютере (Linux)

Программа в трее, которая держит копию на вашей машине и говорит, чья вина, если копия отстала.

Компаньон — небольшая программа в трее, у которой одна задача, умещающаяся в предложение: «моя копия на моём компьютере, и я узнаю первым».

Это намеренно не вторая панель. Он показывает задания, чьи копии лежат на этой машине, насколько каждая отстала и по чьей вине, и умеет стянуть, развернуть и запустить заново. Ни обзора парка, ни истории запусков, ни правил хранения, ни секретов, ни удаления заданий: всё это принадлежит панели, а продублировать его здесь значило бы завести два места, куда смотреть, и два места, где можно ошибиться. Добавить сервер, хранилище и задание он всё-таки умеет — но только в Настройках, как упрощённый аварийный путь.

Это отдельный модуль Go: его зависимости от GUI и CGO не попадают в сборку сервера.

Интерфейс русский и говорит на том же языке, что панель: vocab.go держит его половину словаря, а docs/UX-BRIEF.md §4-5 — общий контракт обеих поверхностей. Подписи ниже приведены так, как их видит человек.

Сборка

Нужны Go, компилятор C и обычные библиотеки для настольных приложений Fyne.

sh
sudo apt-get install -y gcc pkg-config libgl1-mesa-dev xorg-dev
sh
cd desktop && go build -o unruin-desktop . && ./unruin-desktop

Установка

sh
go install fyne.io/tools/cmd/fyne@latest   # один раз; нужен $(go env GOPATH)/bin в PATH
./desktop/package.sh
tar -xJf desktop/Unruin.tar.xz && cd unruin-desktop && make user-install

Это кладёт бинарник в ~/.local/bin, пункт меню в ~/.local/share/applications и значок в тему hicolor. make user-uninstall убирает всё три обратно; sudo make install и sudo make uninstall делают то же самое на всю систему.

package.sh — тонкая обёртка вокруг fyne package, и существует она потому, что пакет, который тот инструмент собирает, не устанавливается как есть:

  • его Makefile ставит значок без .png, и make install падает на третьей строке с cannot stat — так у любого линуксового пакета этого инструмента;
  • пользовательская установка кладёт значок прямо в ~/.local/share/icons/, куда спецификация тем не смотрит, и пункт меню выходит пустым;
  • в ярлыке нет ни описания, ни категории, а ключевое слово — Keywords=fyne;, поэтому программа не попадает ни в один раздел меню и не находится поиском по слову «копии».

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

Значки рисует mkicons.py (нужен Pillow) из палитры панели, чтобы трей и веб не разъехались в понимании того, что значит зелёный. Значок в трее несёт состояние так же, как точки статуса в панели: круг — все копии здесь свежие, янтарный ромб — что-то отстало, серое кольцо — связи с сервером нет, значит свежесть неизвестна. icons_test.go закрепляет и цвета, и разницу между кругом и ромбом: всегда зелёный значок был бы единственным, что постоянно на экране, и единственным, что постоянно врёт.

Окно

Сначала Подключиться: адрес сервера (например, https://hstl.example.com), имя и пароль — те же, что у панели. Если сервер пускает только по ключу, положите ключ в Токен доступа, а пароль оставьте пустым.

Дальше один экран, сверху вниз:

  • Фраза-вердикт — «3 копии здесь, 1 отстала». Предложение, а не счётчики: это единственное, что обязано прочитаться за пять секунд.
  • Строка сервера — с какого сервера эти копии и сколько у него всего заданий. Когда сервер пропадает, она так и говорит, вместо того чтобы нарисовать пустой и на вид здоровый список.
  • Две вкладки. Мои копии — только то, что уже лежит на этой машине (или что вы просили здесь держать). Все задания сервера — весь парк, чтобы добавить в свои копии что-то новое.
  • Подвал — держит ли программа копии свежими сама, куда они ложатся и сколько осталось места. Последняя цифра и позволяет строке сказать «180,0 ГиБ — не поместится, свободно 42,1 ГиБ» до скачивания, а не после.

Строка утверждает два факта, а не один

Это центральная мысль всего замысла. «Копия отстаёт на 3 дня» само по себе обвиняет компаньона в том, что он не делает свою работу. Вторая строка говорит, чья это вина:

моя копия почему действие
копия актуальна стянуто сегодня 09:12 · 1,4 ГиБ Открыть папку
копия отстаёт на 3 дня на сервере тоже сбой — новее нет Открыть папку
копия отстаёт на 3 дня на сервере свежее, сегодня 03:04 Стянуть
копии здесь нет на сервере свежая, 2 часа назад Стянуть
копии здесь нет на сервере копии ещё нет Запустить сейчас
тяну сейчас · 640,0 МиБ из 1,1 ГиБ (куда) Прервать

Ровно одно действие на строку. Статус несёт ещё и форму — ● здесь и свежо, ◆ отстаёт, ○ копии нет, ◐ тяну, — чтобы состояние пережило скриншот, распечатку и человека с дальтонизмом. То же правило, что и в панели.

Щелчок по названию задания открывает настройки его хранения.

Способы хранить (щёлкнуть по названию задания)

Значения в конфигурации не менялись (plain / restic / host-tree); продуктовый язык только у подписей, и каждая показывает путь, который действительно получится.

  • «Просто файлы в папку» (plain) — одна версия, перезаписывается при каждом скачивании, открывается в файловом менеджере. Ставить ничего не надо.
  • «Зашифрованное хранилище с историей» (restic) — настоящее локальное хранилище restic: качаются только изменения, каждая прошлая версия сохраняется, любую можно вернуть через Восстановить из копии. Нужен restic на этой машине — единственное место, где движок назван по имени, потому что пакет, который надо поставить, обязан называться своим именем. Диалог предлагает Как поставить, а не упирается в тупик. Ключ хранилища генерируется и лежит в настройках программы.
  • «Как на сервере, с датами» (host-tree) — точная раскладка файлов исходного хоста, на каждое скачивание новая папка с датой, ничего не перезаписывается. Удобно смотреть глазами «было / стало». Локальный restic не нужен.

В каждой стянутой и восстановленной копии лежит ещё и сгенерированный restore.sh, который автоматизирует возврат данных на место (остановить контейнер и залить том через rsync, psql < дамп и так далее); значения для подстановки собраны у него наверху.

Сторож в фоне

  • На поддерживаемом рабочем столе программа живёт в трее: закрытие окна прячет её туда, и она продолжает смотреть. Меню трея повторяет вердикт, называет то, что отстало, и предлагает Стянуть всё сейчас и Пауза на час.
  • Держать копию свежей самому (у каждого задания) — перекачивать заново, когда на сервере появляется что-то новее. Диалог выбора папки не нужен: копии по умолчанию ложатся в ~/backups/unruin/<задание>, поменять можно в Настройках.
  • Пропущенное скачивание никогда не молчит. Если автоскачивание отказалось — нет restic, не хватает места, соединение лимитное, а «Тянуть и по мобильному интернету» выключено, — оно скажет об этом уведомлением. Копия, которую тихо не взяли, пока интерфейс уверяет, что всё свежо, была бы худшей ошибкой этого продукта. Каждая причина объявляется один раз на задание и забывается после удачного скачивания.
  • Уведомления связывают состояние сервера с вашей копией — «billing-db не забэкапился / db-02 не ответил. На этом компьютере лежит копия от 3 августа». Этого предложения панель сказать не может, и ради него программа и существует.
  • При запуске она молчит про сбои, случившиеся до неё: объявляются только переходы, которые произошли при ней. Иначе каждое утро начиналось бы со вчерашних трёх тревог.

Восстановить из копии на этой машине

Восстановить из копии спрашивает задание, затем версию из локального хранилища (с датой и размером, свежие сверху), затем папку назначения. Версии есть только у способа с историей; для двух других копия — это просто папка, и ответ на вопрос даёт Открыть папку в строке. Восстановление всегда идёт в новую папку: компаньон никогда ничего не перезаписывает на вашей машине и не подменяет за вас рабочий каталог.

Подключение, базовая папка, способы хранения по заданиям, автоскачивание и флаг лимитного соединения лежат в ~/.config/unruin-desktop/config.json.

Заметки

  • Скачивание идёт только по авторизованному соединению программы. Поставьте сервер за TLS, чтобы этот трафик был зашифрован в пути.
  • Отметка на стороне сервера — это только отметка (время и машина); сами файлы лежат только на вашем компьютере. Разворачивайте их локально как любые файлы или направьте на них обычное восстановление.
  • Лимитность соединения выясняется у NetworkManager (nmcli). Если понять не удалось, считается, что соединение не лимитное, — лучше так, чем отказываться работать на машине без NetworkManager.

Бесплатно, целиком ваше, наружу ничего не уходит. Сайт статический: ни аналитики, ни куки, ни внешних запросов.