Это проверенная версия Оригинального руководства Complication, поясняющего использование Monotone в разработке I2P. Основные инструкции смотри в руководстве по быстрому старту.

В I2P используется распределенная модель разработки. Исходный код реплицируется по независимо администрируемым хранилищам Monotone ("MTN"). Разработчики с правами фиксации могут размещать свои изменения в хранилище (необходимо подписать лицензионное соглашение до того как будут выданы права для фиксации).

Некоторые из замечательных качеств Monotone: распределенный контроль версий, криптографическая аутентификация, контроль доступа, малый размер, малое количество зависимостей, хранение проектов в сжатом файле базы данных SQLite и наличие возможности восстанавливать прерванные попытки синхронизации.

Управление клиентом Monotone

Генерация ключей Monotone

Transport ключ дает вам возможность размещать ваши изменения в хранилище сервера Monotone. Для фиксации кода в Monotone (по сути, для подписания вашего кода), также нужен commit ключ. Ни один из публичных серверов Monotone в I2P на данный момент не требует ключ для чтения (или получения) исходного кода.

Без transport ключа невозможно:

  • получать код от сервера, который не предоставляет доступ для глобального чтения
  • размещать код на любом сервере
  • запускать сервер Monotone

Без commit ключа невозможно:

  • фиксировать любой код

Если вы собираетесь только получать код из MTN, можете спокойно пропустить следующий раздел. Если же вы хотите генерировать ключи, прочтите нижеследующее.

По договоренности ключи именуются как адреса e-mail, но соответствующий e-mail не обязательно должен существовать. Например, ваш ключ может называться:

  • yourname@mail.i2p
  • yourname-transport@mail.i2p

Monotone хранит ключи в $HOME/.monotone/keys в текстовых файлах, которые названы также как ключи. Например:

  • /home/complication/.monotone/keys/complication@mail.i2p

Для генерации transport и commit ключей выполните следующие команды в командной строке:

  • $ mtn genkey yourname-transport@someplace
  • $ mtn genkey yourname@someplace

Monotone запросит у вас пароль для защиты ваших ключей. Вам настоятельно рекомендуется установить пароль для commit ключа. Большинство пользователей оставляют пустым пароль для transport ключа, особенно те, кто запускает сервер Monotone.

Доверие и инициализация вашего хранилища

Модель безопасности Monotone помогает быть уверенным в том, что никто не может запросто выдать себя за разработчика, без того, чтобы он был уведомлен. Т.к. разработчики могут совершать ошибки и быть скомпрометированы, то только ручной пересмотр поможет убедиться в качестве кода. Модель доверия Monotone обязывает вас следить за изменением прав. Что не является заменой чтения изменений.

Хранилище Monotone это один файл (сжатая база данных SQLite), который содержит исходный код всех проектов и историю.

После импорта ключей разработчиков в Monotone и установки ловушек оценки доверия, Monotone предотвратит извлечение ненадежного кода в ваш workspace. Существуют команды, способные очистить ненадежный код из вашего workspace, но на практике они не нужны, благодаря политикам доступа на размещение кода.

В хранилище могут находиться несколько веток. Например, наше хранилище содержит следующие главные ветки:

  • i2p.i2p — Маршрутизатор I2P и связанные с ним программы
  • i2p.www — Веб-сайт проекта I2P
  • i2p.syndie — Syndie и средства распределенных форумов

По соглашению хранилище I2P Monotone названо i2p.mtn. Перед извлечением исходного кода с серверов необходимо инициализировать базу данных для вашего хранилища. Для инициализации вашего локального хранилища перейдите в директорию, в которой вы хотите хранить i2p.mtn файл и директории веток, и выполните следующую команду:

  • $ mtn --db="i2p.mtn" db init

Получение и применение ключей разработчиков

Ключи, которые используют для фиксации кода, необходимы для оценки доверия в Monotone. Другие transport ключи разработчиков нужны только для операторов сервера Monotone.

Commit ключи разработчиков представлены в виде GPG-signed на другой странице.

Для импорта ключей разработчиков после проверки их подлинности скопируйте все ключи в новый файл. Создайте этот файл (например, keys.txt) в той же директории, в которой расположен i2p.mtn. Импортируйте ключи командой:

  • $ mtn --db="i2p.mtn" read < keys.txt

Примечание: Никогда не добавляйте ключи в $HOME/.monotone/keys вручную.

Установка ловушек оценки доверия

Дефолтная политика доверия Monotone слишком слаба для наших требований: каждый коммитер по умолчанию надежен. Это неприемлемо для разработки I2P.

Перейдите в директорию $HOME/.monotone и откройте файл monotonerc в текстовом редакторе. Скопируйте и вставьте следующие две функции в этот файл:

-- This implements a list of trusted signers.
-- It is used on checkout and update.
-- It is not used for repo sync/push/pull.
-- If you do not include this function in ~/.monotone/monotonerc, the
-- default is to trust everybody, which is probably a bad thing
-- in an anonymous network.
-- Update the list below to reflect the signers YOU trust.
--
-- ref: http://www.monotone.ca/docs/Trust-Evaluation-Hooks.html
-- Modified to use key identities instead of key names, since
-- monotone allows duplicate key names, so any key-name-based
-- trust system is insecure.

--
--  Modified from intersection() to use key identities instead of key names, since
--  monotone allows duplicate key names.
--
--  a: table of ID structures (see above)
--  b: table of hex IDs
--
function keyintersection(a,b)
    local s={}
    local t={}
    for k,v in pairs(a) do s[v.id] = 1 end
    for k,v in pairs(b) do if s[v] ~= nil then table.insert(t,v) end end
    return t
end

--
-- from mtn source project.hh and lua_hooks.cc:
-- signers is a table of integers (starting with 1) to the following ID structure:
-- struct ID
-- {
--   id: (key_id in key_identity_info) hex of revision id hash;
--   given_name: (given_name in key_identity_info) // name given when creating the key
--   name: (official_name in key_identity_info) // name returned by hooks or (once implented) policy
-- };
-- id: hex of revision id hash;
-- name: cert_name
-- val: cert_value
--
function get_revision_cert_trust(signers, id, name, val)
   local trusted_signers = {
		"5bc185cfd680eb512fdb9626b9fb4298e136215e",	--  BlubMail@mail.i2p
		"f6706ac205e6b5d7a7e3ea4244ab0ef497f0a099",	--  cervantes@mail.i2p
		"690f278ff6c6157cbaf23b0d602b6d6dcf368313",	--  complication@mail.i2p
		"eb4ac08d5ddbb2bd73889f86c1211424025a6f07",	--  dev@robertfoss.se
		"aae785027c240ebbb0a883fd8ebcf8d6ecee4104",	--  dev@welterde.de
		"86478595288d1b96b58f0c8cd8a8971bc430f8fd",	--  dg2@mail.i2p
		-- completed dev agreement 2013-07 but never checked in anything
		--"5f75b8f0769770edc3267c21ddc9a00ddae31394",	--  digit@mail.i2p
		"4ebaace9973913416af92ee8d0fb93d64753df4c",	--  dream@mail.i2p
		"7e498ae94c9c322404adfc61b16bed388095906b",	--  duck@mail.i2p
		"6c728b0ffed3c2bf7fb0f3c583b30f966d9bacd5",	--  echelon2@mail.i2p
		"0e4e7ebebafbdf4cdacc45a47ba155b1215d8e8b",	--  forget@mail.i2p
		"f332b3d3b11b2efdae220cea75b9d5ba9ec3b52d",	--  hamada@mail.i2p
		"e246444b4fe69ba599e13403c4ab931066de902f",	--  hiddenz@mail.i2p
		"a61146ee69ddb9fcf3b82b19a62b8114b60d367e",	--  HungryHobo@mail.i2p
		"4844b1fd45f5a68744fa28d2f3e3b61a3cf83b95",	--  kytv@mail.i2p
		"6b2acfc9fe2f69b796631a514660fd7bdd237e2d",	--  laziestgravy@mail.i2p
		"c9b970f5e8917eada663d4c6b22096617021c95c",	--  m1xxy@mail.i2p
		"3be64909d6ab7c3d7afe16f20f24e672708b576b",	--  magma@mail.i2p
		"2977a6f4e11819a3f928783175caadc0071fc4de",	--  mathiasdm@mail.i2p
		"de9d196e8057e1629178edbfa1ed754c648d7340",	--  meeh@mail.i2p
		"2a0bba98558d7a9d7e4b1bd807789601252c0024",	--  mkvore-commit@mail.i2p
		"6ade4b7a9a6425194f482ab351950e4230dbbc85",	--  neutron@mail.i2p
		"bc74b49fd8a20513b2745a3d13414b7e9818dd18",	--  Oldaris@mail.i2p
		"3fb8d1ee1e82981a8076ddbcbf4d18f372b8bba7",	--  privateer@mail.i2p
		"e3815f0c985663182534fbd7d6a2bf93204a0bd0",	--  russiansponsor@mail.i2p
		"1092773c40f5813b9179d52a8ab7b499b9554da3",	--  sponge@mail.i2p
		"01265f0c817b24548478341fb75e672720a78b21",	--  str4d@mail.i2p
		"38fe2aa37e1eb9a300a2061ef153265c48031c6b",	--  walking@mail.i2p
		"a0eb78d437efad120dd9edcd776a327ec2c2adde",	--  zab@mail.i2p
		"2158706490e62a17c8140b6e9eabca965b681bc7",	--  zab2@mail.i2p
		"56810cd6434ab33593260e188b32bb83e4e9a139",	--  z3r0fox@mail.i2p
		"896e399990704373125f782ae2ee19b6611ac612"	--  zzz@mail.i2p
   }
   local t = keyintersection(signers, trusted_signers)
   if t == nil then return false end
   if #t>= 1 then return true end
   return false
end

Первая функция определяет пересечение между двумя наборами, в нашем случае это подписанты ревизий и надежные подписанты.

Вторая функция определяет доверие в заданной ревизии, вызывая первую функцию с аргументами "signers" и "trusted". Если пересечение пусто, то ревизия не надежна. Если пересечение не пусто, то ревизия надежна. В другом случае ревизия не надежна.

Более подробную информацию о Trust Evaluation Hooks вы можете найти в официальной документации Monotone.

Получение веток i2p.i2p, i2p.www и i2p.syndie

I2P поставляется с предварительно настроенным туннелем, указывающим на сервер проекта Monotone. Убедитесь, что туннель запущен в I2PTunnel, перед тем как получать исходый код с 127.0.0.1:8998.

Перейдите в директорию, в которой Вы инициализировали i2p.mtn. В зависимости от того, хотите ли Вы получить только исходники I2P, или ещё и исходники веб-сайта I2P и Syndie, Вы можете выполнить операцию pull по-разному.

Если вам нужны только исходники I2P:

  • $ mtn --db="i2p.mtn" -k "" pull "mtn://127.0.0.1:8998?i2p.i2p"

Если вам нужны все ветки:

  • $ mtn --db="i2p.mtn" -k "" pull "mtn://127.0.0.1:8998?i2p.*"
Если передача прервалась до успешного завершения, просто повторите команду получения, и передача возобновится.

Получение в примерах выше совершается анонимно, т.к. был указан пустой transport ключ. Если все будут выполнять получение анонимно, то атакующему будет сложнее получить контроль над сервером, избирательно снабжая некоторых людей поддельными данными.

Проверка работоспособности оценки доверия

Чтобы убедиться, что оценка доверия работает:

  • Сделайте резервную копию вашего файла monotonerc.
  • Измените monotonerc, определив переменную trusted_signers следующим образом:
           local trusted_signers = {}
      
  • С измененным т.о. monotonerc Monotone не будет больше доверять никаким коммитерам. Убедитесь в этом, изменив директорию на ту, в которой был создан i2p.mtn, и попробуйте извлечь ветку I2P:
    • $ mtn --db="i2p.mtn" co --branch="i2p.i2p"

    Директория с именем i2p.i2p не должна появиться. Вы должны увидеть много сообщений об ошибках, вроде таких:

        mtn: warning: trust function disliked 1 signers
        of branch cert on revision 523c15f6f50cad3bb002f830111fc189732f693b
        mtn: warning: trust function disliked 1 signers
        of branch cert on revision 8ac13edc2919dbd5bb596ed9f203aa780bf23ff0
        mtn: warning: trust function disliked 1 signers
        of branch cert on revision 8c4dd8ad4053baabb102a01cd3f91278142a2cd1
        mtn: misuse: branch 'i2p.i2p' is empty
      

    Если вы удовлетворены результатом, восстановите резервную копию monotonerc, которая была создана ранее. Если вы не создали резервную копию, как предлагалось, перечитайте Установку ловушек оценки доверия.

    Извлечение рабочей копии последней версии

    Если вы уже извлекли ветку, пропустите следующий раздел.

    Перейдите в директорию, в которой находится i2p.mtn. И выполните в ней:

    • $ mtn --db="i2p.mtn" co --branch="i2p.i2p"

    Извлечение должно быть выполнено без сообщений об ошибках и директория с именем i2p.i2p должна появиться в текущей директории. Поздравляем! Вы успешно извлекли последние исходники I2P, готовые к компиляции.

    Обновление вашей рабочей копии до последней версии

    Если Вы ещё этого не сделали - загрузите самую последнюю версию кода с сервера в свой локальный Monotone-репозиторий. Чтобы сделать это, перейдите в директорию с i2p.mtn и выполните:

    • $ mtn --db="i2p.mtn" -k "" pull "mtn://127.0.0.1:8998?i2p.i2p"

    Теперь перейдите в вашу i2p.i2p директорию, и выполните в ней:

    • $ mtn update

    Т.к. ошибок нет…Поздравляем! Вы успешно обновились до последних исходников I2P. Они готовы для компиляции.

    Управление сервером Monotone

    Получение и применение transport ключей разработчиков

    Как оператор сервера вы можете захотеть наделить некоторых разработчиков правом размещения.

    Назначение прав доступа push и pull

    По умолчанию сервер Monotone запрещает любой доступ.

    Чтобы дать право извлечения всем клиентам, установите следующее в $HOME/.monotone/read-permissions:

        pattern "*"
        allow "*"
    

    Никто без явного наделения правами не сможет размещать код на вашем сервере. Чтобы разрешить доступ на размещение:

    • Добавьте имена transport ключей пользователей в $HOME/.monotone/write-permissions, как это сделано для
          zzz-transport@mail.i2p
          complication-transport@mail.i2p
      
      с одним ключом на строке.
    • Импортируйте transport ключ(и) в вашу базу данных. Процедура для импорта transport ключей подобна импорту commit ключей, которая описана в разделе Получение и применение ключей разработчиков.

    Запуск Monotone в режиме сервера

    Для вашего сервера Monotone должна использоваться отдельная база данных, потому что Monotone блокирует базу данных пока она служит другим. Сделайте копию вашей разработческой базы данных, затем запустите сервер:

    • $ mtn serve --bind="127.0.0.1:8998" --db="i2p.mtn" --key "myserver-transport@mail.i2p"
    Если ваш ключ защищен паролем, Monotone запросит этот пароль когда подключится первый клиент. Вы можете обойти это, собственноручно выполнив первое подключения клиента к вашему серверу (или очистив пароль к вашему transport ключу).

    Чтобы ваш сервер был доступен другим в сети I2P, для этого вам нужно создать серверный туннель. Используйте "Standard" тип туннеля и "Bulk" профиль.

    Различия под Debian GNU/Linux

    В Debian (наряду с другими поставками) есть интегрированный в фреймворк демонов/сервисов Monotone. Также сервера Monotone можно запустить "обычным способом" на системах Debian, запуск в стиле "Debian" может быть более простым.

    Разрешения выдаются редактированием файлов /etc/monotone/read-permissions и /etc/monotone/write-permissions. Вам также нужно отредактировать /etc/default/monotone чтобы включить запуск monotone при загрузке или изменить хост, порт, или расположение базы данных.