Публикуем сайт в межпланетной файловой системе IPFS

    В этой статье я расскажу как в ней запустить статичный сайт который будет доступен и напрямую и по IPNS. У сайта будет нормальное доменное имя благодаря использованию DNS. Доменное имя можно использовать для доступа к сайту напрямую, через глобальный и локальный шлюз.


    Условия:


    1. На нашем сервере установлен IPFS
    2. У нас есть домен и доступно редактирование DNS записей

    Напомню: InterPlanetary File System — это новая децентрализованная сеть обмена файлами (HTTP-сервер, Content Delivery Network). О ней я начал рассказ в статье "Межпланетная файловая система IPFS".

    image


    Имя домена может содержать только один тире подряд из за этой строки:


    const DomainRegexpStr = "^([a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,}$"

    Она проверяет правильность имени домена. Ограничения на домен будут работать пока не примут Pull request "Use more comprehensive hostname regex pattern Fix".



    Один сайт


    1. В каталоге сайта должен быть минимальный набор:


      1. Индексный файл "index.html" (если его не будет то IPFS покажет содержимое каталога)
      2. Инструкция для поисковых систем "robots.txt" (я про него вспомнил когда роботы пришли на разведку и я увидел ошибки в консоли IPFS)
      3. Иконка сайта "favicon.ico" (его браузеры автоматом запрашивают если другой не задан)

    2. В настройках меняем строку


      "Gateway": "/ip6/127.0.0.1/tcp/8080",
      
      на
      
      "Gateway": "/ip6/0.0.0.0/tcp/80",

      Редактирование настроек доступно в веб интерфейсе http://127.0.0.1:5001/webui#config(он будет доступен после запуска клиента командой ipfs daemon) либо в файле ~/.ipfs/config


      После редактирования настроек клиент необходимо перезапустить.


      Так мы откроем доступ к шлюзу из интернета.


    3. Запускаем клиент.


      >ipfs daemon

      Смотрим: Запуск IPFS под Windows


    4. Публикуем каталог с содержимым сайта


      ipfs add -r [путь до каталога]
      
      >ipfs add -r ..\ivan386.github.io
       18.17 KB / ? [-------------------------------------=------------------------------
      added QmP2FJJXBjeVqm5DgJ4Q4ZjC5G9A3e74FRTFMV43kHP5p8 ivan386.github.io/favicon.ico
      ...
       80.25 KB / ? [--------------------------------------------------------------------
      added QmXzx3rvzdRhLXPtzayG7abQzpyeH3JsyXWNt8CFqKy3Yv ivan386.github.io/index.html
      ...
      added QmUsr9A8ggX79UKfQRTRCFX6FU9HrrWstHNyED5ygqgShA ivan386.github.io

      Последним будет нужный нам мультихеш корневого каталога


    5. Привязываем мультихеш каталога к ID


      ipfs name publish [мультихеш каталога]
      
      >ipfs name publish QmNjE3iwCqY7729972CHRdFp3bGPosWoFHJ9YsTzea5icT
      Published to QmVBRmftY9ytHZ1z39b65gtEMY8Tq4Ri8AtmQeqULXPnm5: QmNjE3iwCqY7729972CHRdFp3bGPosWoFHJ9YsTzea5icT

      Здесь в ответе первым идёт ID


    6. Заходим в панель управления DNS добавляем запись TXT


      @ TXT dnslink=/ipns/<наш id>
      
      @ TXT dnslink=/ipns/QmVBRmftY9ytHZ1z39b65gtEMY8Tq4Ri8AtmQeqULXPnm5


    Через некоторое время (когда произойдёт обновление DNS) контент станет доступен по адресу сайта и на шлюзе по адресу <адрес шлюза>/ipns/<имя домена>


    Публикацию через ID нужно использовать когда сайт часто обновляется. IPFS клиент через который публикуется контент должен быть постоянно включен или выключаться на небольшие промежутки времени. За день offline у меня клиент забыл привязку id -> мультихеш. Видимо привязка храниться только в DHT.


    Если данные условия не подходят можно использовать мультихеш.


    Так мы опубликовали один сайт.


    Проверка


    Проверить правильную работу домена можно командой:


        ipfs name resolve -r <имя домена>
    
        >ipfs name resolve -r ipfs.io
        /ipfs/QmaYRrBpZQRjonxBpBBSLvYmy893ySPpXpHCakhomaQtkU

    Несколько сайтов


    Бывает что нужно опубликовать несколько разных сайтов.


    Для этого:


    1. Складываем каталоги сайтов в один, публикуем и привязываем корневой каталог сайтов к ID.
    2. Добавляем в DNS TXT запись каждого каталога dnslink.


      @ TXT dnslink=/ipns/<наш id>/<имя каталога сайта>
      
      @ TXT dnslink=/ipns/QmVBRmftY9ytHZ1z39b65gtEMY8Tq4Ri8AtmQeqULXPnm5/magnet-converter


    Альтернативные способы


    1. Можно ссылаться на другой домен у которого задан dnslink.


      @ TXT dnslink=/ipns/<имя другого домена>[/<путь к файлу или каталогу>]
      
      @ TXT dnslink=/ipns/ipfs.io

    2. В dnslink можно аналогично указать мультихеш на каталог или файл.


      @ TXT dnslink=/ipfs/<мультихеш>[/<путь к файлу или каталогу>]

      1. на каталог


        @ TXT dnslink=/ipfs/Qmce1EkrLpAV4gPxE75c68PhDWFCmEsedWkYVNNVU6Ut1S
        или
        @ TXT dnslink=/ipfs/QmUsr9A8ggX79UKfQRTRCFX6FU9HrrWstHNyED5ygqgShA/magnet-converter

      2. на файл


        @ TXT dnslink=/ipfs/QmXzx3rvzdRhLXPtzayG7abQzpyeH3JsyXWNt8CFqKy3Yv
        или
        @ TXT dnslink=/ipfs/Qmce1EkrLpAV4gPxE75c68PhDWFCmEsedWkYVNNVU6Ut1S/index.html


      Это будут перманентные ссылки. Этот способ подойдёт для публикации редко изменяющегося содержимого. В данном случае сразу доступен мультихеш содержимого и оно сразу будет доступно если есть его копия в IPFS сети.


      Соответственно в данном способе публикации при обновлении содержимого сайта нужно обновлять и DNS запись.



    Локальный шлюз


    Для того чтобы пользователи автоматически подключались к сайту через локальный шлюз я предлагаю добавить A DNS запись.


        this-is-ipfs-site-use-local-gate A 127.0.0.1

    Это позволит пользователю подключить простой proxy.pac который загрузит сайт через локальный шлюз.


    function FindProxyForURL(url, host) {
        if ( shExpMatch(url, "http:*") && dnsResolve("this-is-ipfs-site-use-local-gate."+host) == "127.0.0.1" ){
            return "PROXY 127.0.0.1:8080; DIRECT"
        }
        return "DIRECT"
    }

    Альтернативный вариант: Переключаем свой сайт на localhost (локальный шлюз IPFS)


    Глобальный шлюз


    Можно использовать IPFS хостинг. Для этого надо добавить две записи в DNS.


    _dnslink TXT dnslink=/ipns/<наш id>/<имя каталога сайта>
    
    @ CNAME gateway.ipfs.io

    Но не все DNS хостинги позволят задать CNAME корневому домену.


    В данном случае наш IPFS клиент может работать с настройками по умолчанию. Как только кто то обратится к нашему сайту IPFS клиент на сервере gateway.ipfs.io скопирует от нас содержимое сайта и передаст через шлюз. Данный вариант удобен если ваш сервер за NAT. Но не забываем о том что у глобального шлюза тоже бывают перегрузки.


    Заключение


    Вот так просто мы делаем свой сайт доступным более современным способом. Теперь он доступен не только напрямую но также и в децентрализованной сети IPFS.


    Сайт для теста: ivan386.tk
    Через глобальный шлюз: ipfs.io/ipns/ivan386.tk
    Через локальный шлюз: 127.0.0.1:8080/ipns/ivan386.tk


    Сделал свой релиз клиента с исправлениями:


    1. Совместимость с punycode.
    2. Etag для всех GET запросов.
    3. Правильное определение скрытых файлов в Windows.

    Источники


    1. IPFS for websites
    2. ipfs command reference
      1. ipfs dns
      2. ipfs name
    3. Межпланетная файловая система IPFS
    4. Почему Интернету нужен IPFS, пока ещё не поздно
    5. Работа в IPFS с человеческим лицом
    6. PAC Functions
    7. Мультихеш
    8. IPFS implementation in Go

    Продолжение


    Хостим сайт в межпланетной файловой системе IPFS под Windows

    Поделиться публикацией

    Похожие публикации

    Комментарии 23
      +3

      И на какой еще планете этот сайт можно открыть?

        +4
        Пока только на этой.
        0

        Ну… maidsafe вроде как отдупляет, и сие интересней, чем то, о чем статья.
        А если нужно самый быстрый сайт (из многих точек мира), то есть cloudflare.

          0
          Вот кстати интересно есть ли CloudFlare в Норильске?

          Я воспользовался данным сервисом для 24 часового онлайна. Но в малонаселённых пунктах с медленным интернетом сомневаюсь что CloudFlare позаботится поставить свои сервера. Они держатся на слепом доверии что не будут вмешиваться в то что я через них публикую.

          IPFS клиенты и соответственно шлюзы могут быть в каждой локальной сети. Считайте это такой народный CDN. Поскольку содержимое идентифицируется мультихешем IPFS может проверить что получает от других клиентов именно то содержимое которое я опубликовал.

          По поводу MaidSafe ничего не могу сказать. Я и IPFS недавно только начал изучать.

            +1
            Если я правильно понял карту серверов CloudFlare (https://www.cloudflare.com/network/), то из всей России они есть только в Москве.
              0

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


              На счет cloudflare и населенные пункты — не уверен, что будут ставить, но весь мир и основные города стабильно (а из больших городов есть линки в маленькие). На счет контроля траффика… приведите пример, когда cloudflare вмешались во что-то, они даже радикальный сайт не закрыли.

            0
            Автор, было бы неплохо в начале статьи написать что это вообще такое IPFS и для чего «сие» нужно.
            Я прочитав всю статью целиком, только в конце понял о чем речь.
              +1
              Добавил.
              0
              Немного не по теме конкретно этой статьи, но есть вопрос по IPFS.

              Я сейчас экспериментирую со связкой IPFS+Webtorrent и мне не очень нравится результат. Напрягает падение самого демона IPFS при высокой частоте запросов к нему. Webtorrent-плеер играет видео через webseed, пока ты первый, кто смотрит его. Webseed-урл в торрент-файле указывает как раз на IPFS-хеш. Всё работает нормально только какое-то время, пока количество range-запросов к IPFS не упирается в какой-то непонятный мне потолок и демон падает. Перезапускается супервизиром, но этот downtime останавливает стрим, плеер получает 502 и ничего больше не работает, нужна перезагрузка страницы. Опытным путём выяснил, что демон очень жадный и хочет весь CPU на моём бедном микроинстансе. Я увеличил CPU/RAM дроплета, стало лучше. Но это пока клиент стримит только одно видео. Моя идея ещё и в том, чтобы webtorrent продолжал раздавать медиа-файл уже своими средствами, в фоне, после переключения воспроизведения на что-то другое. В итоге вопрос — сколько ж нужно IPFS-демону для нормальной жизни, если я уже дважды увеличивал инстанс и больше (по бюджету) не хочу? И вдогонку — есть ли какой-то список публичных шлюзов, чтобы я как-то балансировал нагрузку? Спасибо.
                0
                Я тоже эксперементировал с IPFS + ( WebTorrent и Bittorrent ) и выяснил что последовательная загрузка ему даётся легче. Я предпологаю что IPFS клиент проверяет при каждом запросе хеш блоков даже из кеша.

                Вы можете прикрыть свой шлюз кеширующим прокси чтобы снизить нагрузку. На данный момент IPFS для WebTorrent бесполезен в виде локального шлюза т.к. в настройках по умолчанию нет разрешения для range запросов. Но стоит добавить локальный шлюз в магнит или торрент на будущее. И инструктировать пользователей как его установить и настроить.

                Из публичны шлюзов я знаю только gateway.ipfs.io или ipfs.io. Можно пройтись по пирам в сети и найти с открытым наружу портом шлюза но это не правильное использование IPFS.

                Правильное использование сети IPFS это когда у каждого пользователя стоит IPFS клиент.

                Я в будущем может пороюсь в клиенте и попробую найти и выключить перепроверку хешей если запрос идёт от WebTorrent и Bittorrent.
                  0
                  Спасибо за развёрнутый ответ.

                  Я уже установил nginx в роли прокси, с кешированием. Мне это не особо помогло. Да и хочется быть ближе к основной идее — безсерверному ресурсу.

                  IPFS с range-запросами работает хорошо. Только падает в итоге :) Клиент у меня сначала пытается достучаться к локальному демону, если его нет — то к шлюзу на моём инстансе. В целом всё оно работает. Но ощущение общей сырости не даёт покоя. Или я что-то делаю не так, или Go-имплементация далека от стабильной версии.

                  Но если оставить в покое видео и стримить более лёгкий статический контент, то всё прекрасно. Что-то в этом есть.
                    0

                    Для IPNS в текущей версии клиента кеширование не включено. То есть не отдаются хедеры "Etag" и "Cache-Control".


                    Я исправил у себя отдачу "Etag"


                     core/corehttp/gateway_handler.go | 6 ++++--
                     1 file changed, 4 insertions(+), 2 deletions(-)
                    
                    diff --git a/core/corehttp/gateway_handler.go b/core/corehttp/gateway_handler.go
                    index c35431c..d69d8a9 100644
                    --- a/core/corehttp/gateway_handler.go
                    +++ b/core/corehttp/gateway_handler.go
                    @@ -177,7 +177,7 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
                            return
                        }
                    
                    -   etag := gopath.Base(urlPath)
                    +   etag := pbnd.Key().B58String()
                        if r.Header.Get("If-None-Match") == etag {
                            w.WriteHeader(http.StatusNotModified)
                            return
                    @@ -216,8 +216,10 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
                        // and only if it's /ipfs!
                        // TODO: break this out when we split /ipfs /ipns routes.
                        modtime := time.Now()
                    +
                    +   w.Header().Set("Etag", etag)
                    +
                        if strings.HasPrefix(urlPath, ipfsPathPrefix) {
                    -       w.Header().Set("Etag", etag)
                            w.Header().Set("Cache-Control", "public, max-age=29030400, immutable")
                    
                            // set modtime to a really long time ago, since files are immutable and should stay cached
                      0

                      Сделал свой релиз.

                        0
                        Это чудесно, всё никак не попробую. А вы делали им pull request? Всё же хочется получить на выходе одну имплементацию-стандарт, а не кучу форков.
                          0

                          Я сделал один пул реквест с исправлениями определения скрытых файлов под Windows. Но после того как отправил оказалось что его подписать надо. А потом ещё место с ошибкой нашёл. Пул реквес делал с сайта так как изменений был мизер. Как его поправить теперь не знаю.


                          Гуглу вон тоже отправил пул реквест и они тутже захотели чтоб я им документик подписал.


                          Я тоже хотел бы залить свои исправления в главный репозитарий и чтоб их приняли может даже с изменениями. Но мне нужно изучить их бюрократию.


                          В общем надо изучать эти процессы.

                    0
                    Уточню что я не состаю в команде разработчиков. Я только изучаю этот клиент. Возможно я смогу отправить им свои изменения кода но сколько они будут висеть до принятия не известно.
                      0
                      Читал другие ваши статьи, знаю, что вы тоже пробовали webtorrent+ipfs, поэтому наверняка сталкивались с теми же проблемами и может как-то удалось их обойти. Судя по всему, в этом клубе нас двое.
                    0
                    Много ресурсов сжирает демон?
                    Побочный вопрос:
                    tk продолжает раздавать бесплатные домены? С продлением за 19$?
                      0
                      Двухядерный AMD 2.30 GHz.

                      В простое от 0 до 15 процентов прыгает. Пока большой блок отдаёт до 50 прыгает на пару секунд. Памяти 720 МБ сьел. Но это при последовательном проигрывании видео в браузере.

                      При сохранении видео на диск скорость прыгает с 1МБ/с до 5МБ/с. Загрузка процессора прыгает от 10 до 80 пстоянно. Памяти сьел 1ГБ.

                      При случайной загрузке торентом скорость от 200КБ/с до 700КБ/с. Загрузка процессора от 50 до 90 изретка падая до 0. Память 900МБ.

                      Видео: Первый день осени
                      0
                      Продолжают. У меня стоит минимальная цена Upgrade'а на 1 год 9.95$. 2 года — 19.90$
                      0

                      Добавил новую информацию:


                      Публикацию через ID нужно использовать когда сайт часто обновляется. IPFS клиент через который публикуется контент должен быть постоянно включен или выключаться на небольшие промежутки времени. За день offline у меня клиент забыл привязку id -> мультихеш. Видимо привязка храниться только в DHT.
                        0
                        Есть ещё средство автоматизации ipscend.

                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                        Самое читаемое