git-ssb — децентрализованный хостинг git-репозиториев
SSB (Secure Scuttlebutt) — это децентрализованная социальная сеть и протокол, на основе которого она работает. git-ssb заворачивает обычные git-репозитории в этот протокол. SSB хочет заменить собой Facebook, а git-ssb — GitHub. Под катом — краткое руководство по git-ssb. Актуально для тех, кому дискомфортна сама идея использования централизованных сервисов в качестве посредника. Своеобразная красная таблетка с полагающимися в этом случае неожиданными последствиями.
Secure Scuttlebutt
Протокол SSB описывает правила синхронизации ваших данных между заинтересованными в них узлами сети. Ваши данные — это история ваших действий в сети, связный список json-объектов. Связь задаётся hash-суммой предыдущего объекта (как в блокчейне). Таким образом, однажды опубликованные объекты неизменяемы и неудаляемы. Добавлять можно только в конец списка. Типичный use case предполагает, что каждый объект в списке — это пост или комментарий в блоге. Картинки и другие тяжёлые объекты хранятся вне списка в виде blob-ов и реплицируются отдельно. Объекты в списке могут на них ссылаться.
Большинство пользователей сети ведут блоги в приложениях Patchwork и Manyverse. Приложений для ведения блогов около десятка, они, в основном, совместимы друг с другом и отличаются интерфейсом. Кроме этого есть шахматы, чат, менеджер пакетов (ssb-npm) и git (git-ssb). Некоторые разработчики SSB используют git-ssb как основной сервис для управления версиями исходников. Мы тоже попробуем.
Установите ssb-server и git-ssb
ssb-server нужен для синхронизации с другими узлами в p2p сети. Он должен быть запущен, когда вы делаете push, pull, fetch, создаёте pull-request или форкаете репозиторий.
Пакет git-ssb включает:
программу для управления репозиториями (git-ssb)
git-remote-helper, который понимает адреса, начинающиеся с ssb://
web-интерфейс, отдалённо напоминающий GitHub
Все три компонента взаимодействуют с запущенным на вашей машине ssb-server.
$ sudo apt install git nodejs npm
$ npm install ssb-server git-ssb
ssb-server и git-ssb установятся в папку $HOME/node_modules
. Чтобы было удобнее их вызывать, добавьте в конец файла ~/.profile
стоки:
if [ -d "$HOME/node_modules/.bin/" ] ; then
PATH="$HOME/node_modules/.bin/:$PATH"
fi
Чтобы переменная $PATH
обновилась в текущей сессии, наберите
$ source ~/.profile
При логине файл ~/.profile
должен исполниться автоматически. Некоторые среды рабочего стола (например, Xfce) этого не делают. Если после перезагрузки переменная $PATH
не обновилась, то добавьте в .xsessionrc
явный вызов ~/.profile
:
. ~/.profile
Запустите ssb-server и оставьте его работающим на время экспериментов.
$ ssb-server start
При первом запуске он создаст identity по умолчанию в папке ~/.ssb
.
Получите инвайт и примите его
Инвайт нужен для того, чтобы другие узлы сети узнали о вашем существовании. Узел, который выдаст вам инвайт, подпишется на вас и будет реплицировать ваши данные. Через него это смогут сделать и другие пользователи. Без инвайта можно, но сложнее.
У каждого узла могут быть свои правила выдачи инвайта. На данный момент большинство узлов ничего не спрашивают и просто дают строку, которую нужно скопировать. Список выдающих инвайты узлов. Примите инвайт, подставив полученную строку в следующую команду.
$ ssb-server invite.accept <ваш-инвайт-код>
Теперь вы с тем узлом взаимные друзья: вы начинаете копировать себе данные его и его друзей, а он — ваши.
Подпишитесь на @cel
@cel — это разработчик git-ssb.
$ ssb-server publish --type contact --contact "@f/6sQ6d2CMxRUhLpspgGIulDxDCwYD7DzFzPNr7u5AU=.ed25519" --following
Сейчас в папку ~/.ssb
скачается около 1Gb данных — это его история (там и его git-репозитории) и истории тех пользователей, на которых он подписан. Эта подписка нужна, чтобы последующие примеры у всех работали примерно одинаково.
Установка и настройка завершены. Теперь вы многое можете:
Запустить web-интерфейс
$ git-ssb-web
Перейдя по напечатанной в консоли ссылке вы увидите хронологический список коммитов, issue и других действий в видимых репозиториях. Это, разумеется, не всё, а только то, что скачалось после подписки на предыдущем шаге. Нажав на имя пользователя вы увидите его activity log, нажав на репозиторий — интерфейс, похожий на GitHub.
Репозиторий git-ssb в git-ssbВсе ваши действия в web-интерфейсе (например, комментарий, создание issue или форка) запишутся в вашу историю и уйдут вашим подписчикам при синхронизации. Если вы в данный момент отключены от сети, то этот интерфейс будет продолжать работать: репозитории будут форкаться, issue создаваться и т.д. ssb-server работает (вы же его ещё не выключили) и отправит все ваши изменения как только сеть появится.
Создать репозиторий
$ mkdir my-new-repo
$ cd my-new-repo
$ git init
Initialized empty Git repository in /tmp/my-new-repo/.git/
$ git-ssb create ssb my-new-repo
Created repo: ssb://.sha256 (my-new-repo)
Added remote: ssb
$ git remote -v
ssb ssb://.sha256 (fetch)
ssb ssb://.sha256 (push)
К привычному git init
добавилась команда git-ssb create ssb my-new-repo
, которая запишет в вашу историю факт создания нового репозитория с именем my-new-repo
и добавит его URL в качестве remote с именем ssb
. Аналогичным образом можно добавить такой remote к любому существующему репозиторию.
Запушить существующий репозиторий
Вы добавили ssb ссылку в качестве дополнительного remote к вашему репозиторию. Теперь можно пушить.
Важно: невозможно удалить что-то из SSB. Не ставьте эксперименты на чувствительных данных.
$ git push ssb master
Если репозиторий большой, то может не получиться. В git-ssb допустимый размер pack-файла зависит от максимального размера blob, а он ограничен 5Mb. Больший размер сеть не примет. Но закоммитить, тем не менее, возможно:
$ git push ssb master -o allow-big
Это не сделает вашу историю невалидной (blob синхронизируются отдельно от истории), но скачать большой pack-файл другие пользователи не смогут, пока не увеличат у себя в настройках максимальный размер blob.
Альтернативный способ вписаться в ограничение на размер pack-файла — это пушить небольшими порциями так, чтобы создаваемые git-ом pack-файлы не превышали 5Mb.
Клонировать репозиторий
Будем ставить эксперименты с git-ssb на репозитории git-ssb. В SSB нет DNS и красивых названий чего бы то ни было. Ссылку на репозиторий ssb://%n92DiQh7ietE+R+X/I403LQoyf2DtR3WQfCkDKlheQU=.sha256
я скопировал из web-интерфейса.
$ git clone ssb://%n92DiQh7ietE+R+X/I403LQoyf2DtR3WQfCkDKlheQU=.sha256 git-ssb
$ cd git-ssb
$ git remote -v
origin ssb://%n92DiQh7ietE+R+X/I403LQoyf2DtR3WQfCkDKlheQU=.sha256 (fetch)
origin ssb://%n92DiQh7ietE+R+X/I403LQoyf2DtR3WQfCkDKlheQU=.sha256 (push)
В этом репозитории у нас единственный remote, и он из SSB.
Форкнуть репозиторий
$ git-ssb fork my-fork
Created repo: ssb://.sha256 (git-ssb)
Added remote: my-fork
$ git remote -v
my-fork ssb://.sha256 (fetch)
my-fork ssb://.sha256 (push)
origin ssb://%n92DiQh7ietE+R+X/I403LQoyf2DtR3WQfCkDKlheQU=.sha256 (fetch)
origin ssb://%n92DiQh7ietE+R+X/I403LQoyf2DtR3WQfCkDKlheQU=.sha256 (push)
В вашей истории появится запись о создании нового репозитория, а в текущей папке добавится новый remote.
Сделать пулл-реквест
Вы внесли изменения и сделали коммит.
$ git-ssb pull-request
Откроется текстовый редактор, вы напишете описание ваших изменений. После сохранения распечатается новый объект, добавленный в вашу историю.
Пушить в чужой репозиторий
Это не баг, а фича. Согласно документации (git-ssb-intro), это одна из принятых моделей совместной работы. Вы создаёте в чужом репозитории ветку с именем @ваш-юзернейм/master
(git checkout -b @ваш-юзернейм/master
), пушите в неё (git push ssb
), а после делаете пулл-реквест (git ssb pull-request
). Но ничто не помешает вам запушить прямо в master без всяких пулл-реквестов.
Возможность асинхронного внесения изменений в одну ветку может привести к конфликту, если при помощи двух разных identity (про identity — см. ниже) были созданы два конкурирующих коммита. Когда git-ssb встречает такие ситуации, он просит пользователя сделать слияние этих альтернативных версий. Всё это происходит локально на вашем компьютере. Если вы не подписаны на ту другую identity, которая пушит в ваш репозиторий, то вы не увидите никакого конфликта. Другие же пользователи, которые на неё подписаны, увидят. Таким образом, один и тот же репозиторий будет выглядеть по-разному в зависимости от того, чьи обновления вы получаете.
Identity задаётся закрытым ключом в файле ~/.$ssb_appname/secret
. Если переменная ssb_appname
не задана, то будет использована identity по умолчанию (~/.ssb
). Если в указанном месте нет файла secret
, то ssb-server его создаст со случайным ключом.
Положительная сторона этой вседозволенности permissionless модели в том, что вы можете работать с одним репозиторием с нескольких устройств, на которых установлены разные identity.
С другой стороны, это может привести к распространению вредоносного кода: вы делаете что-то полезное, все об этом знают, клонируют и делают sudo make install
не глядя в историю коммитов. У одних пользователей установится ваше приложение, а у других — ваше приложение с добавлением зловреда. Возможно, что даже вы сами не увидите, что после очередного git pull
у вас появились чужие коммиты. Тогда зловред придёт к каждому, в том числе и к вам.
Обсуждение этой возможности внутри SSB.
Что ещё почитать?
git-ssb-intro: a guide to hacking together on the distributed web
Другие способы децентрализации git:
GitTorrent (на основе BitTorrent)
HyperGit (на основе Dat)
igis-remote (на основе IPFS)
ipld-remote (на основе IPFS)
GitCenter (на основе ZeroNet)
Mango (Ethereum + IPFS)
Radicle
Gitopia
Первые четыре подробно проанализированы в статье Daniel Aleksandersen «Four P2P distribution tools for Git repositories compared». К ней есть комментарии разработчиков SSB.
Спасибо за внимание. Надеюсь, что было не очень скучно. Хорошей децентрализации тем, кому это важно.
Картинка в шапке сгенерирована при помощи сервиса myoctocat.com.