Parlons!разговор без центра
РУС
English简体中文РусскийУкраїнська
Руководство

Parlons Node — руководство оператора

Как запустить Parlons Node: полный узел Minima, ретранслятор и ваш аккаунт в одном процессе.

Содержание
  1. 1. Что такое Parlons Node
  2. 2. Архитектура
  3. 3. Требования
  4. 4. Загрузка и проверка jar-файла
  5. 5. Три способа установки
  6. 6. Первый запуск
  7. 7. Юнит systemd (с комментариями)
  8. 8. Справочник по настройкам: все свойства
  9. 9. Порты
  10. 10. Структура каталога данных
  11. 11. TLS-прокси: Caddy, nginx, Apache
  12. 12. Кейп ретранслятора и mesh-сеть
  13. 13. Режим MegaMMR и корневой узел (rootnode)
  14. 14. Шлюз кошелька и его токен
  15. 15. Хостинг NFT и parlons.node.public
  16. 16. DEX-кейп ретранслятора (Dexicon)
  17. 17. Аккаунт, подключение устройств и локальная панель
  18. 18. Вспомогательный процесс keets (мост KeetChat)
  19. 19. MDS (MiniHUB) на узле
  20. 20. Сид-фразы, личность и резервные копии
  21. 21. Административный RPC
  22. 22. Обновление и откат
  23. 23. Проверка извне
  24. 24. Мониторинг и журналы
  25. 25. Заметки о файрволе
  26. 26. Устранение неполадок
  27. 27. Чек-лист безопасности
  28. 28. Настольные приложения, в которые встроен этот jar
  29. 29. Глоссарий

Для Parlons Node 0.2.144 (тег выпуска node-v0.2.144), который несёт DEX-ретранслятор 0.1.5. В выпуске два jar: parlons-node-0.2.144.jar — обычный узел, и parlons-node-fleet-0.2.144.jar — тот же узел со встроенными средой Node.js и вспомогательным процессом keets, так что один jar ещё и запускает транспорт keets, публичный узел начальной загрузки HyperDHT и почтовый ящик keets (§18). Установщик одной командой выбирает fleet-jar всегда, когда машина его тянет.

Имена хостов в примерах (node.example.com, peer1.example.net и т. д.) — условные. Замените их своими.

Для каждой задачи есть пронумерованная процедура «Как …» с точными командами. Команды рассчитаны на сервер с Debian или Ubuntu, пути скрипта развёртывания (/opt/maxima, /var/lib/parlons-node), служебного пользователя maxima и порты по умолчанию. Если у вас они другие, измените их.

Связанные руководства:


1Что такое Parlons Node

Parlons Node — это один Java-процесс, который содержит:

Весь узел управляется одной сид-фразой. При первом запуске личность ретранслятора Maxima и аккаунта выводится из сид-фразы кошелька узла, а затем закрепляется в identity.txt (см. §20).

Кому это нужно? Большинству людей — нет. Parlons Cloud (parlons-cloud.jar) держит постоянно работающий аккаунт примерно на 1 ГБ оперативной памяти. Запускайте Parlons Node, если хотите хранить полную копию цепочки, обслуживать сеть ретрансляторов и предоставить телефонам шлюз кошелька.


2Архитектура

                        Internet
   ┌───────────────┬──────────────┬─────────────────────┐
   │ Minima peers  │ phones /     │ browsers, phones,    │
   │ (TCP p2p)     │ Maxima       │ Dexicon clients      │
   │               │ clients      │ (HTTPS 443)          │
   ▼               ▼ (TCP 9501)   ▼                      │
┌──────────────────────────────────────────┐   ┌─────────┴──────────────┐
│           parlons-node.jar (one JVM)     │   │  TLS front (Caddy /    │
│                                          │   │  nginx / Apache)       │
│  Minima node (org.minima)   :9001 public │   │                        │
│    ├─ admin RPC  127.0.0.1:p2p+4 (opt-in)│◄──┤ /parlons-node/ ──► 9585│
│    └─ MDS        127.0.0.1:p2p+2 (opt-in)│   │ /dex-relay/    ──► 9602│
│                                          │   └────────────────────────┘
│  Maxima relay cape           :9501 public│
│    (TCP, plus UDP STUN on the same port) │
│                                          │
│  Wallet gateway + NFT  127.0.0.1:9585    │
│  Account panel + API   127.0.0.1:9587    │
│  DEX relay cape        127.0.0.1:9602    │  (opt-in; loopback by default when
│                                          │   parlons.dex.public is set)
│  Parlons account (pairing, chat, push)   │
│  keets chat bridge (when -keets is on)   │──► keets sidecar (Node.js child)
└──────────────────────────────────────────┘
КомпонентКодСлушает (по умолчанию)Состояние по умолчанию
Узел Minimaвстроенный node/libs/minima-node.jarTCP 9001 (parlons.node.port)включён
Административный RPCnode/.../AdminRpc.java127.0.0.1:<p2p+4>, всегда loopbackвыключен (parlons.node.rpc=false)
MDS / MiniHUBMDS из форка Minima127.0.0.1:<p2p+2> (файлы), <p2p+3> (команды)выключен
Кейп ретранслятораserver/.../RelayRuntime, RelayServerTCP 9501, плюс UDP STUN на том же портувключён
Шлюз кошелька и /nftnode/.../NodeGateway.java, NftStore.java127.0.0.1:9585включён (запускается, как только готов кошелёк)
Панель аккаунтаaccount/.../ParlonsLocal.java127.0.0.1:9587включена
DEX-кейп ретранслятораdexrelay/.../DexRelay.java127.0.0.1:<port>, если задан parlons.dex.public, иначе 0.0.0.0:<port>; явно заданный parlons.dex.bind имеет приоритетвыключен (parlons.dex.port=0)
Мост keetsnode/.../KeetsChatBridge.javaнет (опрашивает узел)включён, только когда узел запущен с -keets

Порядок запуска (из ParlonsNodeMain.main):

  1. Применяются собственные флаги Minima (parlons.node.args и parlons.node.conf), затем свойства parlons.node.*.
  2. Запускается встроенный узел Minima.
  3. Если включён, запускается административный RPC. Если он не может занять порт, процесс завершается с кодом 2.
  4. Если включён, запускается DEX-кейп. Он не зависит от цепочки, поэтому работает ещё до синхронизации узла.
  5. Фоновый поток ждёт, пока хранилище (vault) узла станет доступно для чтения (до 120 с). Затем он выводит личность и запускает кейп ретранслятора, шлюз и хранилище NFT, а затем аккаунт — именно в таком порядке.
  6. Каждые 30 с в журнал пишется строка heartbeat.

3Требования

Java

Оперативная память и куча

РольОЗУ на сервереКуча Java (-Xmx)
Узел с MegaMMR (по умолчанию; нужен, чтобы быть шлюзом кошелька)8 ГБминимум 3 ГБ
Узел без MegaMMR (-Dparlons.node.megammr=false)2 ГБ768 МБ
Fleet-jar (любой из вариантов выше + вспомогательный процесс keets: Node.js, DHT, почтовый ящик)+ 1 ГБ, минимум 2 ГБ; только x86_64 или aarch64как выше (MemoryMax + 1 ГБ)

Эти цифры взяты из заметок по парку серверов в cloud/NODE-SETUP.md. Они получены на горьком опыте: узлы MegaMMR с кучей 2 ГБ и 2,5 ГБ зацикливались на ошибках нехватки памяти, а один с 3 ГБ упал.

Диск

Занятое место на диске растёт вместе с цепочкой. Фиксированной цифры в коде нет. Заложите также место под:

Сеть

Как проверить сервер перед установкой

  1. Проверьте версию Java. Она должна быть 11 или новее; лучше 21 или новее:
    java -version
  2. Проверьте, что модуль jdk.httpserver присутствует. Команда должна вывести одну строку:
    java --list-modules | grep jdk.httpserver
  3. Проверьте объём ОЗУ. Для узла MegaMMR нужно 8 ГБ, без MegaMMR — 2 ГБ:
    free -h
  4. Проверьте свободное место на диске там, где будет каталог данных:
    df -h /var/lib
  5. Проверьте, что нужные узлу порты ничем не заняты:
    ss -ltnp | grep -E ':(9001|9005|9501|9585|9587|9602) '

    Команда не должна ничего вывести. Если порт 9001 занят обычным узлом Minima, запланируйте перенос P2P-порта узла (§9). Если порт 9501 занят maxima-relay.service, запланируйте его замену (§5).


4Загрузка и проверка jar-файла

Релизы публикуются на GitHub в eurobuddha/maxima под тегами node-v<version>. Они публикуются с --latest=false, поэтому значок «Latest» репозитория не указывает на узел. Всегда выбирайте релиз узла по его тегу.

  1. Скачайте jar-файл и файл контрольных сумм:
    VER=0.2.144
    curl -fLO https://github.com/eurobuddha/maxima/releases/download/node-v$VER/parlons-node-$VER.jar
    curl -fLO https://github.com/eurobuddha/maxima/releases/download/node-v$VER/SHA256SUMS

    Для fleet-jar (с транспортом keets, узлом начальной загрузки DHT и почтовым ящиком) скачайте из того же выпуска parlons-node-fleet-$VER.jar. Его SHA-256: 3dfd655e2c2e3541f471252b3ddbd058c9040ba5814b2bbbbba40674771bf166.

  2. Проверьте хеш SHA-256. Хеш parlons-node-0.2.144.jar:
    c5b114cc13294bdeee95d9872fc6710cd99c92472ffb63c1581081343663a6f5
    echo "c5b114cc13294bdeee95d9872fc6710cd99c92472ffb63c1581081343663a6f5  parlons-node-0.2.144.jar" | sha256sum -c -
    # macOS: shasum -a 256 -c  (same input)

    Команда должна вывести parlons-node-0.2.144.jar: OK. Если это не так, удалите файл и не запускайте его.

  3. Проверьте версию. Это не запускает узел:
    java -jar parlons-node-0.2.144.jar --version
    # parlons-node 0.2.144
  4. Выведите встроенную справку со списком основных свойств. Это тоже не запускает узел:
    java -jar parlons-node-0.2.144.jar --help

Как вместо этого собрать jar-файл из исходного кода

  1. Клонируйте репозиторий и соберите fat jar:
    git clone https://github.com/eurobuddha/maxima.git
    cd maxima
    ./gradlew :node:fatJar
  2. Найдите jar-файл. Это node/build/libs/parlons-node-<version>.jar:
    ls node/build/libs/
  3. Перед отправкой убедитесь, что jar-файл содержит ваше изменение. Уже случалось, что устаревший core.jar выходил под новым номером версии. Посчитайте вхождения символа, который вы добавили в изменённый класс; результат должен быть 1 или больше:
    unzip -p node/build/libs/parlons-node-<version>.jar <class path> | grep -ac <symbol>
  4. Запишите его контрольную сумму, чтобы ещё раз проверить её на сервере перед запуском:
    sha256sum node/build/libs/parlons-node-<version>.jar

Jar-файл не принимает параметров командной строки. Он понимает только аргументы --version/-v и --help/-h/help. Любой другой аргумент выводит справку в stderr и завершает работу с кодом 2. Каждая настройка — это системное свойство -D, указанное перед -jar.


5Три способа установки

A. Установщик одной командой (начните с него)

На самой Linux-машине (VPS, Raspberry Pi 4/5 с 64-битной ОС, домашний сервер), от root или пользователя с sudo:

curl -fsSL https://parlons.info/install.sh | bash

Одна команда даёт сети полноценную точку присутствия. По умолчанию машина запускает в одном процессе:

Что он делает, по порядку:

  1. Ставит Java 11+ и qrencode (apt, dnf, apk или pacman), если их нет, и Caddy для HTTPS-фронта (если порты 80/443 уже занимает другой веб-сервер, он сообщает, какие два пути проксировать самостоятельно, §11).
  2. Находит на GitHub новейший выпуск node-v…, скачивает parlons-node-fleet-<ver>.jar и отвергает его, если sha256 не совпадает с SHA256SUMS выпуска.
  3. Создаёт пользователя maxima и /var/lib/parlons-node (права 700), ставит /usr/local/bin/parlons-pair и записывает защищённый parlons-node.service (§7) с -Dparlons.fleet=true, -Dparlons.public.host=<ваш публичный IPv4>, -Dparlons.dex.public=https://<имя>/dex-relay и -Dparlons.node.public=https://<имя>/parlons-node.
  4. Подбирает узел под машину: при 3,5 ГБ ОЗУ и больше — MegaMMR с кучей 2 ГБ; меньше — обычный полный узел с кучей 768 МБ. MemoryMax — куча плюс 1,5 ГБ на вспомогательный процесс. Синхронизация с 65.109.31.226:9001.
  5. Открывает 9001/tcp, 9501/tcp+udp, 49737/udp и 80 + 443 в ufw или firewalld, если один из них активен.
  6. Запускает узел, ждёт адрес аккаунта и печатает его полностью.
  7. Просит задать пароль администратора для сопряжения (только при первой установке), затем ввести его ещё раз и рисует QR-код, который телефон сканирует в Parlons Cloud.
  8. Печатает публичный ключ keets машины, адрес её узла начальной загрузки DHT и ключ почтового ящика вместе с командой, которой сопровождающий списка подписывает ящик в опубликованный список.

Полному набору нужны процессор x86_64 или aarch64, 2 ГБ ОЗУ и публичный IPv4-адрес. Если чего-то нет, установщик объясняет почему и откатывается к обычному jar (parlons-node-<ver>.jar: узел Minima, ретранслятор Parlons и аккаунт, без keets и без DEX), которому хватает 1 ГБ на любом процессоре.

Параметры (ставьте их после bash -s --):

ПараметрДействие
--host node.example.comОтдавать DEX-ретранслятор и шлюз кошелька под вашим именем вместо sslip.io. Сначала направьте A-запись имени на машину; Caddy сам получит сертификат.
--public-host 1.2.3.4Публичный IPv4, который объявляют DHT и ретранслятор. По умолчанию — глобальный адрес машины. За домашним роутером укажите свой публичный адрес и пробросьте порты.
--basicНамеренно обычный jar: без транспорта keets, DHT, почтового ящика и DEX.
--fleetНастаивать на полном jar; завершиться ошибкой вместо отката.
--updateСкачать новейший выпуск и перезапустить. Повторный запуск команды установки делает то же самое.
--uninstallОстановить и удалить службу и parlons-pair. /var/lib/parlons-node (личность, кошелёк, чаты) сохраняется.
--no-megammrОбычный полный узел без MegaMMR (хватит 1 ГБ ОЗУ). Выбирается автоматически на машинах с менее чем 3,5 ГБ.
--heap <размер>Другая куча Java, например --heap 3g.

Например, со своим доменом: curl -fsSL https://parlons.info/install.sh | bash -s -- --host node.example.com

Установщик не задаёт пиров сетки ретрансляторов (используется встроенный список начальной загрузки) и полку blob. Для этого возьмите скрипт развёртывания (B) или отредактируйте юнит (§7). На Mac или Windows установите Parlons Desktop. Если машина вовсе не тянет узел, аккаунт без блокчейна — get-parlons-cloud.sh — работает в 1 ГБ (руководство Parlons Cloud Portal).

Как установить с помощью установщика одной командой

  1. Откройте 9001/tcp, 9501/tcp и 9501/udp, 49737/udp, а также 80 + 443/tcp в файрволе облачного провайдера или пробросьте их на домашнем роутере. Аккаунт работает и без них; ретрансляция для других, раздача блоков, DHT и DEX-ретранслятор требуют их.
  2. Если у вас есть домен, направьте A-запись на машину сейчас, чтобы Caddy получил сертификат в конце установки. Иначе пропустите: имени sslip.io ничего не нужно.
  3. Выполните команду выше в SSH-сессии или терминале машины. Не запускайте её из скрипта без терминала: тогда шаги с паролем и QR будут пропущены.
  4. По запросу дважды введите пароль администратора для сопряжения. Сохраните его: он нужен для каждого нового приглашения ваших устройств.
  5. По повторному запросу введите пароль один раз. Появятся QR-код и полное приглашение.
  6. В Parlons Cloud на телефоне нажмите Scan pairing QR и отсканируйте его.
  7. Прочтите последние строки. Они называют URL DEX-ретранслятора и шлюза кошелька и печатают публичный ключ keets машины, адрес начальной загрузки DHT и ключ почтового ящика. Отправьте строку с ящиком сопровождающему списка; пока ящик не подписан в опубликованный список, машина ретранслирует и выполняет начальную загрузку, но не хранит почту для телефонов офлайн.
  8. Следите за синхронизацией цепочки: journalctl -u parlons-node -f | grep heartbeat.
  9. Проверьте DEX-ретранслятор с другой машины: curl -s https://<имя>/dex-relay/dex/health должен ответить. После первого запуска сертификат может появиться через минуту.
  10. Сделайте резервную копию сид-фразы (§20).

Если шаг 4 или 5 был пропущен, выполните один раз sudo parlons-pair --set-admin-password, затем sudo parlons-pair --admin.

B. Скрипт развёртывания (со своего компьютера)

Запускайте его из клона репозитория на своём компьютере, указав чистый Linux-сервер, к которому вы можете подключиться по SSH как root. Повторный запуск обновляет узел: установка и обновление — одна и та же операция.

Как установить с помощью скрипта развёртывания

  1. На своём компьютере клонируйте репозиторий. В нём находятся ops/deploy-parlons-node.sh и ops/parlons-pair:
    git clone https://github.com/eurobuddha/maxima.git
    cd maxima
  2. Положите проверенный jar-файл в dist/ (§4). Без --jar скрипт берёт самый новый dist/parlons-node-*.jar:
    mkdir -p dist
    mv ~/Downloads/parlons-node-0.2.144.jar dist/
  3. Убедитесь, что вход по SSH-ключу от имени root работает. Скрипт использует BatchMode=yes, поэтому не может ответить на запрос пароля:
    ssh -o BatchMode=yes root@node.example.com true && echo ssh-ok
  4. Если на сервере уже работает maxima-relay.service на порту 9501, добавьте --replace-relay к следующей команде.
  5. Запустите скрипт. Ниже — типичный узел MegaMMR с TLS-прокси; все флаги перечислены в таблице ниже:
    ops/deploy-parlons-node.sh root@node.example.com \
        --jar dist/parlons-node-0.2.144.jar \
        --heap 3g \
        --rootnode seed-peer.example.net:9001 \
        --rpc \
        --megammr-seed https://eurobuddha.com/mega.mmr \
        --public https://node.example.com/parlons-node \
        --dex 9602 --dex-public https://node.example.com/dex-relay \
        --peers "peer1.example.net:9501,peer2.example.net:9501"
  6. Прочитайте итоговую сводку в конце. В ней выводятся адрес кошелька аккаунта, личность Maxima (Mx…) и bearer-токен шлюза. Храните токен в секрете (§14).
  7. Настройте TLS-прокси (§11).
  8. Подключите телефон (§17) и сделайте резервную копию сид-фразы (§20).
  9. Проверьте узел с другой машины (§23).

Что делает скрипт

Скрипт выполняет эти шаги по порядку:

  1. Устанавливает JRE без графики, если java нет, и пытается установить qrencode (для QR-кодов подключения).
  2. Создаёт непривилегированного системного пользователя maxima и каталог /var/lib/parlons-node с правами 700.
  3. Загружает jar-файл в /opt/maxima/parlons-node-<ver>.jar и проверяет его SHA-256. Только после этого он направляет символическую ссылку /opt/maxima/parlons-node.jar на новый jar-файл.
  4. Устанавливает /usr/local/bin/parlons-pair.
  5. Записывает защищённый юнит /etc/systemd/system/parlons-node.service.
  6. Открывает порты P2P и ретранслятора в ufw или firewalld. Порт DEX он открывает, только если --dex указан без --dex-public, а порт шлюза — только с --gateway-public.
  7. Запускает узел и проверяет, что порт ретранслятора слушает.
  8. Необязательно: --seed-from принимает существующую фразу из 24 слов (§20).
  9. Необязательно: --megammr-seed импортирует снимок MegaMMR (§13).
  10. Выводит адрес кошелька аккаунта, личность Maxima, токен шлюза и инструкции по подключению устройств.
Флаг скриптаПревращается вПо умолчанию
--jar FILEjar-файл для развёртываниясамый новый dist/parlons-node-*.jar
--heap 3g-Xmx2g (мало для MegaMMR; укажите 3g или больше)
--memmax 3584MMemoryMax юнитакуча + 512M
--p2p-port N-Dparlons.node.port9001
--relay-port N-Dparlons.relay.port9501
--gateway-port N-Dparlons.gateway.port9585
--gateway-public-Dparlons.gateway.bind=0.0.0.0 и открывает портloopback
--public URL-Dparlons.node.publicне задано
--rootnode h:p-Dparlons.node.rootnodeне задано (узел не будет синхронизироваться)
--no-megammr-Dparlons.node.megammr=falseMegaMMR включён
--rpc-Dparlons.node.rpc=trueвыключен
--peers h:p,…-Dparlons.relay.peersне задано (используется встроенный в код начальный список)
--blobstore MB-Dparlons.relay.blob0
--dex PORT-Dparlons.dex.port0 (выключен)
--dex-public URL-Dparlons.dex.bind=127.0.0.1 -Dparlons.dex.public=URLне задано
--passphrase-file F-Dparlons.node.passphrase.fileне задано
--node-args "…"-Dparlons.node.argsпусто
--keetsдобавляет -keets -keetssidecar /opt/maxima/keets-sidecar/index.js к аргументам узла и загружает вспомогательный процессвыключен
--seed-from F --archive h:pоднократная пересинхронизация кошелька на фразу из F (нужен --rpc), затем закрепляет её в identity.txt— (--archive по умолчанию указывает на архивный узел, прописанный в скрипте)
--megammr-seed URLоднократный импорт MegaMMR (нужен --rpc)—
--replace-relayостанавливает и отключает maxima-relay.service, чтобы узел мог занять его порт—

Всегда указывайте --dex-public вместе с --dex. С ним скрипт задаёт parlons.dex.bind=127.0.0.1 и держит порт закрытым. Без него DEX-кейп слушает 0.0.0.0, и скрипт открывает порт в интернет как обычный HTTP.

Скрипт записывает в юнит Restart=always, поэтому узел возвращается и после штатного завершения (quit, импорт MegaMMR, пересинхронизация).

C. Вручную

Минимальная команда:

java -Xmx3g -Dparlons.node.data=/var/lib/parlons-node -jar parlons-node.jar

У узла, запущенного так, нет корневого узла (rootnode), поэтому он не будет синхронизироваться.

Как установить вручную

Эти шаги делают на сервере то же, что и скрипт развёртывания. Выполняйте их от имени root.

  1. Установите Java, если её нет, и qrencode, если вам нужны QR-коды подключения:
    apt-get update
    apt-get install -y default-jre-headless qrencode
  2. Создайте служебного пользователя и каталоги:
    id maxima >/dev/null 2>&1 || useradd --system --home /var/lib/maxima --shell /usr/sbin/nologin maxima
    mkdir -p /opt/maxima /var/lib/parlons-node
    chown -R maxima:maxima /var/lib/parlons-node
    chmod 700 /var/lib/parlons-node
  3. Скопируйте проверенный jar-файл в /opt/maxima и направьте на него символическую ссылку:
    cp parlons-node-0.2.144.jar /opt/maxima/
    cd /opt/maxima
    echo "c5b114cc13294bdeee95d9872fc6710cd99c92472ffb63c1581081343663a6f5  parlons-node-0.2.144.jar" | sha256sum -c -
    chmod 644 parlons-node-0.2.144.jar
    ln -sfn parlons-node-0.2.144.jar parlons-node.jar
  4. Необязательно: установите помощник подключения из клона репозитория:
    install -m 755 ops/parlons-pair /usr/local/bin/parlons-pair
  5. Создайте файл юнита /etc/systemd/system/parlons-node.service по примеру из §7. Измените имена хостов, размер кучи и MemoryMax под свой сервер.
  6. Откройте порты P2P и ретранслятора (§25):
    ufw allow 9001/tcp
    ufw allow 9501/tcp
  7. Запустите узел, затем следуйте §6:
    systemctl daemon-reload
    systemctl enable --now parlons-node

6Первый запуск

  1. Запустите службу (установщик одной командой и скрипт развёртывания уже сделали это):
    systemctl enable --now parlons-node
    systemctl is-active parlons-node
  2. Следите за журналом:
    journalctl -u parlons-node -f
  3. Найдите строку запуска. В ней указаны версия, каталог данных и порты:
    [parlons-node] Parlons Node 0.2.144 — booting embedded Minima node <ver> at /var/lib/parlons-node/<base> (p2p 9001, megammr true, admin rpc 127.0.0.1:9005 (loopback-bound))
  4. Следите за синхронизацией цепочки. Каждые 30 с строка heartbeat выводит высоту блока:
    [parlons-node] heartbeat: node block=<n> chainlen=<n> | cape=up:9501 | gateway=up:9585 | account=up:<n> hosts, <n> devices

    Первая синхронизация закончена, когда block= достигает текущей вершины цепочки. Фиксированного времени для этого нет: оно зависит от сервера и соединения.

  5. Когда кошелёк готов, появляются такие строки:
    • identity: pinned from the vault into identity.txt (только при первом запуске);
    • Maxima cape up on port 9501 — identity Mx…;
    • account wallet = node wallet: 0x… (Mx…);
    • wallet gateway up on 127.0.0.1:9585/cmd (… bearer token in /var/lib/parlons-node/gateway-token.txt);
    • account up: attached to N relay(s)….
  6. На узле MegaMMR один раз импортируйте MegaMMR (§13). Пока вы этого не сделаете, балансы существующих адресов будут возвращаться пустыми.
  7. Подключите телефон (§17):
    sudo parlons-pair --set-admin-password
    sudo parlons-pair --admin
  8. Сделайте резервную копию сид-фразы (§20).

7Юнит systemd (с комментариями)

Этот юнит повторяет тот, который записывает ops/deploy-parlons-node.sh, с флагами, которые парк серверов использует в октябре 2026 года: узел MegaMMR, ретранслятор на 9501, шлюз и DEX-кейп на loopback за TLS и явно заданный начальный список mesh-сети.

systemd не допускает комментариев в конце строки или внутри продолженной строки ExecStart, поэтому пояснения находятся в блоке комментариев над ExecStart.

# /etc/systemd/system/parlons-node.service
[Unit]
Description=Parlons Node - full Minima node + Maxima cape + wallet gateway (0.2.144)
Documentation=https://github.com/eurobuddha/maxima
After=network-online.target
Wants=network-online.target
# If the node crashes 5 times within 300 s, systemd stops restarting it (check after heap changes).
StartLimitIntervalSec=300
StartLimitBurst=5

[Service]
Type=simple
User=maxima
Group=maxima

# What each property does (full reference: section 8):
#   -Xmx3g                          hard heap ceiling (MegaMMR needs at least 3g on an 8 GB box)
#   parlons.node.data               data directory (seed, identity, tokens, chain)
#   parlons.node.port=9001          Minima P2P port, public. The admin RPC is p2p+4 = 9005.
#   parlons.node.rpc=true           loopback admin RPC (needed for vault, megammr import)
#   parlons.node.megammr=true       keep the MegaMMR (required for the wallet gateway)
#   parlons.node.rootnode           a Minima peer to discover the chain from
#   parlons.relay.port=9501         Maxima relay cape, public TCP (and UDP STUN on the same port)
#   parlons.relay.peers             mesh bootstrap list: other relays, host:port, comma-separated
#   parlons.relay.blob=1024         media blob shelf in MB (0 = off)
#   parlons.gateway.port/bind       wallet gateway + /nft on loopback, fronted by TLS
#   parlons.node.public             public base URL of the gateway front (NFT URLs, gateway advert)
#   parlons.dex.port/bind/public    DEX relay cape on loopback, announced as its TLS URL
ExecStart=/usr/bin/java -Xmx3g \
    -Dparlons.node.data=/var/lib/parlons-node \
    -Dparlons.node.port=9001 \
    -Dparlons.node.rpc=true \
    -Dparlons.node.megammr=true \
    -Dparlons.node.rootnode=seed-peer.example.net:9001 \
    -Dparlons.relay.port=9501 \
    -Dparlons.relay.peers=peer1.example.net:9501,peer2.example.net:9501,peer3.example.net:9501 \
    -Dparlons.relay.blob=1024 \
    -Dparlons.gateway.port=9585 \
    -Dparlons.gateway.bind=127.0.0.1 \
    -Dparlons.node.public=https://node.example.com/parlons-node \
    -Dparlons.dex.port=9602 \
    -Dparlons.dex.bind=127.0.0.1 \
    -Dparlons.dex.public=https://node.example.com/dex-relay \
    "-Dparlons.node.args=" \
    -jar /opt/maxima/parlons-node.jar

# Restart on a crash. Exit code 3 means "restart me": a wallet resync or an identity import
# requested from a paired device ends with exit 3, and the node comes back on the same identity.
# always, not on-failure: `quit` and a megammr import/resync end with exit 0, and the node must come back.
# The deploy script writes Restart=always. Older units may say on-failure: change them.
Restart=always
RestartSec=10
RestartForceExitStatus=3
SuccessExitStatus=3

# Filesystem: the node gets write access to its data directory and nothing else.
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
# ProtectHome makes /home and /root unreadable: keep passphrase files under /var/lib/parlons-node or /etc.
ProtectHome=true
ReadWritePaths=/var/lib/parlons-node
UMask=0077
PrivateDevices=true
ProtectProc=invisible
ProcSubset=pid
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectKernelLogs=true
ProtectControlGroups=true
ProtectClock=true
ProtectHostname=true
RemoveIPC=true

# Privileges: no capabilities at all.
CapabilityBoundingSet=
AmbientCapabilities=
RestrictSUIDSGID=true
RestrictNamespaces=true
RestrictRealtime=true
LockPersonality=true

# Syscalls: seccomp allow-list for a network service.
SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallFilter=~@privileged ~@resources ~@obsolete
SystemCallErrorNumber=EPERM

# Network: block cloud metadata and link-local addresses.
# With --keets, add AF_NETLINK here (the Node.js sidecar needs it for interface discovery).
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
IPAddressDeny=169.254.0.0/16 fe80::/10

# Resource ceilings: MemoryMax sits ABOVE -Xmx (heap + 512M).
MemoryMax=3584M
TasksMax=1024
LimitNOFILE=65536

# Logs go to the journal. The node never prints the seed to stdout.
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Примечания:

Как изменить юнит

  1. Сохраните резервную копию текущего юнита:
    cp /etc/systemd/system/parlons-node.service /etc/systemd/system/parlons-node.service.before-<what>
  2. Отредактируйте его:
    nano /etc/systemd/system/parlons-node.service
  3. Проверьте юнит на ошибки:
    systemd-analyze verify /etc/systemd/system/parlons-node.service
  4. Загрузите его и перезапустите узел:
    systemctl daemon-reload
    systemctl restart parlons-node
  5. Подождите около 25 с, затем убедитесь, что узел работает, и прочитайте строку запуска:
    systemctl is-active parlons-node
    journalctl -u parlons-node --since -40s --no-pager | grep -E 'Parlons Node|minima flags|REFUSING' | grep -v seed
  6. Если узел не поднимается, верните резервную копию и повторите шаг 4:
    cp /etc/systemd/system/parlons-node.service.before-<what> /etc/systemd/system/parlons-node.service

Как перевести старый юнит на Restart=always

  1. Посмотрите, что указано в юните:
    grep -n '^Restart=' /etc/systemd/system/parlons-node.service
  2. Если выводится Restart=on-failure, измените это:
    cp /etc/systemd/system/parlons-node.service /etc/systemd/system/parlons-node.service.before-restart-always
    sed -i 's/^Restart=on-failure$/Restart=always/' /etc/systemd/system/parlons-node.service
    systemctl daemon-reload

    Новая настройка вступает в силу сразу, перезапуск не нужен.


8Справочник по настройкам: все свойства

Все свойства — это системные свойства JVM (-Dname=value), указываемые перед -jar. Этот список составлен поиском (grep) всех вызовов System.getProperty, Integer.getInteger, Long.getLong и getenv в модулях, упакованных в jar-файл.

Как изменить настройку

  1. Найдите свойство в таблицах ниже.
  2. Добавьте или измените его строку -D… в ExecStart юнита перед -jar и перезапустите узел (§7, «Как изменить юнит»). Если вы развёртывали узел скриптом, можно вместо этого запустить скрипт повторно с соответствующим флагом (§5); он перезаписывает юнит по своим флагам.
  3. Убедитесь, что узел применил настройку. Строка запуска показывает порты, а строка minima flags: — собственные флаги Minima:
    journalctl -u parlons-node -b --no-pager | grep -E 'Parlons Node|minima flags' | grep -v seed

Как передать собственные флаги Minima в conf-файле

Используйте этот способ для секретов, например mdspassword, чтобы они никогда не появлялись в командной строке.

  1. Запишите файл, по одной паре key=value в строке. Строка из одного key — логический флаг. Ведущий - не пишите:
    cat > /var/lib/parlons-node/minima.conf <<'EOF'
    mdspassword=<your MDS password>
    EOF
    chown maxima:maxima /var/lib/parlons-node/minima.conf
    chmod 600 /var/lib/parlons-node/minima.conf
  2. Добавьте -Dparlons.node.conf=/var/lib/parlons-node/minima.conf в юнит и перезапустите узел (§7).
  3. Проверьте строку minima flags: в журнале. Значение mdspassword там скрыто.

8.1 Узел и цепочка

СвойствоЗначениеПо умолчаниюПример
parlons.node.dataКаталог данных. Приоритет: это свойство, затем -data Minima (его родительский каталог), затем ~/.parlons-node.~/.parlons-node/var/lib/parlons-node
parlons.node.portP2P-порт Minima (публичный). Производные порты идут от него: файлы MDS +2, команды MDS +3, административный RPC +4.9001 (значение Minima по умолчанию, если в аргументах нет -port)9101
parlons.node.rootnodeПир Minima (host:port), через который узел находит цепочку. В этом форке список пиров по умолчанию пустой, поэтому без этого свойства (или connect) узел запускается, но никогда не синхронизируется.пустоseed-peer.example.net:9001
parlons.node.connectФиксированный список пиров. Если его задать, поиск пиров по P2P отключается: только статические пиры.пустоa.example.net:9001,b.example.net:9001
parlons.node.megammrХранить полный MegaMMR, чтобы coins/balance megammr:true address:<any> работали для любого адреса. Он нужен шлюзу кошелька. Приоритет: это свойство, затем -megammr Minima, затем true.truefalse
parlons.node.rpcЗапустить административный RPC на loopback 127.0.0.1:<p2p+4>. Если он не может занять порт, узел завершается с кодом 2.falsetrue
parlons.node.argsСобственные флаги запуска Minima, обрабатываемые собственным парсером Minima. Некоторые флаги отвергаются (см. 8.8). Резервная переменная окружения: PARLONS_NODE_ARGS.пусто"-host 203.0.113.10 -archive"
parlons.node.confФайл key=value с флагами Minima, который читается до parlons.node.args. Именно здесь место секретам вроде mdspassword — в файле с правами 600. Строка из одного key — логический флаг.пусто/var/lib/parlons-node/minima.conf
parlons.node.passphrase.fileФайл с парольной фразой узла, защищённого паролем. Узел пытается разблокироваться один раз при запуске. Альтернатива через окружение: PARLONS_NODE_PASSPHRASE. Парольная фраза не должна содержать пробельных символов, " или ;.пусто/var/lib/parlons-node/passphrase.txt
parlons.node.archiveАрхивный хост / хост MegaMMR, используемый при пересинхронизации кошелька, запрошенной с подключённого устройства (megammrsync action:resync host:<this>).встроенный в код архивный узел проекта (см. NodeAccountWallet.java)archive.example.net:9001
parlons.node.selftest.sendТолько для тестов разработчика. При запуске отправляет <address>[,<amount>] с кошелька узла (сумма по умолчанию 0.001). На узле со средствами это отправляет реальные средства. Никогда не задавайте его в рабочей среде.пусто—

8.2 Кейп ретранслятора (Maxima)

СвойствоЗначениеПо умолчаниюПример
parlons.relay.portПорт ретранслятора. Число даёт ретранслятору собственный слушающий порт. 0 выключает ретранслятор (тогда аккаунт использует ретрансляторы парка). shared заставляет ретранслятор делить P2P-порт Minima: узел передаёт ретранслятору каждое подключение, которое представляется как клиент Parlons, так что публичный порт один.95018001, 0, shared
parlons.relay.hostПубличное имя хоста или IP ретранслятора. Если не задано, узел использует публичный адрес, который он узнал от своих пиров, и продолжает его перепроверять (каждые 30 с в первые 30 минут, пока адрес не найден, затем каждые 10 минут, так что изменившийся динамический IP отслеживается). Частные, loopback- и CGNAT-адреса никогда не используются.определяется автоматическиnode.example.com
parlons.relay.peersНачальный список mesh-сети (host:port через запятую). Если не задан, используется встроенный в код список Bootstrap.RELAYS. Аккаунт также использует их как пиров mesh-сети.встроенный списокpeer1.example.net:9501,peer2.example.net:8001
parlons.relay.blobРазмер хранилища медиаблобов в МБ (там хранятся фотографии пользователей). 0 = выключено.01024
parlons.relay.maxconnМаксимальное число подключений, которые держит ретранслятор. 0 оставляет встроенное значение по умолчанию: 512 на платформенных потоках, 4096 на виртуальных потоках (JDK 21+).08192

Свойства уровня ретранслятора из RelayServer (они действуют и внутри узла):

СвойствоЗначениеПо умолчанию
maxima.relay.maxpersourceМаксимум одновременных подключений с одного IP-адреса источника (домохозяйство за NAT считается одним источником).32
maxima.relay.shedМягкий целевой предел числа клиентов. Выше него ретранслятор за каждый такт просит до 4 клиентов перейти в другое место. 0 = никогда не просить.384
maxima.relay.replicateСколько случайных проверенных пиров пула получают копию каждой подписанной записи каталога. 0 = выключено.3
maxima.relay.vthreadsИспользовать виртуальные потоки, если они есть в JDK. false принудительно включает платформенные потоки.true
maxima.pow.enforceОтклонять сообщения без минимального доказательства работы (proof-of-work), требуемого протоколом. При false они только подсчитываются. Окружение: MAXIMA_POW_ENFORCE=true.false
maxima.mls.openЗначение по умолчанию для открытого разрешения в пуле. На узел не влияет: узел всегда включает режим пула.—

Зафиксировано в коде (не настраивается): протокол 1.0.48; лимит скорости ретранслятора 600 сообщений в минуту на одного получателя.

Окружение: MAXIMA_STUN=false отключает UDP STUN-ответчик на порту ретранслятора.

8.3 Шлюз кошелька и NFT

СвойствоЗначениеПо умолчаниюПример
parlons.gateway.portПорт шлюза кошелька (/cmd) и NFT-сервера (/nft).95859585
parlons.gateway.bindИнтерфейс, на котором слушает шлюз. Держите его на loopback за TLS.127.0.0.1127.0.0.1
parlons.gateway.tokenBearer-токен. Если не задан, узел читает <data>/gateway-token.txt или создаёт там 256-битный токен (права 600).из файла—
parlons.gateway.threadsПотоки-обработчики. Каждый блокируется на одну команду узла.816
parlons.gateway.rate.globalОбщая частота запросов /cmd (запросов/с; всплеск = запас на 2 с). 0 = выключено.50100
parlons.gateway.rate.peripЧастота /cmd на один IP. Имеет смысл, только если шлюз открыт напрямую: за прокси каждый запрос приходит с 127.0.0.1.100
parlons.gateway.rate.nft.globalОбщая частота /nft.400—
parlons.gateway.rate.nft.peripЧастота /nft на один IP.40—
parlons.node.publicПубличный базовый URL TLS-прокси шлюза, без /cmd. Он задаёт URL файлов NFT. На узле MegaMMR с включённым ретранслятором он также объявляет шлюз телефонам в приветствии ретранслятора.пустоhttps://node.example.com/parlons-node

8.4 DEX-кейп ретранслятора

СвойствоЗначениеПо умолчаниюПример
parlons.dex.portПорт DEX-кейпа ретранслятора. 0 = выключено.09602
49737 (parlons.keets.dhtport, только fleet-jar)UDPузел начальной загрузки keets HyperDHTвсеПубличный. Откройте его в файрволе.
p2p+5 (9006, с -keets)TCP/HTTPloopback-API keets (токен в <data>/keets/apitoken)127.0.0.1, жёстко заданоНикогда не открывать наружу.
parlons.dex.bindИнтерфейс, на котором он слушает. Явно заданное значение имеет приоритет. Если не задано, кейп слушает 127.0.0.1, когда задан parlons.dex.public, иначе 0.0.0.0. Держите его на loopback и ставьте перед ним TLS-прокси.127.0.0.1 с parlons.dex.public, иначе 0.0.0.0127.0.0.1
parlons.dex.publicПубличный базовый URL, объявляемый в mesh-сети. Если не задан, узел объявляет http://<public host>:<port>, как только узнаёт свой публичный хост.пустоhttps://node.example.com/dex-relay

Зафиксировано в коде: версия DEX-ретранслятора 0.1.5; общая частота 200 запросов/с и частота на один IP 20 запросов/с (что это означает за прокси, см. в §16).

8.5 Аккаунт и панель

СвойствоЗначениеПо умолчаниюПример
parlons.accountЗапускать аккаунт Parlons. false = узел только с ретранслятором и шлюзом.truefalse
parlons.account.nameОтображаемое имя (используется только при первом запуске).пустоExample Node
parlons.account.relaysДополнительные ретрансляторы, к которым подключается аккаунт (csv).пустоpeer1.example.net:9501
parlons.account.builtinfalse = не брать начальные ретрансляторы из встроенного в код списка. Тогда аккаунт начинает с account.relays и запомненных им ретрансляторов.truefalse
parlons.account.directПорт прямого (Tier-2) слушателя аккаунта. 0 = выключено.0—
parlons.panel.portЛокальная веб-панель и JSON API, только на 127.0.0.1. 0 = выключено.95870
parlons.hosted.dirКаталог размещённых (гостевых) аккаунтов. Окружение: PARLONS_HOSTED_DIR. Если не задан, узел включает управляемое размещение для работы с отдельной службой tenants.не задано/var/lib/parlons-tenants
parlons.hosted.limitМаксимальное число размещённых аккаунтов.10—
parlons.restoreВосстановить переносимый пакет аккаунта (.pbk) в чистый каталог данных и завершить работу. Для ввода парольной фразы нужна интерактивная консоль.пусто/root/backup.pbk

8.6 MDS и keets

СвойствоЗначениеПо умолчаниюПример
parlons.mdsРаздавать MDS (MiniHUB и MiniDapps) по адресу https://<bind>:<p2p+2>/. То же, что -mdsenable в Minima.выключеноtrue
parlons.mds.bindИнтерфейс, на котором слушает MDS. Приоритет: это свойство, затем -mdsbind Minima, затем 127.0.0.1. 0.0.0.0 или * означает все интерфейсы.127.0.0.1127.0.0.1
parlons.node.keetschatoff/false/0/no передаёт входящие keets приложению-хосту, и мост не запускается.onoff

8.7 Переменные окружения

ПеременнаяЗначение
PARLONS_NODE_ARGSРезервный вариант для parlons.node.args.
PARLONS_NODE_PASSPHRASEПарольная фраза для заблокированного узла (используйте EnvironmentFile с правами 600).
PARLONS_HOSTED_DIRРезервный вариант для parlons.hosted.dir.
MAXIMA_STUNfalse отключает UDP STUN-ответчик.
MAXIMA_POW_ENFORCEtrue включает обязательный минимум доказательства работы.

8.8 Флаги Minima, которые узел отвергает

Флаги из parlons.node.args или parlons.node.conf передаются собственному парсеру Minima, кроме перечисленных ниже. Узел выводит причину и завершается с кодом 2, прежде чем коснуться каталога данных. Неизвестный флаг тоже приводит к завершению с кодом 2.

ФлагиПочемуЧто использовать вместо них
-rpc -rpcenable -rpcpassword -rpccrlfСтандартный RPC слушает все интерфейсы с полными правами администратора.-Dparlons.node.rpc=true (только loopback)
-seed -anyseed -dbpasswordСекрет в argv может прочитать любой процесс (ps).--seed-from / --passphrase-file
-clean -genesis -test -solo -testchainlengthОни стирают каталог данных или уводят узел из основной сети.—
-daemon -noshutdownhook -jnlp -helpJVM узла сама управляет stdin, завершением и обработчиком выключения.—

Явно заданные свойства -Dparlons.node.* применяются после флагов Minima и имеют приоритет при конфликте. Журнал запуска показывает применённые флаги как minima flags: …, значение mdspassword при этом скрыто.

8.9 Коды завершения

КодЗначение
0Штатная остановка: quit через административный RPC или встроенный узел сам завершился после пересинхронизации, восстановления или сброса.
2Отказ запуска: неизвестный аргумент командной строки, отвергнутый или неизвестный флаг Minima, нечитаемый файл -conf или административный RPC не смог занять порт.
3Запрошен перезапуск: пересинхронизация кошелька или импорт личности с подключённого устройства. systemd должен перезапустить узел (RestartForceExitStatus=3).

9Порты

Порт (по умолчанию)ПротоколЧтоАдрес привязкиДоступность
9001 (parlons.node.port)TCPP2P MinimaвсеПубличный. Откройте его в файрволе.
p2p+2 (9003)TCP/HTTPSФайловый сервер MDS / MiniHUB (только при parlons.mds=true)127.0.0.1Loopback. Никогда не делайте публичным без собственного TLS и файрвола.
p2p+3 (9004)TCPПорт команд MDS (только при включённом MDS)как у MDSLoopback.
p2p+4 (9005)TCP/HTTPАдминистративный RPC (только при parlons.node.rpc=true)127.0.0.1, жёстко задано в кодеНикогда не открывайте наружу. Никогда не проксируйте.
9501 (parlons.relay.port)TCPКейп ретранслятора MaximaвсеПубличный. Сюда подключаются телефоны и пиры mesh-сети.
9501UDPSTUN-ответчик на порту ретрансляторавсеНеобязательно. Скрипт развёртывания UDP не открывает.
9585 (parlons.gateway.port)TCP/HTTPШлюз кошелька /cmd и /nft127.0.0.1Loopback, за TLS-прокси по пути /parlons-node/.
9587 (parlons.panel.port)TCP/HTTPПанель и API аккаунта127.0.0.1, жёстко задано в кодеLoopback. Подключайтесь через SSH-туннель.
9602 (parlons.dex.port, по умолчанию выключен)TCP/HTTPDEX-кейп ретранслятора127.0.0.1, если задан parlons.dex.public, иначе 0.0.0.0; parlons.dex.bind переопределяетLoopback, за TLS-прокси по пути /dex-relay/.

Конфликты портов, о которых нужно знать:

Как перенести узел с порта 9001

Используйте это, когда на сервере уже работает обычный узел Minima.

  1. Выберите свободный базовый порт, например 9101. Убедитесь, что он и следующие четыре свободны:
    ss -ltnp | grep -E ':(9101|9103|9104|9105) '
  2. Задайте -Dparlons.node.port=9101 в юните и перезапустите узел (§7). Со скриптом развёртывания вместо этого укажите --p2p-port 9101.
  3. Откройте новый P2P-порт:
    ufw allow 9101/tcp
  4. Используйте новый порт административного RPC (9105) во всех командах curl в этом руководстве.

Как посмотреть, какие порты занимает узел

ss -ltnp | grep java
ss -lunp | grep java

Первая команда выводит слушающие TCP-сокеты и их адреса привязки; вторая — UDP STUN-ответчик.


10Структура каталога данных

Все пути указаны относительно parlons.node.data (по умолчанию в скрипте развёртывания — /var/lib/parlons-node). Каталог и каждый секретный файл должны принадлежать служебному пользователю и быть доступны только ему.

ПутьЧтоСекрет?
<base version>/Собственные данные узла Minima: базы данных, кошелёк, цепочка. Файл MegaMMR — <base version>/databases/megammr.mmr (скрипт развёртывания использует путь 1.1/databases/megammr.mmr).Да. Здесь хранится кошелёк.
identity.txtЗакреплённая фраза личности (или seed в hex), из которой выводится личность Maxima. Права 600.Да. Это сид.
identity-anyphrase.txtПроизвольная (не BIP39) фраза личности, если она была импортирована.Да.
gateway-token.txtBearer-токен шлюза кошелька. Права 600.Низкая важность (только чтение и рассылка, к тому же объявляется телефонам; см. §14).
pair-code.txtТекущий неиспользованный одноразовый код подключения.Да, пока он не использован.
account.txtПостоянный адрес аккаунта (MAX#…).Нет.
invite.txtАдрес плюс одноразовый код.Да, пока код не использован.
panel-ticket.txtОдноразовая ссылка для входа в локальную панель.Да.
local-device.keyКлюч локального устройства панели. Удалите его и перезапустите узел, чтобы снова включить отозванную панель.Да.
devices.jsonПодключённые устройства.Частное.
cloud-settings.propertiesНастройки аккаунта.Частное.
node/, chat/, media/, private-files/Хранилище аккаунта, история чатов, медиафайлы.Частное.
relay/Состояние ретранслятора: каталог, элементы почтовых ящиков, хранилище блобов.Частное.
nft/Размещённые файлы NFT (<sha256>.<ext>, c/<16-hex>/…) плюс tmp/ для загрузок в процессе.Публичный контент.
account-history/<import-id>/previous/Предыдущая личность после импорта личности.Да.
.seed-adoptedМетка, которую записывает --seed-from скрипта развёртывания.Нет.

Как проверить права доступа к каталогу данных

  1. Выведите владельца и права каталога и секретных файлов:
    ls -ld /var/lib/parlons-node
    ls -l /var/lib/parlons-node/*.txt
  2. У каталога должно быть drwx------ maxima maxima, а у каждого секретного .txt — -rw------- maxima maxima. Если это не так, исправьте:
    chown -R maxima:maxima /var/lib/parlons-node
    chmod 700 /var/lib/parlons-node
    chmod 600 /var/lib/parlons-node/*.txt

11TLS-прокси: Caddy, nginx, Apache

Шлюз (9585) и DEX-кейп (9602) работают по обычному HTTP на loopback. Веб-сервер на том же сервере завершает TLS и перенаправляет эти два пути:

Публичный путьКуда перенаправлятьПрефикс
https://node.example.com/parlons-node/…http://127.0.0.1:9585/…убрать /parlons-node (тогда /parlons-node/cmd попадает на /cmd, а /parlons-node/nft/… — на /nft/…)
https://node.example.com/dex-relay/…http://127.0.0.1:9602/…убрать /dex-relay (тогда /dex-relay/dex/health попадает на /dex/health)

Затем задайте в parlons.node.public и parlons.dex.public публичные URL (шаг 4 ниже).

Никогда не перенаправляйте административный RPC (p2p+4), панель (9587) или MDS.

Важные размеры и тайм-ауты:

Как настроить любой TLS-прокси

  1. Направьте DNS-имя (здесь node.example.com) на сервер и откройте TCP 443 (и 80 для проверки при получении сертификата):
    ufw allow 80/tcp
    ufw allow 443/tcp
  2. Убедитесь, что две HTTP-службы узла отвечают на loopback (DEX — только если вы его включили):
    curl -s -o /dev/null -w '%{http_code}\n' -X POST http://127.0.0.1:9585/cmd   # 401 = gateway up
    curl -s http://127.0.0.1:9602/dex/health
  3. Настройте Caddy, nginx или Apache по шагам ниже.
  4. Задайте публичные URL в юните и перезапустите узел (§7):
    -Dparlons.node.public=https://node.example.com/parlons-node
    -Dparlons.dex.public=https://node.example.com/dex-relay
  5. Проверьте с другой машины:
    curl -s https://node.example.com/dex-relay/dex/health
    curl -s -o /dev/null -w '%{http_code}\n' -X POST https://node.example.com/parlons-node/cmd   # 401

Caddy

Caddy сам получает и продлевает сертификат.

Как поставить Caddy перед узлом

  1. Установите Caddy из официальных пакетов (https://caddyserver.com/docs/install).
  2. Сохраните резервную копию Caddyfile:
    cp /etc/caddy/Caddyfile /etc/caddy/Caddyfile.before-parlons-node
  3. Добавьте эти блоки в блок сайта для вашего имени хоста в /etc/caddy/Caddyfile:
    node.example.com {
        # DEX relay cape: use `handle` + `uri strip_prefix`, NOT `handle_path` (see the trap below).
        handle /dex-relay/* {
            uri strip_prefix /dex-relay
            reverse_proxy 127.0.0.1:9602
        }
    
        # Wallet gateway + NFT files.
        handle /parlons-node/* {
            uri strip_prefix /parlons-node
            reverse_proxy 127.0.0.1:9585
        }
    
        # Your site's catch-all (if any) goes LAST.
        handle {
            root * /var/www/html
            file_server
        }
    }
  4. Проверьте файл, затем перезагрузите Caddy:
    caddy validate --config /etc/caddy/Caddyfile
    systemctl reload caddy
  5. Проверьте с другой машины (шаг 5 из раздела «Как настроить любой TLS-прокси»). Если /dex-relay/dex/health возвращает вашу веб-страницу вместо JSON, вы попали в ловушку, описанную ниже.

reverse_proxy в Caddy по умолчанию отправляет X-Forwarded-For, поэтому DEX-кейп ограничивает частоту для каждого клиента отдельно.

Ловушка порядка в Caddy: handle_path и handle. Перед применением Caddy сортирует директивы в фиксированном порядке, и handle идёт раньше handle_path. Среди блоков handle более конкретные сопоставления путей идут первыми, а handle без сопоставления — последним. Блоки handle взаимоисключающие: срабатывает первый подходящий. Поэтому, если в блоке сайта есть универсальный handle { … }, handle_path /dex-relay/* оказывается после него и никогда не срабатывает: на каждый запрос DEX отвечает универсальный блок. Решение: напишите handle /dex-relay/* { uri strip_prefix /dex-relay; reverse_proxy … }, который сортируется вместе с другими блоками handle по пути. В блоке сайта без универсального handle вариант handle_path /dex-relay/* работает.

Как добавить ограничение частоты для каждого клиента в Caddy (необязательно)

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

  1. Соберите или скачайте бинарный файл Caddy с модулем rate_limit.
  2. Замените блок шлюза на:
        handle /parlons-node/* {
            rate_limit {
                zone phones {
                    key    {remote_host}
                    events 60
                    window 1m
                }
            }
            uri strip_prefix /parlons-node
            reverse_proxy 127.0.0.1:9585
        }
  3. Проверьте и перезагрузите, как в шагах 4 и 5 выше.

nginx

Как поставить nginx перед узлом

  1. Получите сертификат для имени хоста (например, с помощью certbot) и подготовьте для него блок server { listen 443 ssl; server_name node.example.com; … }.
  2. Сохраните резервную копию файла сайта, который собираетесь менять:
    cp /etc/nginx/sites-available/<your site> /etc/nginx/sites-available/<your site>.before-parlons-node

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

  3. Добавьте эти блоки внутрь блока server { … }:
    # DEX relay cape. The trailing slashes strip the prefix.
    location /dex-relay/ {
        proxy_pass http://127.0.0.1:9602/;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_read_timeout 60s;
    }
    
    # Wallet gateway + NFT files.
    location /parlons-node/ {
        proxy_pass http://127.0.0.1:9585/;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        client_max_body_size 2m;
    }
  4. Проверьте конфигурацию, затем перезагрузите nginx:
    nginx -t
    systemctl reload nginx
  5. Проверьте с другой машины (шаг 5 из раздела «Как настроить любой TLS-прокси»).

Примечания:

Apache

Как поставить Apache перед узлом

  1. Подготовьте виртуальный хост с TLS (<VirtualHost *:443>) для имени хоста, например с помощью certbot.
  2. Включите модули прокси:
    a2enmod proxy proxy_http
  3. Поместите это во фрагмент, подключаемый из виртуального хоста с TLS:
    # DEX relay cape
    ProxyPass        /dex-relay/ http://127.0.0.1:9602/
    ProxyPassReverse /dex-relay/ http://127.0.0.1:9602/
    
    # Wallet gateway (POST /cmd) and NFT files (GET/HEAD /nft/...)
    <Location "/parlons-node/cmd">
        ProxyPass        http://127.0.0.1:9585/cmd
        ProxyPassReverse http://127.0.0.1:9585/cmd
    </Location>
    <Location "/parlons-node/nft">
        ProxyPass        http://127.0.0.1:9585/nft
        ProxyPassReverse http://127.0.0.1:9585/nft
    </Location>
  4. Проверьте конфигурацию, затем перезагрузите Apache:
    apachectl configtest
    systemctl reload apache2
  5. Проверьте с другой машины (шаг 5 из раздела «Как настроить любой TLS-прокси»).

ProxyPass в Apache по умолчанию отправляет X-Forwarded-For. Для шлюза за Apache ограничением частоты служат собственные общие лимиты (token buckets) узла.


12Кейп ретранслятора и mesh-сеть

Что делает кейп

Кейп — это полноценный ретранслятор Maxima. В сети он говорит на классическом протоколе Maxima, байт в байт, плюс расширения Parlons: почтовый ящик с хранением и пересылкой, каталог, квитанции о доставке, gossip-обмен и mesh-сеть. У телефона нет публичного адреса, поэтому он сам подключается к кейпу и держит соединение открытым; сообщения для него приходят обратно по этому соединению. Обычный узел Minima тоже может использовать кейп как свой хост Maxima.

Кейп всегда работает как хост пула: хост каталога с открытым разрешением адресов и пересылающий узел mesh-сети.

Личность

Личность кейпа (Mx…) выводится из identity.txt, который закрепляется из сид-фразы узла при первом запуске. Сервер, на котором раньше работал maxima-server.jar, может сохранить личность своего ретранслятора: флаг скрипта развёртывания --seed-from /var/lib/maxima/seed.txt пересинхронизирует кошелёк узла на эту фразу и закрепляет её.

Публичный хост

Кейп должен знать свой публичный адрес. Этим адресом он называет себя в списках пиров, исключает себя из собственной пересылки, привязывает к нему постоянный адрес аккаунта и строит объявляемый DEX URL. Адрес ищется в таком порядке:

  1. -Dparlons.relay.host, если вы его задали.
  2. Иначе — публичный адрес, который узел Minima узнал от своих пиров (network → details.p2p.address), затем status → network.host.
  3. Если ни один из них ещё не публичный, фоновый поток перепроверяет каждые 30 с в первые 30 минут, затем каждые 10 минут. Найдя адрес, он пишет в журнал public address learned from peers: <ip> - the cape now names itself <ip>:<port>.

Никогда не задавайте хостом ретранслятора адрес привязки вроде 0.0.0.0. Классическая Minima считает адреса 0.x внутренними и отвергает весь ретранслятор.

Gossip-обмен и проверенные пиры

Из core/.../session/RelayPeers.java:

Mesh-сеть и parlons.relay.peers

Ёмкость

Режим общего порта

При -Dparlons.relay.port=shared у ретранслятора нет собственного слушающего порта. P2P-слушатель Minima передаёт ему каждое подключение, которое представляется как клиент Parlons. Тогда один публичный порт обслуживает и цепочку, и ретранслятор. Настольные приложения используют этот режим, когда включено «contribute» (участие в сети). Серверы парка держат явно заданный 9501.

Как проверить, что кейп работает

  1. Найдите строки кейпа и mesh-сети в журнале текущего запуска:
    journalctl -u parlons-node -b --no-pager | grep -E 'Maxima cape|mesh:|public address learned|own relay' | grep -v seed

    Нужны строки Maxima cape up on port 9501 — identity Mx… и mesh: N bootstrap peer(s).

  2. Проверьте heartbeat. В нём должно быть cape=up:9501:
    journalctl -u parlons-node --since -2min --no-pager | grep heartbeat | tail -1
  3. Проверьте всю цепочку целиком с другой машины (§23, шаг 2).

Как задать начальных пиров mesh-сети

  1. Соберите host:port каждого ретранслятора, до которого хотите достучаться. Указывайте порт, на котором каждый ретранслятор действительно слушает.
  2. Задайте их одним значением через запятую в юните, затем перезапустите узел (§7):
    -Dparlons.relay.peers=peer1.example.net:9501,peer2.example.net:9501,peer3.example.net:8001

    Со скриптом развёртывания укажите --peers "peer1.example.net:9501,peer2.example.net:9501".

  3. Если сервер по умолчанию блокирует исходящий трафик, разрешите порт ретранслятора каждого пира (§25).
  4. Проверьте журнал запуска. В нём должно быть mesh: N bootstrap peer(s) с вашим количеством:
    journalctl -u parlons-node -b --no-pager | grep 'mesh:'

Как задать публичный хост

Сделайте это, когда в журнале есть own relay NOT advertised или когда у сервера есть постоянное имя, которое вы хотите дать кейпу.

  1. Добавьте публичное имя хоста или IP в юнит, затем перезапустите узел (§7):
    -Dparlons.relay.host=node.example.com

    Никогда не используйте адрес привязки вроде 0.0.0.0, а также частный, loopback- или CGNAT-адрес.

  2. Убедитесь, что предупреждение исчезло:
    journalctl -u parlons-node -b --no-pager | grep -E 'own relay NOT advertised' || echo advertised-ok

Как запустить ретранслятор на P2P-порту Minima (режим общего порта)

  1. Задайте в юните порт ретранслятора shared, затем перезапустите узел (§7):
    -Dparlons.relay.port=shared
  2. Откройте (или пробросьте) только P2P-порт, например 9001. Удалите правило для 9501, если оно больше не нужно:
    ufw delete allow 9501/tcp
  3. Сообщите своим пользователям и пирам mesh-сети, что адрес этого ретранслятора — node.example.com:9001.

Как включить хранилище медиаблобов

  1. Задайте в юните размер хранилища в МБ, затем перезапустите узел (§7). Со скриптом развёртывания укажите --blobstore 1024:
    -Dparlons.relay.blob=1024
  2. Убедитесь, что на диске свободно столько места (df -h /var/lib).
  3. Проверьте журнал запуска. В нём должно быть blob shelf: 1024 MB:
    journalctl -u parlons-node -b --no-pager | grep 'blob shelf'

Как поднять лимит подключений

  1. Запустите узел на JDK 21 или новее. Тогда лимит сам вырастет до 4096.
  2. Чтобы задать свой лимит, добавьте его в юнит и перезапустите узел (§7):
    -Dparlons.relay.maxconn=8192
  3. Если лимит приближается к LimitNOFILE, поднимите и его в юните (юнит задаёт 65536).

Как выключить ретранслятор

Задайте в юните -Dparlons.relay.port=0 и перезапустите узел. Тогда аккаунт использует другие ретрансляторы. Закройте порт ретранслятора в файрволе.


13Режим MegaMMR и корневой узел (rootnode)

Корневой узел (rootnode)

В этом форке узла список пиров по умолчанию пустой. Укажите ему одно из следующего:

Без одного из них узел запускается и обслуживает свои локальные службы, но block= никогда не растёт.

Как задать корневой узел

  1. Выведите корневой узел, рекомендуемый проектом, или выберите узел Minima, которому доверяете:
    java -jar /opt/maxima/parlons-node.jar --help | grep -i rootnode
  2. Убедитесь, что сервер может до него достучаться (замените хост и порт):
    nc -z -w 8 seed-peer.example.net 9001 && echo reachable
  3. Добавьте его в юнит, затем перезапустите узел (§7). Со скриптом развёртывания укажите --rootnode seed-peer.example.net:9001:
    -Dparlons.node.rootnode=seed-peer.example.net:9001
  4. Следите, как растёт block= в heartbeat:
    journalctl -u parlons-node -f | grep heartbeat

MegaMMR

На узле MegaMMR включён по умолчанию; в самой Minima по умолчанию он выключен. С MegaMMR узел может доказывать монеты для любого адреса (coins/balance megammr:true address:<any>). Именно это делает его шлюзом кошелька для телефонов.

Начальная синхронизация не заполняет MegaMMR. MegaMMR только что синхронизированного узла пуст (около 20 байт) и отслеживает только монеты, созданные с этого момента. Пока вы не импортируете снимок, балансы существующих адресов возвращаются пустыми.

Как импортировать снимок MegaMMR

Сделайте это один раз, после первой синхронизации. Выполняйте команды на сервере от имени root.

  1. Убедитесь, что административный RPC включён (-Dparlons.node.rpc=true, §21). Эта команда должна вывести статус в JSON:
    curl -s http://127.0.0.1:9005/status | head -c 200; echo
  2. Проверьте текущий размер MegaMMR. Меньше 1 МБ означает, что он пуст:
    stat -c %s /var/lib/parlons-node/1.1/databases/megammr.mmr
  3. Скачайте снимок в каталог данных и передайте его служебному пользователю (около 460 МБ; -c продолжает прерванную загрузку):
    cd /var/lib/parlons-node
    wget -c -O mega.mmr https://eurobuddha.com/mega.mmr
    chown maxima:maxima mega.mmr

    Чтобы использовать собственный снимок, см. следующую процедуру.

  4. Импортируйте его через loopback RPC (P2P-порт 9001 означает RPC 9005):
    curl -s -m 3600 'http://127.0.0.1:9005/megammr%20action:import%20file:/var/lib/parlons-node/mega.mmr'

    Ответ должен содержать "status":true. Импорт заканчивается выключением узла.

  5. Верните узел. Restart=always перезапускает его через 10 с; для надёжности выполните:
    systemctl restart parlons-node
  6. Подождите около 20 с, затем убедитесь, что megammr.mmr теперь больше 1 МБ:
    stat -c %s /var/lib/parlons-node/1.1/databases/megammr.mmr
  7. Запросите адрес, на котором точно есть средства. Его баланс не должен быть пустым:
    curl -s 'http://127.0.0.1:9005/balance%20megammr:true%20address:<a funded Mx or 0x address>'
  8. Удалите скачанный файл:
    rm -f /var/lib/parlons-node/mega.mmr

Флаги скрипта развёртывания --rpc --megammr-seed <URL> выполняют все эти шаги и пропускают их, если MegaMMR уже заполнен.

Как сделать собственный снимок

  1. На любом подконтрольном вам узле MegaMMR с включённым административным RPC экспортируйте MegaMMR. Это берёт блокировку на чтение и не требует простоя:
    curl -s -m 3600 'http://127.0.0.1:9005/megammr%20action:export%20file:/var/lib/parlons-node/donor.megammr'
  2. Скопируйте файл в каталог данных нового узла и передайте его служебному пользователю:
    scp /var/lib/parlons-node/donor.megammr root@node.example.com:/var/lib/parlons-node/mega.mmr
    ssh root@node.example.com chown maxima:maxima /var/lib/parlons-node/mega.mmr
  3. Удалите экспорт на узле-доноре, затем выполните импорт на новом узле начиная с шага 4 процедуры выше.

Как запустить узел без MegaMMR

  1. Добавьте -Dparlons.node.megammr=false в юнит (или передайте скрипту развёртывания --no-megammr).
  2. Уменьшите кучу соответственно (768 МБ на сервере с 2 ГБ, §3) и задайте MemoryMax на 512 МБ больше.
  3. Перезапустите узел (§7). Узел больше не сможет быть шлюзом кошелька для других адресов.

Если вы также принимаете сид-фразу, порядок важен: выполните --seed-from до импорта MegaMMR. megammrsync сбрасывает базы данных цепочки и выбрасывает импортированный MegaMMR.

Узел с megammr=false не может обслуживать чтения megammr:true. Его шлюз отвечает на такие запросы HTTP 503 (this node has no MegaMMR - use a MegaMMR gateway node), и телефоны переключаются на другой шлюз.


14Шлюз кошелька и его токен

Контракт

POST /cmd
Authorization: Bearer <token>
Content-Type: application/json

{"command":"balance megammr:true address:Mx..."}

Ответ — это собственный JSON узла. Ошибки возвращаются как {"status":false,"error":"…"} с такими HTTP-кодами:

КодЗначение
400некорректное тело JSON или пустая команда
401bearer-токен отсутствует или неверен
403команды нет в списке разрешённых или coins/balance без address:
405не POST
429превышен лимит частоты (проверяется до аутентификации)
500внутренняя ошибка шлюза (подробности только в журнале узла)
502ответ узла больше 12 МиБ
503megammr:true на узле без MegaMMR

Список разрешённых команд

Проходят только эти команды. Проверяется каждый сегмент, разделённый ;, потому что узел выполняет каждый сегмент как отдельную команду:

Всё остальное отклоняется: send, vault, keys, sign, quit и так далее. coins и balance должны содержать address:, чтобы никто не мог получить через шлюз список собственных монет оператора.

Токен

Лимиты частоты

Как опубликовать шлюз для телефонов

  1. Запустите узел с включённым MegaMMR и импортируйте MegaMMR (§13).
  2. Держите шлюз на loopback (-Dparlons.gateway.bind=127.0.0.1, по умолчанию) и поставьте перед /parlons-node/ TLS-прокси (§11).
  3. Задайте в юните публичный базовый URL без /cmd и перезапустите узел (§7):
    -Dparlons.node.public=https://node.example.com/parlons-node
  4. Убедитесь, что узел его объявляет:
    journalctl -u parlons-node -b --no-pager | grep -E 'wallet gateway (up|advertised|FAILED)'

    Нужна строка wallet gateway advertised to phones: https://node.example.com/parlons-node/cmd.

  5. Проверьте его с другой машины (следующая процедура).

Как проверить шлюз

  1. На сервере прочитайте токен в переменную оболочки. Не вставляйте его в общие чаты или заявки в поддержку:
    TOKEN=$(sudo cat /var/lib/parlons-node/gateway-token.txt)
  2. Отправьте команду block. Она должна вернуть JSON узла с "status":true:
    curl -s -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
         -d '{"command":"block"}' https://node.example.com/parlons-node/cmd
  3. Отправьте её без токена. Должен вернуться HTTP 401:
    curl -s -o /dev/null -w '%{http_code}\n' -H 'Content-Type: application/json' \
         -d '{"command":"block"}' https://node.example.com/parlons-node/cmd
  4. Отправьте запрещённую команду. Должен вернуться HTTP 403:
    curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $TOKEN" \
         -H 'Content-Type: application/json' -d '{"command":"vault"}' \
         https://node.example.com/parlons-node/cmd

Как использовать один токен для нескольких шлюзов

  1. Скопируйте gateway-token.txt с первого сервера на каждый из остальных:
    scp root@node.example.com:/var/lib/parlons-node/gateway-token.txt ./gateway-token.txt
    scp ./gateway-token.txt root@node2.example.com:/var/lib/parlons-node/gateway-token.txt
    rm ./gateway-token.txt
  2. На каждом сервере, получившем его, исправьте владельца и права, затем перезапустите узел:
    chown maxima:maxima /var/lib/parlons-node/gateway-token.txt
    chmod 600 /var/lib/parlons-node/gateway-token.txt
    systemctl restart parlons-node

Как заменить токен

  1. Удалите файл токена и перезапустите узел. При запуске узел запишет новый 256-битный токен:
    rm /var/lib/parlons-node/gateway-token.txt
    systemctl restart parlons-node
  2. Дождитесь готовности кошелька (wallet gateway up в журнале), затем прочитайте новый токен:
    sudo cat /var/lib/parlons-node/gateway-token.txt
  3. Передайте новый токен всему, что было вручную настроено со старым. Телефоны, которые нашли шлюз через приветствие ретранслятора, получат новый ключ там же.

Если в юните задан -Dparlons.gateway.token, он имеет приоритет над файлом: тогда меняйте его там.

Как изменить лимиты частоты шлюза

  1. Добавьте в юнит свойства, которые хотите изменить (значения — запросы в секунду; 0 выключает лимит /cmd):
    -Dparlons.gateway.rate.global=100
    -Dparlons.gateway.rate.perip=0
  2. Перезапустите узел (§7).
  3. За TLS-прокси вместо этого ограничивайте каждого клиента в прокси (§11, Caddy).

15Хостинг NFT и parlons.node.public

Узел раздаёт файлы, на которые ссылаются метаданные токенов, так что маркетплейс или обозреватель блоков может ссылаться прямо на ваш сервер.

Как включить хостинг NFT

Хостинг NFT всегда включён; ему нужен только публичный URL.

  1. Направьте /parlons-node/ на http://127.0.0.1:9585/ через TLS-прокси (§11).
  2. Задайте в юните публичную базу и перезапустите узел (§7):
    -Dparlons.node.public=https://node.example.com/parlons-node
  3. Проверьте строку журнала:
    journalctl -u parlons-node -b --no-pager | grep 'nft hosting'

    Она должна заканчиваться на served at https://node.example.com/parlons-node/nft/<file>, а не на (no public base …).

  4. Загрузите файл с подключённого устройства. Загрузка вернёт публичный url файла.
  5. Проверьте файл с другой машины. Должно вернуться 200:
    curl -sI https://node.example.com/parlons-node/nft/<sha256>.<ext> | head -1

Как посмотреть и удалить размещённые файлы

  1. Выведите, что хранит узел:
    ls -l /var/lib/parlons-node/nft/ /var/lib/parlons-node/nft/c/
  2. Удаляйте файл с подключённого устройства (parlons.nft.delete). В manifest.json коллекции перечислен каждый элемент, поэтому не удаляйте файлы коллекций вручную.
  3. Проверьте занятое место на диске:
    du -sh /var/lib/parlons-node/nft

16DEX-кейп ретранслятора (Dexicon)

DEX-кейп ретранслятора (dexrelay/, версия 0.1.5, без зависимостей) — это ретранслятор книги заявок для Dexicon. Он работает внутри узла; это не отдельная служба. По замыслу ему не нужно доверять:

Как включить DEX-кейп ретранслятора

Установщик одной командой (§5 A) уже делает всё это: он задаёт parlons.dex.public = https://<имя>/dex-relay (режим fleet затем включает кейп на loopback 9602) и ставит перед ним Caddy. Шаги ниже — для узла, установленного иначе.

  1. Добавьте три свойства в юнит, затем перезапустите узел (§7):
    -Dparlons.dex.port=9602
    -Dparlons.dex.bind=127.0.0.1
    -Dparlons.dex.public=https://node.example.com/dex-relay

    Со скриптом развёртывания укажите --dex 9602 --dex-public https://node.example.com/dex-relay. Тогда скрипт сам задаст привязку к loopback.

  2. Направьте /dex-relay/ на http://127.0.0.1:9602/ через TLS-прокси (§11). В nginx добавьте строку X-Forwarded-For.
  3. Проверьте журнал запуска:
    journalctl -u parlons-node -b --no-pager | grep 'dex relay'

    Нужны эти две строки:

    [parlons-node] dex relay 0.1.5 up on 127.0.0.1:9602 (GET /dex/health)
    [parlons-node] dex relay announced in the mesh as https://node.example.com/dex-relay (GET /dex/relays)

    Если публичный URL или хост ещё не известен, вторая строка будет такой: dex relay: no public host known yet - NOT announced in the mesh until one is learned ….

  4. Убедитесь, что кейп слушает только на loopback. Адрес должен быть 127.0.0.1:9602:
    ss -ltnp | grep ':9602 '
  5. Проверьте его с другой машины (см. «Проверка» ниже).

Привязка. Явно заданный parlons.dex.bind всегда имеет приоритет. Если он не задан, кейп слушает 127.0.0.1, когда задан parlons.dex.public, и 0.0.0.0, когда не задан. Поэтому, если вы зададите только parlons.dex.port, кейп будет отвечать по обычному HTTP всему интернету. Задайте parlons.dex.public (и, для ясности, parlons.dex.bind=127.0.0.1) и поставьте перед ним TLS.

Как выключить DEX-кейп ретранслятора

  1. Удалите три свойства parlons.dex.* из юнита (или задайте -Dparlons.dex.port=0) и перезапустите узел (§7).
  2. Удалите блок /dex-relay/ из TLS-прокси и перезагрузите его.

API

Метод и путьНазначениеОтветы
POST /dex/publishОпубликовать один конверт заявки (не более 16 КиБ).200 {"ok":true,"seq":…,"cursor":…} · 400 некорректный · 409 устаревший seq · 413 слишком большой · 503 ретранслятор заполнен
GET /dex/book?market=&since=&hold=Изменения книги заявок с момента курсора. Длинный опрос до hold секунд (не более 25). since=0 возвращает полный снимок (reset:true).200 {"cursor":…,"reset":…,"orders":[…]} · 503 занят
POST /dex/msgДоставить одно запечатанное торговое сообщение (не более 256 КиБ).200 {"ok":true} · 400 · 413 · 503 входящие заполнены
GET /dex/inbox?pk=&since=&hold=Сообщения для публичного идентификатора (pk должен быть 0x плюс 64 байта в hex). Длинный опрос до 25 с.200 {"cursor":…,"messages":[…]} · 400 · 503 занят
GET /dex/healthПроверка работоспособности.{"ok":true,"version":"0.1.5","orders":<n>,"cursor":<n>,"uptime":<s>}
GET /dex/relaysВсе URL DEX-ретрансляторов, известные этому хосту, включая его самого, узнанные через mesh-сеть ретрансляторов.{"ok":true,"relays":[{"url":"…","seen":<epoch s>}]}

Любой другой путь возвращает 404. При ограничении частоты возвращается 429 с {"ok":false,"error":"rate limited"}.

Ограничения (зафиксированы в коде)

ОграничениеЗначение
Активные заявки20 000 (после этого 503 relay full)
Всего хранимых сообщений20 000
Сообщений на одного получателя200
Одновременных длинных опросов512
Самый длинный длинный опрос25 с
Срок действия заявкине более чем на 24 ч вперёд
Срок действия сообщенияне более чем на 600 с вперёд
Монет на заявку32
Очистка устаревших записейкаждые 30 с
Частота200 запросов/с общая, 20 запросов/с на один IP (всплеск = запас на 2 с)

Ограничение частоты за прокси. За loopback TLS-прокси каждый запрос приходит с 127.0.0.1. Когда запрос приходит с loopback, кейп ограничивает частоту по самой правой записи X-Forwarded-For (той, которую добавил ваш прокси), а не по адресу соединения. Заголовок прямого вызывающего не с loopback игнорируется, так что никто не может выбрать себе лимит сам. Ваш прокси должен отправлять этот заголовок: reverse_proxy в Caddy и ProxyPass в Apache делают это по умолчанию; nginx нужна строка proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; в блоке /dex-relay/. Без заголовка лимит на один IP в 20 запросов/с (всплеск 40) действует на весь публичный трафик вместе.

Обнаружение

Проверка

  1. С другой машины запросите запись о работоспособности. Она должна вернуть {"ok":true,"version":"0.1.5",…}:
    curl -s https://node.example.com/dex-relay/dex/health
  2. Выведите DEX-ретрансляторы, известные этому. Его собственный URL должен быть в списке:
    curl -s https://node.example.com/dex-relay/dex/relays
  3. Убедитесь, что обычный порт закрыт снаружи. Команда не должна ничего вывести:
    nc -z -w 5 node.example.com 9602 && echo "EXPOSED 9602"
  4. Примерно через 10 минут запросите список у другого DEX-ретранслятора. URL этого узла тоже должен там появиться.

17Аккаунт, подключение устройств и локальная панель

Каждый Parlons Node также запускает аккаунт Parlons: тот же код, что и parlons-cloud.jar, на личности узла, с собственным кошельком узла и кейпом в роли ретранслятора. Телефоны подключаются к нему из приложения Parlons Cloud. Выключается через -Dparlons.account=false.

Как подключить телефон

Выполняйте эти команды на сервере в интерактивном SSH-терминале. Что делать в приложении на каждом шаге, описано в Руководстве по порталу Parlons Cloud.

  1. Один раз задайте пароль администратора для подключения устройств:
    sudo parlons-pair --set-admin-password
  2. Выведите адрес вашего аккаунта и одноразовое приглашение владельца. Если установлен qrencode, рисуется QR-код:
    sudo parlons-pair --admin
  3. Отсканируйте или вставьте приглашение в приложении Parlons Cloud. Действующий код подключает устройство сразу.
  4. Проверьте heartbeat. Число устройств в account=up:… devices увеличится на одно:
    journalctl -u parlons-node --since -2min --no-pager | grep heartbeat | tail -1

parlons-pair по умолчанию читает /var/lib/parlons-node. Если ваш каталог данных находится в другом месте, укажите --data DIR.

Неиспользованный код хранится в pair-code.txt, пока его не используют. Использованный код больше никогда не действует. Не берите коды из старых журналов или старых копий invite.txt.

Как разместить гостевой аккаунт

Для гостевых аккаунтов нужна отдельная служба parlons-tenants рядом с узлом. Сначала настройте её (Руководство по порталу Parlons Cloud, §21). Укажите ей --panel-port 9597, чтобы она не конфликтовала с панелью узла на 9587.

  1. Создайте гостевое приглашение для нового имени аккаунта:
    sudo parlons-pair --guest <name>
  2. Отправьте приглашение гостю по закрытому каналу. Гость подключается из своего приложения Parlons Cloud.

Подробнее о приглашениях: Руководство по порталу Parlons Cloud, §23.

Как запустить узел без аккаунта

Задайте в юните -Dparlons.account=false и перезапустите узел (§7). Тогда узел работает только как ретранслятор и шлюз. Heartbeat показывает account=off.

Собственный ретранслятор

Когда кейп включён и его публичный хост известен, аккаунт сначала подключается к собственному кейпу, объявляет его первым и привязывает к нему свой постоянный адрес. Если хост неизвестен или частный, в журнале будет own relay NOT advertised: … set -Dparlons.relay.host=<public ip>.

Как открыть локальную панель

  1. Со своего компьютера откройте SSH-туннель к порту панели и не закрывайте его:
    ssh -L 9587:127.0.0.1:9587 root@node.example.com
  2. В этой SSH-сессии прочитайте одноразовую ссылку:
    sudo cat /var/lib/parlons-node/panel-ticket.txt

    Она выглядит как http://127.0.0.1:9587/open?ticket=….

  3. Откройте ссылку в браузере на своём компьютере. Как только ссылка использована, аккаунт создаёт новую.
  4. Если раньше вы отозвали панель и хотите её вернуть, удалите ключ локального устройства и перезапустите узел:
    rm /var/lib/parlons-node/local-device.key
    systemctl restart parlons-node

Панель слушает только 127.0.0.1:9587 (parlons.panel.port; 0 выключает её). У неё нет доступа к сид-фразе, резервным копиям, отправке средств из кошелька, платежам, консоли узла и хостингу NFT. Всё это остаётся на подключённых телефонах и в командной строке. Что она показывает: Руководство по порталу Parlons Cloud, §24.

Как восстановить переносимый аккаунт на новом узле

Пакет .pbk создаётся на подключённом устройстве («Настройки» → Создать резервную копию аккаунта…, см. Руководство по порталу Parlons Cloud, §16). Он содержит личность, подключённые устройства, настройки, контакты и чаты.

  1. Навсегда остановите хост, с которого сделана резервная копия: одна личность — один работающий аккаунт.
  2. Установите узел (§5), но не запускайте его, или остановите его и уберите его каталог данных в сторону. Для восстановления нужен чистый каталог данных:
    systemctl stop parlons-node
    mv /var/lib/parlons-node /var/lib/parlons-node.before-restore
    mkdir -p /var/lib/parlons-node
    chown maxima:maxima /var/lib/parlons-node
    chmod 700 /var/lib/parlons-node
  3. Скопируйте пакет и передайте его служебному пользователю:
    cp backup.pbk /var/lib/parlons-node/backup.pbk
    chown maxima:maxima /var/lib/parlons-node/backup.pbk
  4. Запустите восстановление от имени служебного пользователя в интерактивном терминале. Оно запросит парольную фразу пакета, запишет аккаунт и завершит работу:
    sudo -u maxima java -Dparlons.node.data=/var/lib/parlons-node \
        -Dparlons.restore=/var/lib/parlons-node/backup.pbk -jar /opt/maxima/parlons-node.jar
  5. Удалите пакет и запустите узел:
    rm /var/lib/parlons-node/backup.pbk
    systemctl start parlons-node
  6. Подключённые устройства переподключатся сами, потому что MAX# тот же.
  7. Кошелёк узла остаётся его собственным хранилищем. Чтобы средства последовали за аккаунтом, пересинхронизируйте кошелёк на старую фразу с подключённого устройства (§20).

Приложение также может импортировать личность или .pbk прямо на работающий узел («Настройки» → Импортировать личность или резервную копию…). Тогда узел завершается с кодом 3 и возвращается с импортированной личностью. Предыдущая личность сохраняется в account-history/<import-id>/previous/.


18Вспомогательный процесс keets (мост KeetChat)

Когда встроенный узел Minima запускает keets, чат-движок аккаунта получает транспорт keets, а узел становится единственным читателем своих входящих keets.

Fleet-jar делает всё это сам. parlons-node-fleet-<ver>.jar несёт внутри среду Node.js и вспомогательный процесс. Запущенный с -Dparlons.fleet=true (это записывает установщик одной командой), он при первом старте распаковывает их в <data>/runtime/, включает роль сервера Minima и -keets и запускает вспомогательный процесс в режиме serve: один JavaScript-процесс, который одновременно является транспортом keets машины, её публичным узлом начальной загрузки HyperDHT (49737/udp, -Dparlons.keets.dhtport) и её почтовым ящиком keets (<data>/keets-mailbox). -Dparlons.public.host=<ip> даёт машине имя. В журнале загрузки печатается баннер FLEET ENDPOINT с публичным ключом keets, адресом начальной загрузки DHT и ключом почтового ящика, а также команда mailboxes-sign.js, которую выполняет сопровождающий списка; почтовый ящик хранит почту для телефонов офлайн только после подписи в опубликованный список. Флаги Minima, заданные вами в parlons.node.args, имеют приоритет над тем, что выставил бы режим fleet. Остальная часть раздела — ручной путь с обычным jar и внешним вспомогательным процессом.

Как включить keets с помощью скрипта развёртывания

  1. Установите Node.js на сервер. Без среды выполнения node скрипт отказывается продолжать:
    apt-get install -y nodejs
    node --version
  2. На своём компьютере склонируйте репозиторий keets рядом с клоном maxima, чтобы вспомогательный процесс оказался в ../keets/sidecar, и установите его пакеты:
    (cd ../keets/sidecar && npm ci --omit=dev)

    Чтобы использовать вспомогательный процесс из другого места, задайте SIDECAR=/path/to/sidecar перед запуском скрипта.

  3. Запустите скрипт развёртывания повторно со всеми обычными флагами плюс --keets. Он загрузит вспомогательный процесс в /opt/maxima/keets-sidecar, добавит флаги и добавит AF_NETLINK в юнит.
  4. Проверьте журнал:
    journalctl -u parlons-node -b --no-pager | grep -E 'keets'

    Нужны строки keets chat bridge up (KeetChat interop) и keets identity: 0x….

Как включить keets вручную

  1. Установите Node.js на сервер и скопируйте вспомогательный процесс вместе с его node_modules в /opt/maxima/keets-sidecar (там должен быть index.js).
  2. Добавьте флаги keets в parlons.node.args в юните:
    "-Dparlons.node.args=-keets -keetssidecar /opt/maxima/keets-sidecar/index.js"
  3. Добавьте AF_NETLINK в семейства адресов в юните:
    RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX AF_NETLINK
  4. Перезагрузите конфигурацию и перезапустите узел (§7), затем проверьте журнал, как в шаге 4 выше.
  5. Передайте значение keets identity: 0x… пользователям KeetChat, которые хотят добавить узел в контакты.

19MDS (MiniHUB) на узле

Как включить MDS и открыть MiniHUB

  1. Поместите пароль MDS в conf-файл (§8, conf-файл) или пропустите этот шаг, и узел сгенерирует пароль сам.
  2. Добавьте эти свойства в юнит и перезапустите узел (§7). Если вы пропустили шаг 1, не добавляйте строку parlons.node.conf: нечитаемый conf-файл останавливает узел с кодом завершения 2.
    -Dparlons.mds=true
    -Dparlons.mds.bind=127.0.0.1
    -Dparlons.node.conf=/var/lib/parlons-node/minima.conf
  3. Если вы не задали пароль, прочитайте сгенерированный через административный RPC на сервере:
    curl -s http://127.0.0.1:9005/mds
  4. Со своего компьютера откройте SSH-туннель к файловому порту MDS (P2P-порт 9001 означает 9003):
    ssh -L 9003:127.0.0.1:9003 root@node.example.com
  5. Откройте https://127.0.0.1:9003/ в браузере, примите самоподписанный сертификат и войдите с паролем.

20Сид-фразы, личность и резервные копии

Сид-фраза — это кошелёк. Фраза узла из 24 слов, identity.txt и любой принятый вами seed.txt позволяют тратить средства. Никогда не выводите их в журнал, заявку в поддержку, чат или терминал, который записывается. Когда вы ищете что-то через grep в файлах юнитов или журналах, добавляйте | grep -v seed.

Два секрета, одно происхождение

ЧтоГдеДля чего
Сид-фраза кошелькахранилище (vault) узла в <data>/<base version>/кошелёк узла (кошелёк аккаунта)
Фраза личности<data>/identity.txt (права 600)личность Maxima Mx…, MAX# аккаунта, подключение устройств, контакты

При первом запуске узел создаёт собственную сид-фразу кошелька и копирует фразу в identity.txt. Если фраза узла — произвольная, которую правило фраз не может воспроизвести, вместо неё сохраняется seed в hex. С этого момента личность берётся из identity.txt, а не из хранилища. Поэтому:

Как сделать резервную копию сид-фразы кошелька

  1. Убедитесь, что административный RPC включён (§21).
  2. На сервере, в сессии, которая не записывается, выведите хранилище:
    curl -s http://127.0.0.1:9005/vault
  3. Запишите phrase из 24 слов на бумаге или сохраните в офлайн-хранилище. Не перенаправляйте её в файл в общедоступном месте.
  4. Очистите историю прокрутки терминала.
  5. Если фраза личности отличается от фразы кошелька (после пересинхронизации или импорта личности), сделайте резервную копию и identity.txt (следующая процедура).

Как сделать резервную копию всего узла

Саму цепочку копировать не нужно: новый узел синхронизирует её заново. Сохраните секреты и свои настройки.

  1. Сделайте резервную копию сид-фразы кошелька (предыдущая процедура).
  2. Скопируйте файлы личности и аккаунта в закрытое зашифрованное место под вашим контролем. Сначала остановите узел, чтобы файлы были согласованы:
    systemctl stop parlons-node
    tar -C /var/lib/parlons-node -czf /root/parlons-node-backup.tgz \
        --exclude='./1.1' --exclude='./nft/tmp' .
    systemctl start parlons-node
    chmod 600 /root/parlons-node-backup.tgz

    Архив содержит identity.txt, аккаунт (устройства, контакты, чаты), состояние ретранслятора, токен шлюза и размещённые файлы NFT. Это секрет уровня кошелька: обращайтесь с ним как с сид-фразой.

  3. Скопируйте юнит и конфигурацию TLS-прокси:
    cp /etc/systemd/system/parlons-node.service /root/
  4. Перенесите архив с сервера, затем удалите его там:
    scp root@node.example.com:/root/parlons-node-backup.tgz .
    ssh root@node.example.com rm /root/parlons-node-backup.tgz
  5. Для переносимой копии только аккаунта создайте пакет .pbk на подключённом устройстве (Руководство по порталу Parlons Cloud, §16).

Никогда не восстанавливайте этот архив на второй сервер, пока первый ещё работает. Одна личность работает в одном месте.

Как принять существующую фразу с помощью скрипта развёртывания

  1. Поместите фразу из 24 слов в файл на сервере, владелец root, права 600. На сервере, где работал maxima-server.jar, она уже лежит в /var/lib/maxima/seed.txt.
  2. Запустите скрипт развёртывания повторно с --rpc --seed-from <file on the box> плюс обычными флагами. Укажите --archive <host:port>, чтобы выбрать архивный узел. Если вы также импортируете MegaMMR, скрипт сначала принимает фразу, как и положено.
  3. Прочитайте результат. vault MATCHES <file> - identity preserved (and pinned in identity.txt) означает, что всё получилось. Любой другой результат означает: не доверяйте узлу, пока не выясните причину.
  4. Удалите файл с фразой с сервера, как только у вас будет офлайн-копия.

Что делает --seed-from

Он сохраняет личность существующего ретранслятора или облачного аккаунта. Скрипт развёртывания:

  1. Проверяет, что файл на сервере содержит ровно 24 слова.
  2. Отправляет megammrsync action:resync host:<--archive> phrase:"…" как тело POST-запроса из временного файла с правами 600. Фраза никогда не попадает в argv и в журнал.
  3. Перезапускает узел и сравнивает фразу в хранилище с файлом, не выводя ни ту, ни другую.
  4. Если они совпадают, записывает identity.txt из файла и метку .seed-adopted, чтобы последующие запуски пропускали этот шаг.

Фраза никогда не покидает сервер.

Как пересинхронизировать кошелёк на другую фразу

С подключённого устройства: «Кошелёк» → Сменить фразу кошелька…. Узел использует архивный хост из parlons.node.archive, завершается с кодом 3 и возвращается с той же личностью.

Вручную на сервере (именно это делает --seed-from скрипта развёртывания):

  1. Запишите команду в закрытый временный файл, чтобы фраза никогда не попала в argv или журнал:
    umask 077
    tmp=$(mktemp /var/lib/parlons-node/.resync.XXXXXX)
    printf 'megammrsync action:resync host:%s phrase:"%s"' 'archive.example.net:9001' '<24 words>' > "$tmp"

    Вводите фразу в сессии, которая не записывается, и после этого очистите историю оболочки.

  2. Отправьте её административному RPC как тело POST-запроса. Это может занять несколько минут:
    curl -s -m 3600 --data-binary @"$tmp" http://127.0.0.1:9005/
    shred -u "$tmp"

    Ответ должен содержать "status":true. Пересинхронизация заканчивается выключением узла.

  3. Перезапустите узел и дождитесь, пока RPC снова начнёт отвечать:
    systemctl restart parlons-node
    until curl -s -m 5 http://127.0.0.1:9005/status >/dev/null; do sleep 2; done
  4. Убедитесь, что хранилище теперь содержит новую фразу (curl -s http://127.0.0.1:9005/vault), в сессии, которая не записывается.
  5. Если вы используете MegaMMR, импортируйте его заново сейчас (§13): пересинхронизация сбросила базы данных цепочки.

Личность остаётся закреплённой в identity.txt, поэтому MAX#, подключённые устройства и контакты не меняются.

Как заново закрепить личность за хранилищем

Это меняет личность Maxima и MAX#, если фраза хранилища отличается от identity.txt. Тогда подключённые устройства и контакты указывают на старую личность.

  1. Сохраните копию старого файла личности, затем удалите его:
    cp /var/lib/parlons-node/identity.txt /var/lib/parlons-node/identity.txt.before-repin
    rm /var/lib/parlons-node/identity.txt
  2. Перезапустите узел. В журнале запуска будет identity: pinned from the vault into identity.txt:
    systemctl restart parlons-node
    journalctl -u parlons-node -b --no-pager | grep 'identity:' | grep -v seed
  3. Удалите копию .before-repin, когда убедитесь, что старая личность вам не нужна.

Как запустить узел, защищённый паролем

Если хранилище заблокировано, кейп, шлюз и аккаунт не могут запуститься, пока оно не разблокировано. Сам узел Minima продолжает работать. Узел пытается разблокироваться ровно один раз за запуск — из файла или из переменной окружения PARLONS_NODE_PASSPHRASE.

  1. Запишите парольную фразу в файл в /var/lib/parlons-node или /etc (не в /root или /home: ProtectHome=true их скрывает). Парольная фраза не должна содержать пробельных символов, " или ;:
    umask 077
    printf '%s\n' '<passphrase>' > /var/lib/parlons-node/passphrase.txt
    chown maxima:maxima /var/lib/parlons-node/passphrase.txt
    chmod 600 /var/lib/parlons-node/passphrase.txt
  2. Добавьте её в юнит и перезапустите узел (§7). Со скриптом развёртывания укажите --passphrase-file /var/lib/parlons-node/passphrase.txt:
    -Dparlons.node.passphrase.file=/var/lib/parlons-node/passphrase.txt
  3. Убедитесь, что кейп, шлюз и аккаунт поднялись (cape=up, gateway=up в heartbeat). node is password-locked but no passphrase provided в журнале означает, что файл не был прочитан.

Никогда


21Административный RPC

Как включить административный RPC

  1. Добавьте -Dparlons.node.rpc=true в юнит и перезапустите узел (§7). Со скриптом развёртывания укажите --rpc.
  2. Проверьте строку запуска. В ней должно быть admin rpc 127.0.0.1:9005 (loopback-bound):
    journalctl -u parlons-node -b --no-pager | grep 'admin rpc' | grep -v seed
  3. На сервере выполните команду:
    curl -s http://127.0.0.1:9005/status
  4. С другой машины убедитесь, что порт не отвечает. Команда не должна ничего вывести:
    nc -z -w 5 node.example.com 9005 && echo "EXPOSED 9005"

Как выполнить команду с пробелами или кавычками

  1. Для короткой команды закодируйте пробелы в URL как %20:
    curl -s 'http://127.0.0.1:9005/balance%20megammr:true%20address:<address>'
  2. Всё, что длиннее или содержит кавычки, отправляйте как тело POST-запроса (до 64 КиБ):
    curl -s --data-binary 'coins relevant:true' http://127.0.0.1:9005/

Как остановить или перезапустить узел

Используйте systemd, а не quit:

systemctl stop parlons-node
systemctl start parlons-node
systemctl restart parlons-node

22Обновление и откат

По соглашению используются jar-файлы с версиями плюс символическая ссылка. Все jar-файлы хранятся в /opt/maxima, а юнит всегда запускает /opt/maxima/parlons-node.jar, который является символической ссылкой.

Как обновить один сервер

  1. На своём компьютере скачайте новый jar-файл и проверьте его SHA-256 (§4).
  2. Скопируйте его на сервер под временным именем:
    B=parlons-node-0.2.144.jar
    scp $B root@node.example.com:/opt/maxima/$B.part
  3. На сервере ещё раз проверьте хеш, затем поставьте jar-файл на место:
    cd /opt/maxima
    echo 'c5b114cc13294bdeee95d9872fc6710cd99c92472ffb63c1581081343663a6f5  parlons-node-0.2.144.jar.part' | sha256sum -c --quiet
    mv parlons-node-0.2.144.jar.part parlons-node-0.2.144.jar
    chmod 644 parlons-node-0.2.144.jar
  4. Запишите, на какой jar-файл сейчас указывает символическая ссылка. Это нужно для отката:
    readlink /opt/maxima/parlons-node.jar
  5. Сохраните резервную копию юнита:
    cp /etc/systemd/system/parlons-node.service /etc/systemd/system/parlons-node.service.before-parlons-node-0.2.144.jar
  6. Обновите версию в строке Description юнита (необязательно; это только подпись):
    sed -i 's/wallet gateway ([0-9.]*)/wallet gateway (0.2.144)/' /etc/systemd/system/parlons-node.service
  7. Направьте символическую ссылку на новый jar-файл:
    ln -sfn /opt/maxima/parlons-node-0.2.144.jar /opt/maxima/parlons-node.jar
  8. Перезапустите узел:
    systemctl daemon-reload
    systemctl restart parlons-node
  9. Подождите около 25 с, затем проверьте:
    systemctl is-active parlons-node
    journalctl -u parlons-node --since -40s --no-pager | grep -E 'Parlons Node|dex relay|Exception' | grep -v seed

    Строка запуска должна показывать Parlons Node 0.2.144, а DEX-кейп — dex relay 0.1.5 up.

  10. Проверьте узел извне (§23).

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

Как обновить с помощью скрипта развёртывания

  1. Положите новый проверенный jar-файл в dist/ на своём компьютере.
  2. Запустите скрипт повторно с теми же флагами, что и раньше, и новым jar-файлом:
    ops/deploy-parlons-node.sh root@node.example.com --jar dist/parlons-node-0.2.144.jar <your usual flags>

    Скрипт загружает и проверяет jar-файл, переключает символическую ссылку и перезаписывает юнит по своим флагам. Флаг, который вы не укажете, вернётся к значению по умолчанию.

  3. Проверьте узел извне (§23).

Как откатиться

  1. Направьте символическую ссылку на предыдущий jar-файл (тот, который readlink показал на шаге 4 обновления):
    cd /opt/maxima && ln -sfn parlons-node-<old version>.jar parlons-node.jar
  2. Если вы меняли юнит, восстановите его из резервной копии .before-…:
    cp /etc/systemd/system/parlons-node.service.before-<what> /etc/systemd/system/parlons-node.service
  3. Перезапустите узел:
    systemctl daemon-reload
    systemctl restart parlons-node
  4. Убедитесь, что строка запуска показывает старую версию, затем проверьте узел извне (§23).

Как вернуться к maxima-relay.service

Если раньше на сервере работал maxima-relay.service и узел заменил его, можно откатиться и к нему. Скрипт развёртывания оставил его юнит на диске:

systemctl disable --now parlons-node
systemctl enable --now maxima-relay

23Проверка извне

systemctl is-active показывает только, что процесс запущен. Всегда проверяйте с другой машины в публичном интернете. Не проверяйте с самого сервера или из его локальной сети: hairpin NAT даёт ложные результаты в обе стороны.

  1. Доступность по TCP портов P2P и ретранслятора:
    nc -z -w 8 node.example.com 9001 && echo p2p-open
    nc -z -w 8 node.example.com 9501 && echo relay-open
  2. Ретранслятор целиком. Из клона этого репозитория, где :core и его тесты скомпилированы в build/classes:
    ops/verify-relay.sh node.example.com:9501

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

  3. DEX-кейп:
    curl -s https://node.example.com/dex-relay/dex/health    # {"ok":true,"version":"0.1.5",...}
    curl -s https://node.example.com/dex-relay/dex/relays
  4. Шлюз: POST-запрос block с токеном (§14). Запрос без токена должен вернуть 401.
  5. NFT: curl -sI https://node.example.com/parlons-node/nft/<sha256>.<ext> возвращает 200 для размещённого файла и 404 для всего остального.
  6. Порты только для loopback НЕ должны отвечать извне:
    for p in 9005 9585 9587 9602; do nc -z -w 5 node.example.com $p && echo "EXPOSED $p"; done

    Команда не должна ничего вывести.


24Мониторинг и журналы

Весь вывод идёт в журнал (StandardOutput=journal). Полезные команды:

journalctl -u parlons-node -f                                   # follow
journalctl -u parlons-node -f | grep heartbeat                  # sync progress and subsystem health
journalctl -u parlons-node --since -1h | grep -E 'Exception|FAILED|REFUSING' | grep -v seed
journalctl -u parlons-node -b | grep -E 'Parlons Node|cape up|gateway up|dex relay|account up'
systemctl status parlons-node

Строка heartbeat, каждые 30 с:

[parlons-node] heartbeat: node block=<n> chainlen=<n> | cape=up:<port> | gateway=up:<port> | account=up:<n> hosts, <n> devices
ПолеНорма
block=растёт, затем держится на вершине цепочки
cape=up:<relay port> (down означает, что кейп упал или выключен)
gateway=up:<gateway port>
account=up: с 1 или более хостами (off при parlons.account=false)

Если вы видите heartbeat: node not ready: …, встроенный узел ещё не отвечает на status. Это нормально в течение короткого времени после запуска.

Как проверить состояние узла за одну минуту

  1. Работает ли служба? -w ищет слово целиком, поэтому inactive не засчитывается:
    systemctl is-active parlons-node | grep -qw active && echo running
  2. Прочитайте последний heartbeat:
    journalctl -u parlons-node --since -2min --no-pager | grep heartbeat | tail -1
  3. Сверьте каждое поле с таблицей выше.
  4. Поищите ошибки за последний час:
    journalctl -u parlons-node --since -1h --no-pager | grep -E 'Exception|FAILED|REFUSING|OutOfMemoryError' | grep -v seed
  5. Проверьте диск и память:
    df -h /var/lib
    systemctl status parlons-node --no-pager | grep -E 'Memory|Tasks'
  6. Выполните проверки извне (§23).

Как настроить оповещения о проблемах

У узла нет адреса для метрик; интерфейсом служат heartbeat и строки журнала ниже. Простая проверка — задание cron, которое отправляет оповещение, когда heartbeat пропадает или появляется тревожная строка:

  1. Создайте скрипт проверки /usr/local/bin/parlons-node-check:
    #!/bin/sh
    # Exit 1 (and print why) when the node needs attention.
    systemctl is-active parlons-node | grep -qw active || { echo "parlons-node not active"; exit 1; }
    journalctl -u parlons-node --since -2min --no-pager | grep -q heartbeat || { echo "no heartbeat for 2 min"; exit 1; }
    bad=$(journalctl -u parlons-node --since -5min --no-pager | grep -E 'REFUSING|FAILED|OutOfMemoryError|password-locked' | grep -v seed)
    [ -z "$bad" ] || { echo "$bad"; exit 1; }
  2. Сделайте его исполняемым и запускайте каждые 5 минут из crontab пользователя root со своей командой оповещения:
    chmod 755 /usr/local/bin/parlons-node-check
    crontab -e
    # */5 * * * * /usr/local/bin/parlons-node-check || <your alert command>

Строки журнала, на которые стоит настроить оповещения:

Строка содержитЗначение
REFUSING to start / REFUSING to runневерные флаги или конфликт портов (код 2)
Maxima cape FAILED to startретранслятор не поднялся
wallet gateway FAILEDшлюз не поднялся
account layer FAILED to startаккаунт не поднялся
node is password-locked but no passphrase providedкейп, шлюз и аккаунт ждут разблокировки
node seed (vault) not available after 120sкошелёк не готов, поэтому кейп не может вывести свою личность
the embedded node shut itself downпосле пересинхронизации, восстановления или сброса JVM завершается; перезапустите её
wallet resync FAILEDпересинхронизация с устройства не удалась; кошелёк не изменён
OutOfMemoryErrorкуча слишком мала (см. §3)

25Заметки о файрволе

Входящие, открыть:

Входящие, никогда не открывать: p2p+2, p2p+3, p2p+4, 9585, 9587, 9602 и любые панели гостевых аккаунтов 959x.

Облачные файрволы. Файрвол провайдера (в консоли Vultr, Hetzner или AWS) может отбрасывать пакеты ещё до того, как они дойдут до сервера. ufw этого не исправит. Если порт извне не отвечает по тайм-ауту, хотя он открыт в ufw и отвечает на localhost, откройте его в консоли провайдера. Изменения правил могут применяться минуту или две, поэтому проверьте ещё раз, прежде чем делать выводы.

Запрет исходящих по умолчанию. На сервере с политикой запрета исходящих по умолчанию (ufw default deny outgoing) узел не может достучаться до пиров, которых вы не разрешили. Разрешите как минимум:

Отсутствующее правило для исходящих проявляется как пир, которого нет в /dex/relays, или поиски в mesh-сети, которые никогда не доходят до одного из ретрансляторов.

Домашние роутеры. Пробросьте P2P-порт и порт ретранслятора или используйте -Dparlons.relay.port=shared, чтобы хватило одного проброшенного порта.

Как открыть порты с помощью ufw

  1. Сначала разрешите SSH, чтобы не отрезать себе доступ, затем публичные порты узла:
    ufw allow OpenSSH
    ufw allow 9001/tcp
    ufw allow 9501/tcp
    ufw allow 80/tcp
    ufw allow 443/tcp
  2. Необязательно: разрешите STUN на порту ретранслятора:
    ufw allow 9501/udp
  3. Включите ufw, если он выключен, и проверьте правила:
    ufw enable
    ufw status numbered
  4. Откройте те же порты в файрволе облачного провайдера, если он есть.
  5. Проверьте с другой машины (§23).

Как открыть порты с помощью firewalld

  1. Добавьте порты постоянно, затем перезагрузите правила, чтобы они вступили в силу:
    firewall-cmd --permanent --add-port=9001/tcp
    firewall-cmd --permanent --add-port=9501/tcp
    firewall-cmd --permanent --add-service=http
    firewall-cmd --permanent --add-service=https
    firewall-cmd --reload
  2. Проверьте результат:
    firewall-cmd --list-all

Скрипт развёртывания добавляет порты с --permanent, но не перезагружает firewalld. На сервере с firewalld выполните firewall-cmd --reload после скрипта.

Как разрешить исходящий трафик на сервере с запретом по умолчанию

  1. Разрешите порт ретранслятора каждого пира mesh-сети (повторите для каждого пира с его настоящим портом):
    ufw allow out to <peer ip> port 9501 proto tcp
  2. Разрешите корневой узел, ваших пиров Minima и архивный узел (повторите для каждого):
    ufw allow out to <peer ip> port 9001 proto tcp
  3. Разрешите исходящий HTTPS для загрузки снимков, а также DNS:
    ufw allow out 443/tcp
    ufw allow out 53
  4. Убедитесь, что пир, которого не было в /dex/relays, появляется примерно через 10 минут.

Как пробросить порты на домашнем роутере

  1. Дайте серверу постоянный адрес в локальной сети (резервирование DHCP в роутере).
  2. В роутере пробросьте TCP 9001 и TCP 9501 на этот адрес. При -Dparlons.relay.port=shared пробросьте только 9001.
  3. Проверяйте извне домашней сети, например с телефона через мобильный интернет или с VPS. Проверка изнутри локальной сети недействительна (hairpin NAT).

26Устранение неполадок

Сначала разберитесь с «не удаётся подключиться»

Извне у nc -z -w 8 <host> <port> три возможных исхода:

ИсходОзначаетКуда смотреть
Отказ (refused), сразуХост ответил, но ничего не слушает.systemctl status parlons-node; ss -ltnp | grep <port>; журнал запуска
Тайм-аут (~8 с)Фильтр пакетов молча отбрасывает пакеты.Облачный файрвол или проброс порта на роутере, затем ufw
ОткрытСетевой путь в порядке; проблема в приложении.Журнал; ops/verify-relay.sh

Проверки на сервере:

systemctl is-active parlons-node
ss -ltnp | grep -E ':(9001|9501|9585|9587|9602) '
ufw status numbered | head -20
bash -c '</dev/tcp/127.0.0.1/9501' && echo localhost-ok

Решающая проверка — перехватить пакеты на сервере, пока вы подключаетесь извне:

# on the box
timeout 25 tcpdump -ni any 'tcp port 9501' -c 5
# meanwhile, from outside
nc -z -w 5 node.example.com 9501

Осторожно с systemctl is-active x | grep -q active: это совпадает и с inactive. Используйте grep -qw active.

«Invalid SyncBlock as NO PARENT» после перезапуска

Это сообщение встречалось в журнале сразу после перезапуска, пока узел догоняет вершину цепочки. Дальше оно не исследовалось. Что делать:

  1. Следите за heartbeat. Если block= продолжает расти и доходит до вершины, узел восстановился сам.
  2. Если block= долго не меняется, проверьте, что корневой узел и пиры доступны (файрвол для исходящих, §25), и что часы идут правильно.

Порт уже занят

СимптомПричинаРешение
REFUSING to run: admin rpc on 127.0.0.1:9005 cannot startДругой узел Minima занимает p2p+4, или в JRE нет jdk.httpserver.Перенесите P2P-порт (parlons.node.port=9101 переносит RPC на 9105) или используйте полную JRE.
Конфликт порта ретранслятора; cape=downmaxima-relay.service или другой ретранслятор занимает 9501.systemctl disable --now maxima-relay или выберите другой порт ретранслятора.
Панель не запускается на 9587Его занимает служба parlons-tenants (или второй узел).Укажите службе tenants --panel-port 9597 или задайте parlons.panel.port.
wallet gateway FAILED: …BindExceptionПорт 9585 чем-то занят.Задайте parlons.gateway.port и измените TLS-прокси соответственно.
Узел не запускается на 9001На 9001 работает обычный узел Minima.parlons.node.port=9101

Другие симптомы

СимптомРешение
Процесс сразу завершается и выводит справкуВы передали аргумент командной строки. Все настройки — это свойства -D перед -jar.
REFUSING to start: these Minima flags are not allowedУдалите перечисленные флаги из parlons.node.args или conf-файла (см. §8.8).
block= остаётся на 0Нет корневого узла или списка connect, или исходящий доступ к нему заблокирован.
Цикл нехватки памяти, или служба оказывается в состоянии «failed»Увеличьте кучу (минимум 3 ГБ с MegaMMR) и держите MemoryMax выше неё. Сбросьте лимит запусков командой systemctl reset-failed parlons-node.
Телефоны видят пустые балансыMegaMMR ещё не импортирован (§13).
Шлюз возвращает 503 no MegaMMRУзел работает с megammr=false. Телефоны переключаются на другой шлюз.
Шлюз возвращает 403 requires an address:Добавьте address: к coins/balance.
Шлюз возвращает 429Общий лимит исчерпан. Увеличьте parlons.gateway.rate.global или ограничивайте частоту в прокси.
Шлюз никогда не объявляется телефонамНужны включённый MegaMMR, заданный parlons.node.public и включённый ретранслятор.
url NFT пустойЗадайте в parlons.node.public URL, который действительно ведёт на порт 9585 этого сервера.
own relay NOT advertised: public host unknown or privateЗадайте -Dparlons.relay.host=<public host>.
dex relay: no public host known yet - NOT announcedЗадайте -Dparlons.dex.public=<https url> (или parlons.relay.host).
Пира нет в /dex/relaysПодождите один 10-минутный цикл повторного подключения. Затем проверьте, что этот сервер может подключиться наружу к порту ретранслятора этого пира.
DEX-кейп отвечает на публичном IPparlons.dex.bind всё ещё 0.0.0.0. Задайте 127.0.0.1 и перезапустите узел.
Caddy отдаёт ваш сайт по /dex-relay/…Ловушка порядка handle_path и handle (§11).
Аккаунт так и не сообщает «attached»Нет исходящего доступа в интернет, или часы сильно сбиты.
Кейп, шлюз и аккаунт так и не запускаются; в журнале упоминается блокировка паролемУкажите парольную фразу (§20).
Служба остановилась после quit, ручного импорта megammr или пересинхронизацииВ юните всё ещё указано Restart=on-failure, а оно не перезапускает после штатного завершения. Переведите его на Restart=always (см. решения ниже).
Вспомогательный процесс keets падает с EPERM на сокетахДобавьте AF_NETLINK в RestrictAddressFamilies.
Завершение зависшего процессаЗавершайте его по PID. Никогда не выполняйте pkill -f parlons-node.jar: шаблон может совпасть с вашей собственной SSH-сессией.

Пошаговые решения

Решение: порт административного RPC занят

  1. Посмотрите, кто его занимает:
    ss -ltnp | grep ':9005 '
  2. Если это обычный узел Minima, перенесите P2P-порт Parlons Node (§9).
  3. Если его никто не занимает, в JRE нет jdk.httpserver. Проверьте и, если строки нет, установите полную JRE:
    java --list-modules | grep jdk.httpserver || apt-get install -y default-jre-headless

Решение: порт ретранслятора занят

  1. Посмотрите, кто занимает 9501:
    ss -ltnp | grep ':9501 '
  2. Если это старый отдельный ретранслятор, остановите его и перезапустите узел:
    systemctl disable --now maxima-relay
    systemctl restart parlons-node
  3. Убедитесь, что heartbeat показывает cape=up:9501.

Решение: порт панели или шлюза занят

  1. Посмотрите, кто его занимает:
    ss -ltnp | grep -E ':(9585|9587) '
  2. Если на 9587 работает служба parlons-tenants, укажите ей --panel-port 9597 (Руководство по порталу Parlons Cloud, §21). Иначе перенесите узел: задайте -Dparlons.panel.port=<free port> или -Dparlons.gateway.port=<free port>.
  3. Если вы перенесли шлюз, измените порт и в TLS-прокси, затем перезагрузите его.
  4. Перезапустите узел (§7).

Решение: узел сразу завершается или отказывается запускаться

  1. Прочитайте причину:
    journalctl -u parlons-node -n 30 --no-pager | grep -E 'REFUSING|usage|Usage' | grep -v seed
  2. Если выведена справка, удалите в юните все аргументы после -jar …parlons-node.jar. Все настройки — это свойства -D перед -jar.
  3. Если названы отвергнутые флаги Minima, удалите их из parlons.node.args или conf-файла (§8.8).
  4. Если сказано, что не удаётся прочитать -conf, проверьте путь conf-файла, его владельца (maxima) и права (600).
  5. Перезапустите узел (§7).

Решение: block= остаётся на 0

  1. Убедитесь, что в юните есть корневой узел или список connect:
    grep -E 'parlons.node.(rootnode|connect)' /etc/systemd/system/parlons-node.service
  2. Если их нет, задайте (§13).
  3. Убедитесь, что сервер может до него достучаться:
    nc -z -w 8 seed-peer.example.net 9001 && echo reachable
  4. Если не может, разрешите исходящий трафик к нему (§25).
  5. Проверьте часы:
    timedatectl | grep -E 'synchronized|NTP'

Решение: цикл нехватки памяти, или служба в состоянии «failed»

  1. Подтвердите причину:
    journalctl -u parlons-node --since -1h --no-pager | grep -E 'OutOfMemoryError|oom' | tail -5
  2. Увеличьте -Xmx в юните (3g или больше с MegaMMR) и задайте MemoryMax хотя бы на 512 МБ больше, например -Xmx3g с MemoryMax=3584M.
  3. Перезагрузите конфигурацию, сбросьте лимит запусков и запустите снова:
    systemctl daemon-reload
    systemctl reset-failed parlons-node
    systemctl restart parlons-node
  4. Через минуту убедитесь, что служба всё ещё active.

Решение: телефоны видят пустые балансы

  1. Проверьте размер MegaMMR. Меньше 1 МБ означает, что он так и не был импортирован:
    stat -c %s /var/lib/parlons-node/1.1/databases/megammr.mmr
  2. Импортируйте его (§13).

Решение: шлюз никогда не объявляется телефонам

  1. Проверьте три условия: MegaMMR включён, parlons.node.public задан, ретранслятор включён:
    grep -E 'megammr|node.public|relay.port' /etc/systemd/system/parlons-node.service
  2. Исправьте то, чего не хватает, и перезапустите узел (§14).
  3. Найдите в журнале wallet gateway advertised to phones:.

Решение: кейп не объявляет себя, или DEX-кейп не анонсируется

  1. Прочитайте предупреждение:
    journalctl -u parlons-node -b --no-pager | grep -E 'own relay NOT advertised|dex relay: no public host'
  2. Задайте публичный хост (§12), а для DEX-кейпа также -Dparlons.dex.public=https://node.example.com/dex-relay.
  3. Перезапустите узел и снова проверьте журнал.

Решение: DEX-кейп отвечает на публичном IP

  1. Проверьте привязку:
    ss -ltnp | grep ':9602 '
  2. Если показано 0.0.0.0:9602 или *:9602, добавьте в юнит -Dparlons.dex.bind=127.0.0.1 (и -Dparlons.dex.public=…) и перезапустите узел.
  3. Закройте порт в файрволе, если его открыл скрипт развёртывания:
    ufw delete allow 9602/tcp
  4. Убедитесь извне, что 9602 больше не отвечает (§23, шаг 6).

Решение: Caddy отдаёт ваш сайт по /dex-relay/…

  1. Найдите блок DEX в Caddyfile:
    grep -n 'dex-relay' /etc/caddy/Caddyfile
  2. Если там написано handle_path /dex-relay/*, замените это на handle /dex-relay/* с uri strip_prefix /dex-relay внутри (§11).
  3. Проверьте и перезагрузите Caddy, затем проверьте /dex-relay/dex/health извне.

Решение: за nginx все клиенты DEX ограничиваются по частоте вместе

  1. Убедитесь, что блок /dex-relay/ отправляет заголовок:
    grep -n 'X-Forwarded-For' /etc/nginx/sites-enabled/*
  2. Если его нет, добавьте proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; в блок (§11), затем выполните nginx -t и systemctl reload nginx.

Решение: служба остаётся остановленной после штатного завершения

  1. Переведите юнит на Restart=always (§7).
  2. Запустите узел:
    systemctl start parlons-node

Решение: вспомогательный процесс keets падает с EPERM

  1. Добавьте AF_NETLINK в юнит:
    sed -i 's/^RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX$/RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX AF_NETLINK/' /etc/systemd/system/parlons-node.service
  2. Перезагрузите конфигурацию и перезапустите узел:
    systemctl daemon-reload
    systemctl restart parlons-node

Решение: аккаунт так и не сообщает «attached»

  1. Проверьте исходящий доступ в интернет и часы:
    curl -sI https://github.com | head -1
    timedatectl | grep synchronized
  2. Если сервер блокирует исходящий трафик, разрешите порты ретрансляторов (§25).
  3. После перезапуска найдите в журнале account up: attached to N relay(s).

Решение: зависший процесс

  1. Найдите PID. Никогда не используйте pkill -f parlons-node.jar: шаблон может совпасть с вашей собственной SSH-сессией:
    systemctl show -p MainPID parlons-node
  2. Попросите процесс остановиться, а принудительно завершайте, только если он не остановился:
    kill <pid>
    sleep 15
    kill -0 <pid> 2>/dev/null && kill -9 <pid>
  3. Снова запустите его командой systemctl start parlons-node.

27Чек-лист безопасности


28Настольные приложения, в которые встроен этот jar

parlons-node.jar также служит движком узла внутри настольных приложений. Они скачивают релиз node-v* в свои ресурсы (scripts/fetch-parlons-node-jar.sh) и запускают его со своими флагами.

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


29Глоссарий

ТерминЗначение
Административный RPC (admin RPC)HTTP-адрес узла на p2p+4, доступный только через loopback, без аутентификации, принимающий любые команды.
Архивный узелУзел Minima, хранящий достаточно истории (и MegaMMR) для пересинхронизаций через megammrsync.
Bearer-токенУчётные данные шлюза в gateway-token.txt. Позволяют только чтение и рассылку.
Начальные пиры (bootstrap peers)Первые ретрансляторы, с которыми связывается кейп (parlons.relay.peers или встроенный в код список).
Кейп (cape)Ретранслятор Maxima, работающий внутри узла. Так же называется DEX-кейп ретранслятора.
КурсорЧисло в DEX-ретрансляторе, которое только растёт. Клиенты запрашивают изменения «с момента» курсора.
DexiconDEX-приложение, книгу заявок которого переносит DEX-кейп ретранслятора.
КонвертПодписанная JSON-заявка или сообщение, принятые DEX-ретранслятором.
ШлюзПрокси POST /cmd со списком разрешённых команд, через который телефоны читают данные кошелька и рассылают транзакции.
HeartbeatСтрока состояния, которую узел пишет в журнал каждые 30 с.
IBDInitial blockchain download — первая синхронизация. Она не заполняет MegaMMR.
identity.txtЗакреплённая фраза, из которой выводятся личность Maxima узла и MAX# аккаунта. Секрет уровня кошелька.
keets / KeetChatОдноранговая (peer-to-peer) система чатов. Узел соединяется с ней через вспомогательный процесс на Node.js.
Длинный опрос (long-poll)HTTP-запрос, который сервер держит открытым (здесь до 25 с), пока не появятся новости.
MAX#Постоянный адрес аккаунта, которым можно делиться.
MegaMMRРежим Minima, в котором хранятся доказательства для каждой монеты, так что узел может отвечать по любому адресу.
Mesh-сетьСеть ретрансляторов для пересылки запросов к каталогу и копирования записей каталога.
MDS / MiniHUBСистема MiniDapp в Minima и её интерфейс-хаб.
MxUSDТокен Minima, привязанный к доллару, идентификатор токена 0x7D39745FBD29049BE29850B55A18BF550E4D442F930F86266E34193D89042A90. Платёжные функции аккаунта распознают его по этому идентификатору.
Личность Mx…Публичная личность Maxima ретранслятора или аккаунта.
ПанельЛокальный веб-интерфейс и API аккаунта на 127.0.0.1:9587.
Хост пулаРетранслятор, который отвечает на открытые запросы к каталогу и участвует в mesh-сети.
REDIAL_MS / TTL_MSИнтервал повторного подключения ретранслятора (10 минут) и срок жизни проверенных пиров (2 часа).
Корневой узел (rootnode)Пир Minima, через который узел впервые находит сеть.
Общий портРетранслятор, работающий на P2P-порту Minima (parlons.relay.port=shared).
STUNНебольшая UDP-служба на порту ретранслятора, которая сообщает клиентам их публичный адрес.
Хост гостевых аккаунтов (tenants host)Отдельная служба parlons-cloud, которая запускает гостевые аккаунты рядом с узлом.
TLS-проксиВеб-сервер (Caddy, nginx или Apache), который завершает HTTPS и перенаправляет запросы на loopback-порты.
Хранилище (vault)Команда и хранилище Minima, где находится сид-фраза кошелька узла.
Проверенный пирРетранслятор, заявленный адрес которого подтверждён обратным подключением.
Наверх ↑