Saltar al contenido principal

Autoalojar el paquete de recursos

ResourcePackManager incluye su propio pequeño servidor HTTP. Cuando autoHost: true (el valor por defecto) y preferSelfHost: true (el valor por defecto), el plugin intenta alojar el paquete fusionado desde la misma JVM que el propio servidor de Minecraft — sin host de archivos externo, sin servidor web separado, sin pegar URLs manualmente.

Esta página cubre cómo funciona esa ruta de autoalojamiento, qué hacen las comprobaciones de cordura, cómo se eligen el puerto y el hostname, y qué configurar cuando los valores por defecto no encajan con tu configuración.

Si, en cambio, quieres alojar el zip a través de tu propio servidor web ya existente fuera de RSPM, consulta la sección sobre autoHost: false en la página de Solución de problemas.

Árbol de decisión de entrega

Cuando un jugador se conecta, RSPM elige una URL de entrega usando esta precedencia:

  1. selfHostForce: true — directo al autoalojamiento, sin sondeos, sin subida remota. Principalmente para probar la ruta de autoalojamiento. Pasa por encima de todos los demás flags.
  2. preferSelfHost: true Y selfHostEnabled: true Y no en modo de red — intenta autoalojar con tres comprobaciones de cordura (ver abajo). Si todas pasan, se compromete con el autoalojamiento. Si alguna falla, recurre a la ruta remota.
  3. En caso contrario — sube el paquete a https://magmaguy.com/rsp/ y anuncia esa URL. Si la subida falla o la comprobación SHA1 informa SESSION_NOT_FOUND, recurre al autoalojamiento (suponiendo selfHostEnabled: true).

Una vez que tiene una URL, RSPM usa la API de varios paquetes de Minecraft, de modo que su paquete Java puede coexistir con otros paquetes enviados por el servidor. El descriptor actual del plugin de Bukkit requiere Minecraft 1.21.4 o posterior.

Las tres comprobaciones de cordura

Cuando preferSelfHost: true, RSPM ejecuta estas comprobaciones en orden antes de comprometerse con el autoalojamiento:

Capa 1 — Comprobación heurística sobre el host externo resuelto

Si el host resuelto (consulta "Detección del host externo" abajo) es RFC1918 (10.*, 172.16-31.*, 192.168.*), loopback (127.*), link-local (169.254.*), o no especificado (0.0.0.0), el autoalojamiento no puede funcionar para clientes de internet. Se omite de inmediato y se usa el alojamiento remoto.

Esto detecta el modo de fallo muy común de "la búsqueda en ipify falló, recurrió a la IP de LAN".

Capa 2 — Sondeo a sí mismo en localhost

Abre una solicitud HEAD a http://127.0.0.1:<port>/rspm.zip, verifica HTTP 200 y un cuerpo no vacío. Detecta:

  • colisiones de enlace de puerto (otra cosa ocupa el puerto elegido)
  • archivo de paquete faltante (la ruta está registrada pero el zip aún no está en disco)
  • errores de registro de rutas

Agota el tiempo de forma agresiva (3 s) para que un sondeo lento no pueda alargar el arranque.

Capa 3 — Sondeo de accesibilidad externa

Hace POST de la URL anunciada a POST /rsp/probe en el hoster de magmaguy.com. El hoster obtiene la URL desde un punto de observación público (con protecciones SSRF y un timeout ajustado) e informa de vuelta si es accesible.

Detecta el modo de fallo de producción más común: el servidor tiene una IP pública pero el puerto HTTP no está reenviado en el router o el firewall. La Capa 2 pasa (el servidor responde en 127.0.0.1), pero ningún cliente real podría descargar nunca el paquete.

Política de decisión sobre los resultados del sondeo:

  • reachable=true → los clientes externos pueden alcanzar nuestra URL. Se compromete con el autoalojamiento.
  • reachable=false → los clientes externos no pueden. Desmonta el autoalojamiento y usa el alojamiento remoto (que es universalmente accesible desde magmaguy.com).
  • la propia comunicación del sondeo falla (IOException) → no se pudo verificar en ningún sentido. Por defecto mantiene el autoalojamiento: negarse por incapacidad de sondear sería paradójico, porque la ruta remota también necesita magmaguy.com.

Lo que las comprobaciones aún no detectan

El caso límite de NAT-hairpin donde el puerto está abierto a internet público (la Capa 3 pasa) pero el propio router del operador no devuelve el tráfico desde dentro de la LAN. Los clientes externos funcionan, pero el operador que prueba desde la misma máquina falla.

Para una prueba rápida desde la máquina host, establece preferSelfHost: false y usa el respaldo remoto, o prueba la URL pública desde una red móvil/externa. Para una configuración autoalojada permanente, usa DNS de horizonte dividido (el mismo hostname público resuelve a la dirección LAN del servidor dentro de tu red). No establezcas selfHostExternalHost a 127.0.0.1: los hosts de loopback y privados los rechaza la comprobación de cordura del host público y no pueden servir a clientes externos.

Resolución de puertos

Interactúan dos opciones:

  • selfHostPort — puerto explícito (cualquier entero positivo) o -1 (por defecto) para autoderivación.
  • networkHttpOffset-v2 — solo se consulta cuando selfHostPort = -1. Se añade al puerto del servidor de Minecraft para derivar el puerto HTTP. Por defecto 1. (En redes proxy este mismo valor es también la conjetura de respaldo del proxy para el puerto HTTP de un backend — ver abajo.)

El valor por defecto es selfHostPort: -1 + networkHttpOffset-v2: 1, por lo que:

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

Esto escalona automáticamente los puertos HTTP entre backends en una red de un solo host sin ninguna configuración por parte del administrador — cada backend ya tiene un puerto MC único, por lo que cada uno obtiene un puerto HTTP único.

¿Por qué desplazamiento 1?

La mayoría de los alojamientos de Minecraft compartidos / gestionados (paneles basados en Pterodactyl, etc.) asignan un rango de puertos estrecho por contenedor (a menudo solo 4–10 puertos). Los desplazamientos mayores caen fuera del rango y el firewall del host bloquea silenciosamente el puerto HTTP. El desplazamiento 1 cabe incluso en asignaciones ajustadas.

Los administradores autoalojados con control total de puertos pueden subirlo a cualquier valor. En una red proxy, el backend anuncia automáticamente al proxy el puerto HTTP exacto al que se enlazó, por lo que el proxy lo sigue incluso si cambias el desplazamiento o estableces un selfHostPort explícito. Subir el network-http-offset-v2 del proxy para que coincida solo importa como respaldo durante la breve ventana antes de que un backend haya anunciado (o si el anuncio no puede alcanzar el proxy).

Cuidado: colisión con RCON

Si tu host activa RCON por defecto en MC port + 1, elige el desplazamiento 2 o 3 para evitar una colisión de puertos. Comprueba server.properties en busca de rcon.port=.

Clave de configuración versionada

La opción en config.yml se llama literalmente networkHttpOffset-v2. La clave v1 era networkHttpOffset con valor por defecto 100 — ese valor por defecto se rompía en alojamientos compartidos / gestionados donde cada contenedor de juego solo obtiene ~4–10 puertos consecutivos, MC + 100 caía fuera del rango, el servidor HTTP se enlazaba internamente pero el firewall del host descartaba el tráfico externo, y el proxy recibía un CONNECT_FAILED silencioso para siempre. La v2 viene con el valor por defecto 1, de modo que MC + 1 se mantiene bien dentro incluso de las asignaciones de contenedor más estrechas.

Si actualizas desde la v1, la clave v1 muerta queda en tu config como un artefacto inofensivo hasta que la limpies — RSPM intencionadamente no la lee.

Detección del host externo

selfHostExternalHost controla qué hostname ven los clientes en la URL. Déjalo vacío (por defecto) para autodetectar en este orden de prioridad:

  1. api.ipify.org / checkip.amazonaws.com — devuelve la IPv4 pública de este host. Se almacena en caché una vez por /rspm reload para no martillear los servicios de IP.
  2. Bukkit.getIp() — la dirección de enlace del servidor, cuando no está vacía y no es 0.0.0.0. Normalmente una dirección de LAN.
  3. InetAddress.getLocalHost() — el mejor esfuerzo posible.
  4. localhost — respaldo de último recurso. Los clientes fuera de la máquina no alcanzarán esto.

Si la autodetección aterriza en una dirección no enrutable y preferSelfHost: true, la comprobación heurística de la Capa 1 falla y el plugin cambia al alojamiento remoto.

Para la configuración de autoalojamiento más fiable, establece selfHostExternalHost explícitamente a tu hostname público (p. ej. play.example.com). Esto omite por completo la detección de ipify/AWS y el sondeo se ejecuta contra el valor explícito.

Referencia de configuración

# 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

Qué imprime realmente la consola

RSPM imprime deliberadamente una línea sobre el alojamiento en un arranque normal — el resultado, no el trayecto:

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

o, cuando gana la ruta remota:

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

Esa línea se imprime una vez cada vez que se inicializa de cero una ruta de entrega, no en los reintentos de los jugadores ni en los ticks de keep-alive. Una recarga cuyo paquete no ha cambiado puede reutilizar el registro de alojamiento existente en lugar de imprimir un nuevo resultado.

Las comprobaciones de cordura fallidas no son advertencias. Un sondeo que falla es una condición de la que RSPM se recupera por sí mismo, así que se registra como detalle, no como fallo, y cada mensaje lo dice explícitamente (Self-host check: local pack link is not public. This is OK.). No lo verás salvo que lo pidas — una advertencia sobre algo que el plugin ya ha resuelto se lee como un fallo y hace que los operadores persigan un problema inexistente.

Para ver toda la cadena de decisión — qué comprobación falló, la URL del sondeo, el código de motivo, cada paquete preparado y cada clúster fusionado — ejecuta:

/rspm verbose on

Y luego /rspm reload. Este es el interruptor que hay que accionar antes de abrir un informe de error sobre el alojamiento. El comando escribe verboseLogging: true en config.yml y la opción persiste entre reinicios, así que ejecuta /rspm verbose off cuando termines; editar la clave de configuración a mano tiene exactamente el mismo efecto.

Ten en cuenta que verboseLogging cubre la preparación de paquetes y el alojamiento. El convertidor de Bedrock tiene su propio interruptor independiente, bedrockConverterDebug — consulta Conversión a Bedrock.

Rutas del servidor HTTP del backend

El servidor HTTP integrado siempre sirve el zip del paquete en:

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

En modo de red (RSPM está detrás de un proxy de Velocity / BungeeCord / Waterfall) se registran rutas adicionales para que el plugin del proxy las obtenga:

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)

Las rutas del paquete y de los artefactos de Bedrock están respaldadas por archivos: cada ruta lee su archivo de forma fresca en cada solicitud, de modo que una nueva mezcla que reescribe la misma ruta se recoge automáticamente sin reiniciar el servidor HTTP. Las rutas de Bedrock usan ETags fuertes y además soportan If-Modified-Since por compatibilidad, así que los sondeos del proxy sin cambios reciben 304 con aproximadamente cero ancho de banda. Esas rutas devuelven un 404 limpio cuando el archivo subyacente está ausente (p. ej. antes de que se complete la primera mezcla). La ruta de actualización está protegida aparte por un token bearer derivado de la clave de red compartida y solo está disponible cuando se puede ofrecer un jar de actualización válido.

Verificar que el autoalojamiento está activo

/rspm status muestra:

  • Active delivery: SELF-HOSTED — el autoalojamiento está en uso
  • Active delivery: REMOTE (magmaguy.com) — el auto-host remoto está en uso
  • URL: ... — la URL real que verán los clientes
  • Resolved external host — a qué se resolvió selfHostExternalHost
  • Public IP (auto-detected) — lo que informó ipify/AWS, si es que algo
  • selfHostPort — auto vs explícito, y el valor resuelto

Si esperabas autoalojamiento pero ves remoto, /rspm status es el sitio donde mirar — el log de arranque permanece callado sobre los fallos de sondeo autorresueltos por diseño. Ejecuta /rspm verbose on y /rspm reload para ver qué comprobación de cordura falló y por qué.

Errores comunes

  • Confiar en el sondeo de la Capa 3 con un router con hairpin roto — el sondeo se ejecuta desde el punto de observación de magmaguy.com, por lo que no puede detectar el caso en que los clientes externos funcionan pero la propia LAN del operador no devuelve el tráfico. Prueba desde un teléfono con datos móviles si no estás seguro.
  • Subir networkHttpOffset-v2 más allá del rango de puertos de tu proveedor de alojamiento — el síntoma es un CONNECT_FAILED silencioso para siempre del lado del proxy. Los backends anuncian su puerto enlazado real al proxy, pero el servidor HTTP aún tiene que enlazarse a un puerto accesible y el proxy aún tiene que poder alcanzarlo; si mcPort + offset aterriza fuera de la banda de puertos asignada de tu contenedor, el enlace/firewall falla independientemente del anuncio. Comprueba que el puerto esté en la banda asignada de tu contenedor antes de subir el desplazamiento.