====== Gemini (протокол) ======
Gemini - сетевой протокол прикладного уровня, являющийся наследником протокола Gopher.
Ориентирован на минимализм и приватность, поскольку исключает использование таких технологий как сжатие, Cookies и JavaScript;
формат передаваемых данных ограничен текстом или бинарными данными, обязательной является подпись TLS.
Тем не менее, протокол вполне многофункционален и позволяет работать с различными типами ресурсов: как хостинг статических файлов так и системы с авторизацией и обработкой пользовательских запросов - форумы, поисковые системы, организация радио и видео вещания, обмен изображениями и другими мультимедийными данными.
В виду своих характеристик, Gemini будет интересен тем, кого не устраивает "раздутость" современного протокола HTTP, а также подойдёт для пользователей командной строки, E-ink планшетов.
===== Терминология =====
Как и во многих других экосистемах, для Gemini характерна своя терминология, знание которой поможет лучше понимать контекст и формировать поисковые запросы.
* **Gemini space** - экосистема Gemini, подобно термину "Fediverse" для федеративной тематики
* **Capsule** - капсула, веб-сайт - название протокола отсылается к тематике космической программы, поэтому в сети многие ресурсы наследуют концепцию в своих названиях
* **Gemlog** - блог, персональная страница, фид профиля
===== Разметка =====
==== Gemtext ====
Gemtext (MIME text/gemini, .gmi) - близкий к Markdown текстовый формат, использующийся согласно спецификации Gemini по-умолчанию (если MIME-тип не указан) и предоставляющий легко читающийся в "source view" набор тегов:
# h1
## h2
### h3
=> ссылка
> цитата
* элемент списка
``` file.ext или альтернативный текст
исходный код
```
* file.ext - имя файла, путь к файлу или расширение: может интерпретироваться клиентом для подсветки синтаксиса
В разметке не используются декоративные технологии вроде CSS, при этом задача отрисовки ресурса выполняется на стороне браузера и полностью делегирована клиенту.
==== Gemfeed ====
Поскольку текстовый регламент протокола не подразумевает использование тегов, такие стандарты оповещений как Atom и RSS, без [[https://tildegit.org/solderpunk/gemfeed|внешних средств интеграции]], в Gemini неприменимы.
Несмотря на это, нативные подписки возможны - средствами [[https://geminiprotocol.net/docs/companion/subscription.gmi|стандарта]] для программной интерпретации изменений документа gemtext.
Говоря проще, протокол сохраняет человеко-понятную структуру документа, при этом позволяет клиентским приложениям отслеживать его обновления.
В браузере Lagrange, подписаться на обновления страницы можно с помощью меню ''Bookmarks'' - ''Subscribe to page...'' и выбрать соответствующий странице способ (меню подписок: ''View'' - ''Show Feeds'')
=== Отслеживание по дате ===
В данном подходе, осуществляется отслеживание по впереди идущей за ссылкой дате, в формате ISO 8601 (Y-m-d), например:
# Заголовок страницы, выполняет роль заголовка фида
Содержимое параграфа, игнорируется
=> /index.gmi любая ссылка, игнорируется
## Подраздел страницы, игнорируется
Произвольное содержимое подраздела, игнорируется
## Публикации
=> /pub1.gmi 2024-01-28 Ссылка на первую публикацию, отслеживается
=> /pub2.gmi 2024-01-29 Ссылка на вторую публикацию, отслеживается
=> /pub3.gmi Ссылка публикацию, не отслеживается (так как не содержит даты)
=> /pub4.gmi Ссылка публикацию, не отслеживается (так как дата является частью заголовка) 2024-01-30
Таким образом, документ не теряет читаемость для человека и при этом содержит мета-информацию для интерпретатора обновлений.
Единственный недостаток такого подхода заключается в том, что обновления нельзя получать чаще, чем раз в сутки.
Как заявлено в документации, связано это с временной зоной.
=== Отслеживание по заголовкам ===
Альтернативный подход, отслеживающий изменения в заголовках документа
# Мой блог, заголовок фида
Параграф описания
## Первая публикация, отслеживается
Описание первой публикации
=> /pub1.gmi Читать
## Вторая публикация, отслеживается
Описание второй публикации
=> /pub2.gmi Читать
...
===== Коды статусов =====
* **10-19** - //input expected// - ожидается ввод - используется например для отправки и получения данных форм
* **20-29** - //success// - код 20 аналогичен коду 200 в HTTP
* **30-39** - //redirection// - диапазон переадресации, в отправляемом пакете, код обычно сопровождается мета-ссылкой: ''code + link + \n\r + text''
* **40-49** - //temporary failure//
* **50-59** - //permanent failure//
* **60-69** - //client certificates// - в Gemini сертификаты используются для идентификации и авторизации пользователей
Клиент обязан отклонять любой код меньше 10 или больше 69, при этом уведомить пользователя.
В неопределённых случаях, приоритет будет отдан коду с начальным значением диапазона, например, 10 для 11 или 20 для 27.
===== Обработка запросов =====
Протокол предусматривает обмен пакетами с заголовками длиной максимум 1024 байт.
В эту длину необходимо уместить мета информацию пакета - например строку URI и/или данные пользовательского ввода.
Текстовые данные должны быть закодированы в стандарт RFC 3986 (известный такими функциями, как urlencode).
В какой то степени, это сокращает полезный объём заголовка при использовании например кириллицы.
Тело пакета состоит из "сырых" текстовых или бинарных данных без сжатия; сервер закрывает соединение после отправки последнего байта.
С помощью отправляемых клиенту статусов группы "10", сервер способен запрашивать пользовательский ввод (вместо привычных форм, обычно в браузерах Gemini - это всплывающее текстовое окно)
После получения и обработки данных, сервер обычно возвращает статус "20", статус "51" (не найдено) или редирект на целевую страницу с кодом "30".
Пример CLI-запроса с openssl:
echo -e "gemini://gemini.circumlunar.space:1965/\r\n" | openssl s_client -connect gemini.circumlunar.space:1965 -ign_eof
Пример условного ответа сервера с фразой "Hello world":
20 text/gemini; charset=utf-8; lang=en\r\nHello world
===== Клиент =====
Чтобы открыть ресурс с адресом %%gemini://%% необходим специальный браузер, стандартно работающий с портом 1965/TCP.
**Специфика**
* в протоколе Gemini нет webstorage и cookies, поэтому некоторые интерактивные сайты запрашивают для авторизации [[https://geminiprotocol.net/docs/protocol-specification.gmi#client-certificates|пользовательский сертификат]]
* вместо фидов RSS есть встроенные в браузер инструменты отслеживания контента (см. [[gemini_protocol#gemfeed]])
Пользователи GUI, могут начать с популярных [[https://gmi.skyjake.fi/lagrange/|Lagrange]], [[https://codeberg.org/jeang3nie/eva|Eva]], [[https://kristall.random-projects.net/|Kristall]] и [[https://github.com/kr1sp1n/awesome-gemini#graphical|других]].
Появился новый браузер [[https://github.com/mochaman/alhena|Alhena]] (Java), отличающийся возможностью inline-загрузки документов (спецификация этого не предусматревает с целью приватности) а также гибкими настройками интерфейса.
Пользователям Ygg(stack), Tor и I2P следует обратить внимание на Rust/GTK браузер (в разработке) [[https://github.com/YGGverse/Yoda|Yoda]] - предоставляющий:
* гибкие настройки проксирования по regex
* подсветку строки адреса для проксируемых запросов (с наименованием используемого сервера)
* подробную статистику сокет-подключения (опционально поддерживает geo-ip для Интернет запросов)
* по-умолчанию исключает внешние редиректы (требует подтверждения для перехода)
* подсветку синтаксиса (syntect) для удобства чтения документации в формате gemtext
* проверку орфографии (libspelling) для пользовательского ввода
===== Сервер =====
Понятие "сервер" в среде Gemini может быть непривычным для пользователей веб, поскольку вместо прокси Nginx или Apache, этот термин зачастую предусматривает полноценный сервис для конкретной задачи, резервирующий за собой отдельный хост и порт.
В каталоге [[https://github.com/kr1sp1n/awesome-gemini#servers|awesome-gemini]] представлено большое количество таких решений.
Например, для запуска простой статики, подойдёт сервер [[https://github.com/mbrubeck/agate|Agate]] (Rust), [[gemini_protocol:gmid]] (C) или [[gemini_protocol:twins]] (Go)
* в качестве %%index.html%% указывается %%index.gmi%%
* для публикации сервера на разных сетевых интерфейсах, лучше использовать gmid, так он позволяет гибко настраивать обработку SNI (актуально для связки IPv6 + Alfis)
* CN для сертификата можно указывать любой (удобно при мультибиндинге на разные сети) - валидация клиентом осуществляется по отпечатку / публичному ключу, по крайней мере в Lagrange
Запуск динамических ресурсов часто предусматривает разработку собственного сокет-сервера для реализации специфики отдельно взятого приложения.
Веб-разработчикам проще понять принцип работы "server-side" на примере нескольких файлов [[https://github.com/eapl-gemugami/gemini-php|gemini-php]]. Для разработки server-side на PHP, смотрите актуальные решения вроде [[https://github.com/ratchetphp/Ratchet|Ratchet]] - многофункциональную библиотеку для организации асинхронных сокет-серверов.
==== I2P ====
Ввиду фундаментальной приватно-ориентированности, протокол Gemini идеален для использования в комбинации с [[:i2p|I2P]]. Для организации сайта (капсулы) в i2pd, достаточно указать следующие настройки туннеля:
[mycapsule]
type = server
host = 127.0.0.1
port = 1965
keys = mycapsule.dat
* при условии, что сервер Agate, gmid или другой "слушает" входящие подключения на 127.0.0.1:1965
* mycapsule.dat - сделать резервную копию (ключ домена)
После чего, ресурс можно открыть в любом клиенте с поддержкой локального проксирования, например:
%%gemini://shxxkkrws2m6qowjse5jpgmu64vzupnnhxrhdzrn6fr6m7ynddbq.b32.i2p%%
===== Ресурсы =====
* %%gemini://geminiprotocol.net%% - домашняя страница проекта
* %%gemini://geminiprotocol.net/docs/ru/%% - документация на русском
* %%gemini://geminispace.info%% - внутрисетевой поиск
* %%gemini://station.martinrue.com%% - социальная сеть по типу twitter
* %%gemini://astrobotany.mozz.us%% - ASCII ботаника / тамагочи
* %%gemini://cthulhu28.space%% - квест по мотивам Космических рейнджеров
* %%gemini://pub.phreedom.club/crypto.gmi%% - курсы криптовалют
* %%gemini://gemlog.blue%% - самый простой способ разместить страничку в сети Gemini ([[https://gemlog.blue|веб-прокси]])
* %%gemini://cities.yesterweb.org%% - хостинг с поддоменом, есть возможность загрузки файлов через Titan и WebDAV
* %%gemini://flounder.online%% - хостинг с поддоменом и динамическим агрегатором активности на главной странице, есть SFTP
* %%gemini://bbs.geminispace.org/s/Yggdrasil%% - Yggdrasil subspace on BBS
===== Yggdrasil =====
==== TLS ====
Спорным моментом является обязательное шифрование TLS поверх уже имеющегося слоя.
Также сертификат TLS предусматривает наличие CN записи, что может стать проблемой при выборе сервера с поддержкой CN/SNI в формате IPv6.\\
Ввиду указанных особенностей, если не критична коллизия адреса Yggdrasil и не требуется авторизация пользователей, более целесообразным выбором для сети Yggdrasil может быть протокол [[:nex_protocol|Nex]].
==== DNS ====
Пользователи [[:yggdrasil:dns:internal_dns|DNS с подключением через Yggdrasil]] и в частности - [[:yggdrasil:dns:alfis#скорость_работы|Alfis DNS]], использующего стандартно AdGuard, могут столкнуться с задержками при открытии казалось-бы легковесных страниц Gemtext.
Связано это с относительно простым устройством внутрисетевых браузеров, разработчики которых не особо стремятся вникать в особенности альтернативных подключений. В то время, как [[:yggdrasil:web-browsers|HTTP браузеры]] из коробки имеют встроенные инструменты кеширования, пользователи Gemini могут ускорить загрузку с помощью кеширующих DNS серверов. Также можно снизить задержки для резольва Clearnet, указав DNS CloudFlare (1.1.1.1) с обычно наиболее высокими показателями отклика.
Второй причиной задержки отклика, может быть отключённый клиентом (на стороне back-end) режим кеширования TLS/handshake. Это нужно для корректной маршрутизации клиентом пользовательских сертификатов, которые согласно спецификации Gemini, применяются не только к хосту, но и к пути (path) запроса.
===== Похожие протоколы =====
* Gopher
* Guppy - %%gemini://guppy.000090000.xyz/guppy-spec.gmi%%
* Spartan - %%gemini://spartan.mozz.us/specification.gmi%%
* [[:nex_protocol|Nex]] - %%nex://nightfall.city/nex/info/specification.txt/%%
* Scroll - %%gemini://scrollprotocol.us.to%%
* Text - https://textprotocol.org
==== Сравнение ====
gemini spartan scroll nex
------ ------- ------ ---
naming scheme space sparta/greece scrolls & libraries cityscape & highways
transport TCP + TLS TCP TCP + TLS TCP
request structure full URL hostname & path full URL path
request encoding utf-8 us-ascii utf-8 utf-8
status codes 18 4 18 0
document type text/gemini text/gemini text/scroll text/plain
input prompt 1x status "=:" prompt line 1x status none
data upload limited yes limited no
mimetypes yes yes yes no
virtual hosting yes yes yes no
same-site redirects yes yes yes no
cross-site redirects yes no yes no
proxy requests yes no yes no
"lang" response parameter yes no yes no
lang request parameter no no yes no
response metadata heuristic heuristic yes heuristic
abstract/metadata requests no no yes no
link relationships heuristic heuristic yes heuristic
list nesting no no yes heuristic
Источник: %%gemini://scrollprotocol.us.to%%
===== Статьи внутри раздела =====
{{indexmenu>:gemini_protocol}}
===== Ссылки =====
* [[https://geminiprotocol.net|Официальный сайт]]
* [[https://ru.wikipedia.org/wiki/Gemini_(протокол)|Страница на википедии]]
* [[https://github.com/kr1sp1n/awesome-gemini|Каталог программного обеспечения на GitHub]]
* [[https://www.dokuwiki.org/plugin:gemini|Плагин для DokuWiki]] | [[https://github.com/YGGverse/bdoku|Проект β-Doku]]
* [[https://portal.mozz.us|Веб-прокси]]
* [[https://gopher.emacs.ch|Поиск с функцией веб-прокси для протоколов Gemini, Gopher, Spartan]]
* [[https://github.com/YGGverse/Yo/tree/gemini|Ветка]] поисковой системы [[:yggdrasil:sites_and_services:search_services:yo|Yo!]] для протокола Gemini
* [[https://github.com/YGGverse/Yoda|Yoda]] (Rust) - GTK браузер от YGGverse, с упором на приватность (исключает предзагрузку документов по-умолчанию, внешние редиректы) и поддержку IPv6, I2P посредством гибких настроек проксирования