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Репозиторий 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.

© Habrahabr.ru