Pular para o conteúdo principal

Self-hosting do Resource Pack

O ResourcePackManager inclui seu próprio pequeno servidor HTTP. Quando autoHost: true (o padrão) e preferSelfHost: true (o padrão), o plugin tenta hospedar o pack unificado a partir da mesma JVM do próprio servidor Minecraft — sem host de arquivos externo, sem servidor web separado, sem colar URL manualmente.

Esta página cobre como esse caminho de self-host funciona, o que as checagens de sanidade fazem, como a porta e o hostname são escolhidos, e o que configurar quando os padrões não servirem para a sua configuração.

Se, em vez disso, você quiser hospedar o zip por meio do seu próprio servidor web existente, fora do RSPM, consulte a seção sobre autoHost: false na página de Solução de Problemas.

Árvore de Decisão de Entrega

Quando um jogador entra, o RSPM escolhe uma URL de entrega usando esta precedência:

  1. selfHostForce: true — direto para o self-host, sem probes, sem upload remoto. Principalmente para testar o caminho de self-host. Ignora todas as outras flags.
  2. preferSelfHost: true E selfHostEnabled: true E não está em modo de rede — tenta o self-host com três checagens de sanidade (veja abaixo). Se todas passarem, compromete-se com o self-host. Se alguma falhar, recorre ao caminho remoto.
  3. Caso contrário — faz upload do pack para https://magmaguy.com/rsp/ e anuncia essa URL. Se o upload falhar ou a checagem de SHA1 reportar SESSION_NOT_FOUND, recorre ao self-host (assumindo selfHostEnabled: true).

Uma vez de posse de uma URL, o RSPM usa a API de múltiplos packs do Minecraft, então seu pack Java pode coexistir com outros packs enviados pelo servidor. O descritor atual do plugin Bukkit exige Minecraft 1.21.4 ou mais recente.

As Três Checagens de Sanidade

Quando preferSelfHost: true, o RSPM executa estas checagens em ordem antes de se comprometer com o self-host:

Camada 1 — Checagem heurística no host externo resolvido

Se o host resolvido (veja "Detecção de Host Externo" abaixo) for RFC1918 (10.*, 172.16-31.*, 192.168.*), loopback (127.*), link-local (169.254.*) ou não especificado (0.0.0.0), o self-host não tem como funcionar para clientes da internet. Pula imediatamente e usa a hospedagem remota.

Isso captura o modo de falha muito comum de "a busca pelo ipify falhou e recorreu ao IP de LAN".

Camada 2 — Self-probe em localhost

Abre uma requisição HEAD para http://127.0.0.1:<port>/rspm.zip, verifica HTTP 200 e corpo não vazio. Captura:

  • colisões de bind de porta (algo mais está na porta escolhida)
  • arquivo de pack ausente (a rota está registrada mas o zip ainda não está no disco)
  • bugs de registro de rota

Tem timeout agressivo (3 s) para que um probe lento não arraste o boot.

Camada 3 — Probe de alcançabilidade externa

Faz POST da URL anunciada para POST /rsp/probe no hoster do magmaguy.com. O hoster busca a URL a partir de um ponto de observação público (com proteções contra SSRF e um timeout apertado) e reporta de volta se ela está acessível.

Captura o modo de falha de produção mais comum: o servidor tem um IP público mas a porta HTTP não está encaminhada no roteador ou firewall. A Camada 2 passa (o servidor responde em 127.0.0.1), mas nenhum cliente real conseguiria baixar o pack.

Política de decisão sobre os resultados do probe:

  • reachable=true → clientes externos conseguem alcançar nossa URL. Compromete-se com o self-host.
  • reachable=false → clientes externos não conseguem. Desmonta o self-host e usa a hospedagem remota (que é universalmente acessível a partir do magmaguy.com).
  • a própria comunicação do probe falha (IOException) → não foi possível verificar em nenhum sentido. Por padrão, mantém o self-host: recusá-lo por incapacidade de fazer o probe seria paradoxal, pois o caminho remoto também precisa do magmaguy.com.

O que as checagens ainda não detectam

O caso de borda do NAT-hairpin, em que a porta está aberta para a internet pública (a Camada 3 passa) mas o próprio roteador do operador não faz o tráfego retornar de dentro da LAN. Clientes externos funcionam, mas o operador testando a partir da mesma máquina falha.

Para um teste rápido na máquina host, defina preferSelfHost: false e use o fallback remoto, ou teste a URL pública a partir de uma rede celular/externa. Para uma configuração de self-host permanente, use DNS split-horizon (o mesmo hostname público resolve para o endereço de LAN do servidor dentro da sua rede). Não defina selfHostExternalHost como 127.0.0.1: hosts de loopback e privados são rejeitados pela checagem de sanidade de host público e não conseguem servir clientes externos.

Resolução de Portas

Duas configurações interagem:

  • selfHostPort — porta explícita (qualquer inteiro positivo) ou -1 (padrão) para auto-derivação.
  • networkHttpOffset-v2 — só é consultado quando selfHostPort = -1. Adicionado à porta do servidor Minecraft para derivar a porta HTTP. Padrão 1. (Em redes com proxy, esse mesmo valor também é o palpite de fallback do proxy para a porta HTTP de um backend — veja abaixo.)

O padrão é selfHostPort: -1 + networkHttpOffset-v2: 1, então:

  • porta MC 25565 → porta HTTP 25566
  • porta MC 25584 → porta HTTP 25585

Isso escalona automaticamente as portas HTTP entre backends em uma rede de host único sem nenhuma configuração do admin — cada backend já tem uma porta MC única, então cada um recebe uma porta HTTP única.

Por que offset 1?

A maioria das hospedagens compartilhadas / gerenciadas de Minecraft (painéis baseados em Pterodactyl, etc.) aloca uma faixa estreita de portas por container (geralmente apenas 4 a 10 portas). Offsets maiores caem fora da faixa e o firewall do host bloqueia silenciosamente a porta HTTP. O offset 1 cabe até em alocações bem apertadas.

Admins que fazem self-host com controle total de portas podem aumentar isso para qualquer valor. Em uma rede com proxy, o backend anuncia automaticamente ao proxy a porta HTTP exata em que se vinculou, então o proxy acompanha mesmo que você mude o offset ou defina um selfHostPort explícito. Aumentar o network-http-offset-v2 do proxy para coincidir só importa como fallback para a breve janela antes de um backend ter anunciado (ou se o anúncio não consegue alcançar o proxy).

Atenção: colisão com RCON

Se o seu host habilita RCON por padrão em porta MC + 1, escolha o offset 2 ou 3 para evitar uma colisão de portas. Verifique rcon.port= no server.properties.

Chave de config versionada

A configuração no config.yml se chama literalmente networkHttpOffset-v2. A chave v1 era networkHttpOffset, com padrão 100 — esse padrão quebrava em hospedagens compartilhadas / gerenciadas, onde cada container de jogo recebe apenas ~4 a 10 portas consecutivas; MC + 100 caía fora da faixa, o servidor HTTP se vinculava internamente mas o firewall do host descartava o tráfego externo, e o proxy recebia um CONNECT_FAILED silencioso para sempre. A v2 vem com padrão 1, então MC + 1 fica bem dentro até da alocação de container mais estreita.

Se você atualizar a partir da v1, a chave v1 morta fica na sua config como um artefato inofensivo até você limpá-la — o RSPM intencionalmente não a lê.

Detecção de Host Externo

selfHostExternalHost controla qual hostname os clientes veem na URL. Deixe vazio (padrão) para auto-detecção nesta ordem de prioridade:

  1. api.ipify.org / checkip.amazonaws.com — retorna o IPv4 público deste host. Cacheado uma vez por /rspm reload para que os serviços de IP não sejam sobrecarregados.
  2. Bukkit.getIp() — o endereço de bind do servidor, quando não vazio e não 0.0.0.0. Geralmente um endereço de LAN.
  3. InetAddress.getLocalHost() — melhor esforço.
  4. localhost — fallback de último recurso. Clientes fora da máquina não alcançarão isso.

Se a auto-detecção cair em um endereço não roteável e preferSelfHost: true, a checagem heurística da Camada 1 falha e o plugin muda para a hospedagem remota.

Para a configuração de self-host mais confiável, defina selfHostExternalHost explicitamente com o seu hostname público (por exemplo, play.example.com). Isso pula a detecção via ipify/AWS por completo e o probe roda contra o valor explícito.

Referência de Configuração

# 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

O Que o Console Realmente Imprime

O RSPM deliberadamente imprime uma linha sobre hospedagem em uma inicialização normal — o resultado, não o percurso:

[ResourcePackManager] Resource pack is live via self-hosting — http://play.example.com:25566/rspm.zip

ou, quando o caminho remoto venceu:

[ResourcePackManager] Resource pack is live via automatic hosting — https://magmaguy.com/rsp/<uuid>

Essa linha é impressa uma vez a cada vez que um caminho de entrega é inicializado do zero, não em retentativas de jogadores nem em ticks de keep-alive. Um reload cujo pack não mudou pode reutilizar o registro de hospedagem existente em vez de imprimir um novo resultado.

Checagens de sanidade que falham não são avisos. Um probe que falha é uma condição da qual o RSPM se recupera sozinho, então é registrado como detalhe, e não como falha, e cada mensagem diz isso explicitamente (Self-host check: local pack link is not public. This is OK.). Você não verá isso a menos que peça — um aviso sobre algo que o plugin já tratou passa a impressão de falha e faz operadores perseguirem um problema inexistente.

Para ver toda a cadeia de decisão — qual checagem falhou, a URL do probe, o código de motivo, cada pack preparado e cada cluster mesclado — execute:

/rspm verbose on

Em seguida, /rspm reload. Esta é a chave a acionar antes de abrir um relatório de bug sobre hospedagem. O comando grava verboseLogging: true no config.yml e a configuração persiste entre reinícios, então execute /rspm verbose off quando terminar; editar a chave da config à mão tem exatamente o mesmo efeito.

Note que verboseLogging cobre a preparação do pack e a hospedagem. O conversor Bedrock tem sua própria chave separada, bedrockConverterDebug — veja Conversão Bedrock.

Rotas do Servidor HTTP do Backend

O servidor HTTP integrado sempre serve o zip do pack em:

http://<host>:<port>/rspm.zip

Em modo de rede (o RSPM está por trás de um proxy Velocity / BungeeCord / Waterfall), rotas adicionais são registradas para o plugin do proxy buscar:

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)

As rotas do pack e dos artefatos Bedrock são respaldadas por arquivos: cada rota lê o seu arquivo atualizado a cada requisição, então um re-mix que reescreve o mesmo caminho é detectado automaticamente sem reiniciar o servidor HTTP. As rotas Bedrock usam ETags fortes e também suportam If-Modified-Since por compatibilidade, então pollings do proxy sem mudanças recebem 304 com praticamente zero de banda. Essas rotas retornam 404 de forma limpa quando o arquivo subjacente está ausente (por exemplo, antes da primeira mescla ser concluída). A rota de atualização é protegida separadamente por um bearer token derivado da chave de rede compartilhada e só fica disponível quando um jar de atualização válido pode ser oferecido.

Verificando se o Self-host Está Ativo

/rspm status mostra:

  • Active delivery: SELF-HOSTED — o self-host está em uso
  • Active delivery: REMOTE (magmaguy.com) — o auto-host remoto está em uso
  • URL: ... — a URL real que os clientes verão
  • Resolved external host — para o que selfHostExternalHost resolveu
  • Public IP (auto-detected) — o que o ipify/AWS reportou, se algo
  • selfHostPort — automático vs explícito, e o valor resolvido

Se você esperava self-host mas vê remoto, /rspm status é o lugar para olhar — o log de boot fica silencioso sobre falhas de probe autocorrigidas, por design. Execute /rspm verbose on e /rspm reload para ver qual checagem de sanidade falhou e por quê.

Erros Comuns

  • Confiar no probe da Camada 3 com um roteador sem suporte a hairpin — o probe roda a partir do ponto de observação do magmaguy.com, então não consegue capturar o caso em que clientes externos funcionam mas a própria LAN do operador não faz o tráfego retornar. Teste a partir de um celular no dados móveis se estiver em dúvida.
  • Aumentar o networkHttpOffset-v2 para além da faixa de portas do seu provedor de hospedagem — o sintoma é um CONNECT_FAILED silencioso para sempre do lado do proxy. Os backends anunciam ao proxy sua porta real vinculada, mas o servidor HTTP ainda precisa se vincular a uma porta acessível e o proxy ainda precisa conseguir alcançá-la; se mcPort + offset cair fora da faixa de portas alocada do seu container, o bind/firewall falha independentemente do anúncio. Verifique se a porta está na faixa alocada do seu container antes de aumentar o offset.