Самостоятельный хостинг ресурс-пака
ResourcePackManager поставляется с собственным небольшим HTTP-сервером. Когда autoHost: true (по умолчанию) и preferSelfHost: true (по умолчанию), плагин пытается хостить собранный пак из той же JVM, что и сам Minecraft-сервер — без внешнего файлового хоста, без отдельного веб-сервера, без ручной вставки URL.
Эта страница описывает, как работает этот путь самостоятельного хостинга, что делают проверки исправности, как выбирается порт и hostname, и что настраивать, когда значения по умолчанию вам не подходят.
Если вместо этого вы хотите хостить zip через свой собственный существующий веб-сервер вне RSPM, см. раздел про autoHost: false на странице устранения неполадок.
Дерево решений по доставке
Когда игрок подключается, RSPM выбирает URL для доставки по такому приоритету:
selfHostForce: true— прямой self-host, без проверок, без удалённой загрузки. Главным образом для тестирования self-host пути. Обходит все остальные флаги.preferSelfHost: trueИselfHostEnabled: trueИ не в сетевом режиме — попробовать self-host с тремя проверками исправности (см. ниже). Если все проходят, фиксируется self-host. Если хоть одна не прошла, откат на удалённый путь.- Иначе — загрузить пак на
https://magmaguy.com/rsp/и анонсировать этот URL. Если загрузка не удалась или проверка SHA1 сообщаетSESSION_NOT_FOUND, откат на self-host (при условииselfHostEnabled: true).
Как только URL получен, RSPM использует multi-pack API Minecraft, поэтому его Java-пак может сосуществовать с другими паками, отправляемыми сервером. Текущий дескриптор Bukkit-плагина требует Minecraft 1.21.4 или новее.
Три проверки исправности
Когда preferSelfHost: true, RSPM выполняет эти проверки по порядку перед тем, как зафиксировать self-host:
Уровень 1 — эвристическая проверка разрешённого внешнего хоста
Если разрешённый хост (см. «Определение внешнего хоста» ниже) — это RFC1918 (10.*, 172.16-31.*, 192.168.*), loopback (127.*), link-local (169.254.*) или unspecified (0.0.0.0), self-host никак не сможет работать для интернет-клиентов. Сразу пропустить и использовать удалённый хостинг.
Это ловит очень распространённый сценарий «ipify-запрос не удался, откатился на LAN-IP».
Уровень 2 — локальная самопроверка
Открывается HEAD-запрос на http://127.0.0.1:<port>/rspm.zip, проверяется HTTP 200 и непустое тело. Ловит:
- коллизии при привязке порта (что-то другое уже на выбранном порту)
- отсутствующий файл пака (маршрут зарегистрирован, но zip ещё не на диске)
- баги регистрации маршрутов
Агрессивный таймаут (3 с), чтобы медленная проверка не затягивала загрузку.
Уровень 3 — проверка внешней доступности
POST анонсированного URL на POST /rsp/probe на хостере magmaguy.com. Хостер скачивает URL с публичной vantage point (с SSRF-защитой и жёстким таймаутом) и отчитывается, доступен ли он.
Ловит наиболее распространённую боевую проблему: у сервера есть публичный IP, но HTTP-порт не проброшен на роутере или файрволе. Уровень 2 проходит (сервер отвечает на 127.0.0.1), но ни один реальный клиент никогда не сможет скачать пак.
Политика принятия решений по результатам проверки:
- reachable=true → внешние клиенты могут достучаться до нашего URL. Фиксируется self-host.
- reachable=false → внешние клиенты не могут. Сворачивается self-host, используется удалённый хостинг (который универсально доступен с magmaguy.com).
- сама связь проверки не удалась (IOException) → не удалось проверить никак. По умолчанию оставляется self-host: отказывать из-за невозможности проверки было бы парадоксально, потому что удалённому пути magmaguy.com тоже нужен.
Что проверки всё ещё не обнаруживают
Граничный случай NAT-hairpin, когда порт открыт в публичный интернет (Уровень 3 проходит), но собственный роутер оператора не делает loopback трафика обратно изнутри LAN. Внешние клиенты работают, но оператор, тестирующий с той же машины, получает отказ.
Для быстрой проверки с хост-машины выставьте preferSelfHost: false и используйте удалённый резерв либо проверьте публичный URL из сотовой/внешней сети. Для постоянной self-host установки используйте split-horizon DNS (то же публичное имя хоста внутри вашей сети резолвится в LAN-адрес сервера). Не выставляйте selfHostExternalHost в 127.0.0.1: loopback и приватные хосты отклоняются проверкой публичности хоста и не могут обслуживать внешних клиентов.
Разрешение порта
Две настройки взаимодействуют:
selfHostPort— явный порт (любое положительное целое) или-1(по умолчанию) для авто-вывода.networkHttpOffset-v2— учитывается только когдаselfHostPort = -1. Прибавляется к порту Minecraft-сервера для вывода HTTP-порта. По умолчанию1. (В прокси-сетях это же значение является ещё и запасной догадкой прокси о HTTP-порте бэкенда — см. ниже.)
По умолчанию selfHostPort: -1 + networkHttpOffset-v2: 1, поэтому:
- MC порт 25565 → HTTP порт 25566
- MC порт 25584 → HTTP порт 25585
Это автоматически разводит HTTP-порты по бэкендам в одноузловой сети без какой-либо административной настройки — у каждого бэкенда уже есть уникальный MC-порт, поэтому каждый получает уникальный HTTP-порт.
Почему смещение 1?
Большинство shared / managed Minecraft-хостингов (панели на базе Pterodactyl и т. п.) выделяют узкий диапазон портов на контейнер (часто всего 4–10 портов). Большие смещения уходят за границы диапазона, и файрвол хостинга молча блокирует HTTP-порт. Смещение 1 помещается даже в самые узкие выделения.
Самостоятельные администраторы с полным контролем над портами могут увеличить это до любого значения. В прокси-сети бэкенд автоматически объявляет прокси точный HTTP-порт, на который привязался, поэтому прокси следует за ним, даже если вы измените смещение или зададите явный selfHostPort. Увеличивать network-http-offset-v2 прокси для совпадения имеет смысл только как запасной вариант на короткий промежуток до того, как бэкенд объявил порт (или если объявление не может достичь прокси).
Осторожно: коллизия с RCON
Если ваш хостинг включает RCON по умолчанию на MC port + 1, выберите смещение 2 или 3 во избежание коллизии портов. Проверьте server.properties на rcon.port=.
Версионированный ключ конфига
Настройка в config.yml буквально называется networkHttpOffset-v2. Ключ v1 был networkHttpOffset с дефолтом 100 — этот дефолт ломался на shared / managed-хостингах, где каждый игровой контейнер получает всего ~4–10 последовательных портов, MC + 100 уходило за пределы диапазона, HTTP-сервер привязывался внутренне, но файрвол хостинга отбрасывал внешний трафик, и прокси получал молчаливый CONNECT_FAILED навсегда. v2 поставляется с дефолтом 1, поэтому MC + 1 остаётся хорошо внутри даже самых узких контейнерных выделений.
Если вы обновляетесь с v1, мёртвый ключ v1 сидит в вашем конфиге как безвредный артефакт, пока вы не уберёте его вручную — RSPM намеренно его не читает.
Определение внешнего хоста
selfHostExternalHost контролирует, какое имя хоста клиенты видят в URL. Оставьте пустым (по умолчанию), чтобы авто-определить в таком порядке приоритета:
- api.ipify.org / checkip.amazonaws.com — возвращает публичный IPv4 этого хоста. Кешируется один раз на
/rspm reload, чтобы IP-сервисы не нагружались. Bukkit.getIp()— bind-адрес сервера, когда непустой и не0.0.0.0. Обычно LAN-адрес.InetAddress.getLocalHost()— best-effort.localhost— последний резерв. Клиенты вне коробки сюда не достучатся.
Если авто-определение приводит к не-маршрутизируемому адресу и preferSelfHost: true, эвристическая проверка Уровня 1 проваливается, и плагин переключается на удалённый хостинг.
Для максимально надёжной настройки self-host выставьте selfHostExternalHost явно на ваше публичное имя хоста (например, play.example.com). Это полностью пропускает определение через ipify/AWS, и проверка запускается против явного значения.
Справочник по конфигурации
# Whether the built-in HTTP server may be used as a delivery path at all.
# When false, ordinary self-host attempts are disabled. selfHostForce still overrides it.
selfHostEnabled: true
# Port for the self-host HTTP server.
# -1 (default) = auto-derive: HTTP port = Minecraft server port + networkHttpOffset-v2.
# Set to any positive value to force an explicit port.
selfHostPort: -1
# Added to the Minecraft server port when selfHostPort = -1.
# Default 1 (MC 25565 -> HTTP 25566). On a proxy network this is only a FALLBACK:
# the backend announces the exact HTTP port it actually bound to the proxy, so
# you no longer have to match this against the proxy's network-http-offset-v2.
networkHttpOffset-v2: 1
# Public hostname or IP clients use to reach the self-host server.
# Leave empty for auto-detect (api.ipify.org / checkip.amazonaws.com).
selfHostExternalHost: ""
# Try self-host FIRST with three sanity checks, fall back to remote if any fail.
# When false, use the legacy order: remote upload first, self-host only on upload failure.
preferSelfHost: true
# Skip ALL other delivery paths and force self-hosting.
# Bypasses sanity checks AND remote upload. Mainly for testing.
selfHostForce: false
# Print every step of pack preparation and the hosting handshake.
# Default false — see "What the console actually prints" below.
# `/rspm verbose on|off` flips this same key at runtime and saves it here.
verboseLogging: false
Что консоль на самом деле печатает
RSPM намеренно печатает одну строку о хостинге при обычной загрузке — результат, а не путь к нему:
[ResourcePackManager] Resource pack is live via self-hosting — http://play.example.com:25566/rspm.zip
или, когда победил удалённый путь:
[ResourcePackManager] Resource pack is live via automatic hosting — https://magmaguy.com/rsp/<uuid>
Эта строка печатается один раз при каждой свежей инициализации пути доставки, а не при повторных попытках игроков или тиках keep-alive. Перезагрузка, при которой пак не изменился, может переиспользовать существующую регистрацию хостинга вместо того, чтобы печатать новый результат.
Непройденные проверки исправности — не предупреждения. Непрошедшая проверка — это условие, из которого RSPM восстанавливается сам, поэтому оно логируется как деталь, а не как сбой, и каждое сообщение прямо об этом говорит (Self-host check: local pack link is not public. This is OK.). Вы его не увидите, пока не попросите — предупреждение о том, что плагин уже обработал, читается как сбой и заставляет операторов гоняться за несуществующей проблемой.
Чтобы увидеть всю цепочку решений — какая проверка не прошла, URL пробы, код причины, каждый подготовленный пак и каждый объединённый кластер — выполните:
/rspm verbose on
Затем выполните /rspm reload. Это тот переключатель, который надо включить до того, как открывать баг-репорт по хостингу. Команда записывает verboseLogging: true в config.yml, и настройка сохраняется между перезапусками, поэтому выполните /rspm verbose off, когда закончите; ручное изменение ключа в конфиге даёт ровно тот же эффект.
Учтите, что verboseLogging охватывает подготовку пака и хостинг. У Bedrock-конвертера есть собственный отдельный переключатель, bedrockConverterDebug — см. Преобразование в Bedrock.
Маршруты бэкенд-HTTP-сервера
Встроенный HTTP-сервер всегда раздаёт zip пака по адресу:
http://<host>:<port>/rspm.zip
В сетевом режиме (RSPM находится за Velocity / BungeeCord / Waterfall прокси) регистрируются дополнительные маршруты, из которых забирает данные прокси-плагин:
http://<host>:<port>/bedrock.zip # the Bedrock-converted pack
http://<host>:<port>/mappings.json # the Geyser custom-mappings JSON
http://<host>:<port>/rspm-update.jar # the universal RSPM update jar (authenticated)
Маршруты пака и Bedrock-артефактов file-backed: каждый маршрут читает свой файл свежим при каждом запросе, поэтому пересборка, переписывающая тот же путь, подхватывается автоматически без перезапуска HTTP-сервера. Bedrock-маршруты используют строгие ETag и для совместимости поддерживают If-Modified-Since, поэтому опросы прокси без изменений получают 304 с практически нулевым трафиком. Эти маршруты корректно возвращают 404, когда подлежащий файл отсутствует (например, до завершения первой сборки). Маршрут обновления отдельно защищён bearer-токеном, выводимым из общего сетевого ключа, и доступен только тогда, когда есть валидный jar обновления, который можно предложить.
Проверка, что self-host активен
/rspm status показывает:
Active delivery: SELF-HOSTED— self-host используетсяActive delivery: REMOTE (magmaguy.com)— удалённый авто-хостинг используетсяURL: ...— фактический URL, который увидят клиентыResolved external host— во что разрешилосьselfHostExternalHostPublic IP (auto-detected)— что вернули ipify/AWS, если что-тоselfHostPort— авто vs явный, и разрешённое значение
Если вы ожидали self-host, но видите удалённый, смотреть нужно в /rspm status — лог загрузки намеренно молчит о самоустранённых сбоях проб. Выполните /rspm verbose on и /rspm reload, чтобы увидеть, какая проверка исправности не прошла и почему.
Типичные ошибки
- Доверять проверке Уровня 3 при сломанном hairpin на роутере — проверка идёт с vantage point magmaguy.com, поэтому она не может поймать случай, когда внешние клиенты работают, но собственная LAN оператора не делает loopback. Тестируйте с телефона по сотовой, если не уверены.
- Увеличение
networkHttpOffset-v2за пределы диапазона портов вашего хостинг-провайдера — симптом — молчаливый CONNECT_FAILED навсегда на стороне прокси. Бэкенды объявляют прокси свой реальный привязанный порт, но HTTP-серверу всё равно нужно привязаться к доступному порту, а прокси всё равно нужно иметь возможность до него достучаться; еслиmcPort + offsetуходит за пределы выделенной полосы портов вашего контейнера, привязка/файрвол падает независимо от объявления. Проверьте, что порт находится в выделенной полосе вашего контейнера, прежде чем увеличивать смещение.