<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Cómo montar un servidor dedicado de Windrose en Linux (Bazzite + Podman)]]></title><description><![CDATA[<h1>Cómo montar un servidor dedicado de Windrose en Linux (Bazzite + Podman)</h1>
<p dir="auto">Guía paso a paso para levantar un servidor privado de <strong>Windrose</strong> usando la imagen Docker oficial (<code>windroseserver/windroseserver</code>) en un sistema Linux tipo Bazzite/Fedora Atomic con <strong>Podman rootless</strong>. Documentado a partir de una instalación real, incluyendo los errores que salieron y cómo se resolvieron.</p>
<hr />
<h2>0. Requisitos previos</h2>
<ul>
<li>Linux con Podman (o Docker) instalado.</li>
<li>Al menos ~6 GB libres (la imagen pesa varios GB por el payload del juego).</li>
<li>Puerto <code>7777</code> TCP/UDP disponible.</li>
<li>Acceso al router (para exponer el servidor a internet, opcional).</li>
</ul>
<p dir="auto">Verifica qué tienes disponible:</p>
<pre><code class="language-bash">which podman docker
</code></pre>
<p dir="auto">En Bazzite, Podman viene de fábrica con un alias <code>docker='podman'</code>, así que ambos comandos funcionan igual.</p>
<hr />
<h2>1. Preparar la carpeta del servidor</h2>
<pre><code class="language-bash">mkdir -p ~/Windrose-Server/Saved
cd ~/Windrose-Server
</code></pre>
<hr />
<h2>2. Primer arranque SIN configuración propia (para generar IDs válidos)</h2>
<p dir="auto"><strong>Importante:</strong> no crear el <code>ServerDescription.json</code> a mano desde cero con campos vacíos (<code>PersistentServerId</code>, <code>WorldIslandId</code>, etc. en <code>""</code>). Eso provoca un crash tipo:</p>
<pre><code>Fatal error: [R5DataKeeperForServerCoop.cpp:154] InitializeBLServer - Cannot init Coop NetServer
Condition: 'ServerDescription.WorldIslandId.IsValid()'
</code></pre>
<p dir="auto">En su lugar, deja que el propio servidor genere el archivo la primera vez:</p>
<pre><code class="language-bash">podman run --user ue_user --name WindroseServer \
  -p 7777:7777/tcp -p 7777:7777/udp \
  -d \
  -v ~/Windrose-Server/Saved:/home/ue_user/app/R5/Saved:Z \
  docker.io/windroseserver/windroseserver:latest

sleep 20
podman stop WindroseServer
</code></pre>
<p dir="auto">Copia el archivo generado a tu carpeta local:</p>
<pre><code class="language-bash">podman cp WindroseServer:/home/ue_user/app/R5/ServerDescription.json ~/Windrose-Server/ServerDescription.json
</code></pre>
<p dir="auto">Este archivo ya trae <code>PersistentServerId</code> real y otros valores válidos generados por el motor — no los toques.</p>
<hr />
<h2>3. Editar solo los campos que quieres personalizar</h2>
<pre><code class="language-bash"># Nombre del servidor
sed -i 's/"ServerName": *"[^"]*"/"ServerName": "TU_NOMBRE_AQUI"/' ServerDescription.json

# Habilitar conexión directa por IP (necesario para Docker/Podman)
sed -i 's/"UseDirectConnection": false/"UseDirectConnection": true/' ServerDescription.json
sed -i 's/"DirectConnectionServerPort": -1/"DirectConnectionServerPort": 7777/' ServerDescription.json
</code></pre>
<p dir="auto">Campos relevantes en <code>ServerDescription_Persistent</code>:</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Campo</th>
<th>Qué hace</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>ServerName</code></td>
<td>Nombre visible del servidor</td>
</tr>
<tr>
<td><code>MaxPlayerCount</code></td>
<td>Jugadores máximos</td>
</tr>
<tr>
<td><code>IsPasswordProtected</code> / <code>Password</code></td>
<td>Contraseña de acceso</td>
</tr>
<tr>
<td><code>UseDirectConnection</code></td>
<td><code>true</code> = conexión por IP directa. <code>false</code> = conexión por código de invitación (relay P2P vía Epic Online Services)</td>
</tr>
<tr>
<td><code>DirectConnectionServerPort</code></td>
<td>Puerto a usar (7777 por defecto)</td>
</tr>
<tr>
<td><code>InviteCode</code></td>
<td>Código de invitación — <strong>solo funciona si <code>UseDirectConnection</code> está en <code>false</code></strong></td>
</tr>
</tbody>
</table>
<p dir="auto"><img src="https://forum.losdelring.net/assets/plugins/nodebb-plugin-emoji/emoji/android/26a0.png?v=8ced9ab119d" class="not-responsive emoji emoji-android emoji--warning" style="height:23px;width:auto;vertical-align:middle" title="⚠" alt="⚠" />️ <strong><code>UseDirectConnection</code> y el código de invitación son mutuamente excluyentes.</strong> No puedes usar ambos al mismo tiempo. Con <code>true</code>, el invite code queda inútil aunque tenga un valor válido. Para hosting dedicado con IP fija, <code>true</code> (Direct IP) es lo recomendado: menos latencia, no depende del relay de Epic/AWS.</p>
<hr />
<h2>4. Borrar el contenedor de prueba y lanzar el definitivo</h2>
<p dir="auto"><strong>Clave: usar <code>--userns=keep-id</code> en Podman rootless.</strong> Sin esto, el UID <code>ue_user</code> (1000) dentro del contenedor no mapea al UID real del host, y el servidor no puede reescribir <code>ServerDescription.json</code> cuando genera el mundo — causa el mismo crash del paso 2 pero después de crear el mundo:</p>
<pre><code>open('.../ServerDescription.json', ...) failed: errno=13 (Permission denied)
Cannot save ServerDescription file.
</code></pre>
<p dir="auto">Comando final:</p>
<pre><code class="language-bash">podman rm -f WindroseServer

podman run --user ue_user --userns=keep-id --name WindroseServer \
  -p 7777:7777/tcp -p 7777:7777/udp \
  -d \
  -v ~/Windrose-Server/Saved:/home/ue_user/app/R5/Saved:Z \
  -v ~/Windrose-Server/ServerDescription.json:/home/ue_user/app/R5/ServerDescription.json:Z \
  docker.io/windroseserver/windroseserver:latest
</code></pre>
<p dir="auto">El flag <code>:Z</code> en los volúmenes es necesario en sistemas con SELinux (Fedora/Bazzite) para evitar errores de permisos.</p>
<hr />
<h2>5. Verificar que está corriendo bien</h2>
<pre><code class="language-bash">podman logs -f WindroseServer
</code></pre>
<p dir="auto">Busca estas líneas como señal de éxito:</p>
<pre><code>IpNetDriver listening on port 7777
Bringing World .../GenlandiaMulty up for play
Server. Change state LoadedIslandData =&gt; WaitingForFirstAccount
</code></pre>
<p dir="auto">Para ver logs sin quedarte pegado en tiempo real:</p>
<pre><code class="language-bash">podman logs --tail 100 WindroseServer
</code></pre>
<p dir="auto">Guardar log completo a archivo:</p>
<pre><code class="language-bash">podman logs WindroseServer &gt; ~/Windrose-Server/server.log
</code></pre>
<hr />
<h2>6. Ver nombre, contraseña e invite code guardados</h2>
<pre><code class="language-bash">grep -E '"ServerName"|"Password"|"IsPasswordProtected"|"InviteCode"' ~/Windrose-Server/ServerDescription.json
</code></pre>
<hr />
<h2>7. Cómo conectan tus amigos</h2>
<p dir="auto"><strong>En la misma red local:</strong></p>
<pre><code>IP_LOCAL_DEL_HOST:7777
</code></pre>
<p dir="auto">(consíguela con <code>ip addr show | grep 'inet ' | grep -v 127.0.0.1</code>)</p>
<p dir="auto"><strong>Remotos (por internet):</strong> necesitan la IP pública del host, más el port forwarding hecho en el router (ver sección 8).</p>
<pre><code class="language-bash">curl ifconfig.me
</code></pre>
<p dir="auto">En el juego: <strong>Play → Connect to Server → Direct IP tab</strong> → pegan <code>IP:7777</code>.</p>
<hr />
<h2>8. Port forwarding en router MikroTik (RouterOS)</h2>
<p dir="auto">Reemplaza <code>ether1</code> por tu interfaz WAN y <code>192.168.88.254</code> por la IP local del host (idealmente fijada por DHCP lease estático).</p>
<p dir="auto"><strong>Fijar la IP del host (opcional pero recomendado):</strong></p>
<pre><code>/ip dhcp-server lease print
/ip dhcp-server lease make-static &lt;número_de_la_entrada&gt;
</code></pre>
<p dir="auto"><strong>Reglas NAT (port forward), TCP y UDP:</strong></p>
<pre><code>/ip firewall nat add chain=dstnat protocol=tcp dst-port=7777 in-interface=ether1 action=dst-nat to-addresses=192.168.88.254 to-ports=7777 comment="Windrose TCP"

/ip firewall nat add chain=dstnat protocol=udp dst-port=7777 in-interface=ether1 action=dst-nat to-addresses=192.168.88.254 to-ports=7777 comment="Windrose UDP"
</code></pre>
<p dir="auto"><strong>Reglas de firewall filter (deben quedar antes de cualquier drop general en la cadena forward):</strong></p>
<pre><code>/ip firewall filter add chain=forward protocol=tcp dst-port=7777 dst-address=192.168.88.254 action=accept place-before=0 comment="Allow Windrose TCP"

/ip firewall filter add chain=forward protocol=udp dst-port=7777 dst-address=192.168.88.254 action=accept place-before=0 comment="Allow Windrose UDP"
</code></pre>
<p dir="auto"><strong>Verificar:</strong></p>
<pre><code>/ip firewall nat print
/ip firewall filter print
</code></pre>
<p dir="auto"><strong>Revisar CGNAT (paso crítico):</strong> compara la IP de tu interfaz WAN...</p>
<pre><code>/ip address print
</code></pre>
<p dir="auto">...contra la que te da <code>curl ifconfig.me</code> desde el host, o <a href="https://www.whatismyip.com" rel="nofollow ugc">whatismyip.com</a>. Si son diferentes, hay CGNAT/doble NAT de por medio y el forwarding no funcionará desde afuera sin pasos extra (pedir IP pública al ISP, o usar una alternativa tipo VPN/túnel).</p>
<hr />
<h2>Resumen de comandos útiles</h2>
<pre><code class="language-bash"># Ver contenedores corriendo
podman ps

# Ver logs en vivo
podman logs -f WindroseServer

# Reiniciar el servidor (tras editar ServerDescription.json)
podman rm -f WindroseServer
podman run --user ue_user --userns=keep-id --name WindroseServer \
  -p 7777:7777/tcp -p 7777:7777/udp -d \
  -v ~/Windrose-Server/Saved:/home/ue_user/app/R5/Saved:Z \
  -v ~/Windrose-Server/ServerDescription.json:/home/ue_user/app/R5/ServerDescription.json:Z \
  docker.io/windroseserver/windroseserver:latest

# Parar / iniciar sin borrar
podman stop WindroseServer
podman start WindroseServer
</code></pre>
<hr />
<h2>Notas finales</h2>
<ul>
<li>La imagen oficial (<code>windroseserver/windroseserver</code>) corre el binario <strong>nativo Linux</strong> del motor (no requiere Wine).</li>
<li>Actualizar el servidor: <code>podman pull docker.io/windroseserver/windroseserver:latest</code> y volver a lanzar el contenedor (los datos del mundo persisten en <code>Saved/</code> porque está montado como volumen).</li>
<li>Pendiente para el futuro: configurar arranque automático con <strong>Quadlet</strong> (systemd nativo de Fedora Atomic/Bazzite) para que el servidor levante solo al encender la máquina.</li>
</ul>
]]></description><link>https://forum.losdelring.net/topic/15/cómo-montar-un-servidor-dedicado-de-windrose-en-linux-bazzite-podman</link><generator>RSS for Node</generator><lastBuildDate>Thu, 20 Aug 2026 01:01:32 GMT</lastBuildDate><atom:link href="https://forum.losdelring.net/topic/15.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 05 Aug 2026 13:51:07 GMT</pubDate><ttl>60</ttl></channel></rss>