2hours.gg/

Servidores de jogos por hora. Pague só quando jogar.

Como rodar um game server só para Windows no Linux

Alguns jogos da Steam só trazem um servidor dedicado para Windows. Não há binário Linux no depot, então o conselho de sempre é "rode em uma máquina Windows." Você não precisa. Com o Wine, você pode rodar o servidor Windows em uma máquina Linux normal, e ele vai se conectar à Steam e aceitar jogadores reais. Esta é a receita exata que funcionou para nós, usando Alien Swarm: Reactive Drop (um jogo co-op Source gratuito) como exemplo. A mesma abordagem deve valer para outros servidores dedicados Source só para Windows.

Primeiro, confira se realmente não existe um servidor Linux

Não presuma. Pergunte direto à Steam antes de recorrer ao Wine. Aponte o steamcmd para o app e leia a lista de plataformas dele:

steamcmd +login anonymous +app_info_print <appid> +quit \
  | grep -iE "oslist|name"

Se o app do servidor dedicado for só "oslist windows", não há build Linux nativo para recorrer. Você também pode tentar forçar uma instalação Linux; quando realmente não há depot Linux, ela falha na hora:

steamcmd +@sSteamCmdForcePlatformType linux \
  +login anonymous +app_update <appid> validate +quit
# ERROR! Failed to install app '<appid>' (Missing configuration)

Esse erro, e nenhum arquivo ELF baixando, confirmam. Agora o Wine é o caminho. Instale o servidor E o app 1007 (os Steamworks Common Redistributables) na mesma pasta, com o tipo de plataforma windows. O app 1007 traz as DLLs da Steam de que o servidor precisa, e você vai ver por quê no Passo 2:

steamcmd +@sSteamCmdForcePlatformType windows +login anonymous \
  +force_install_dir /path/to/server \
  +app_update <appid> validate \
  +app_update 1007 validate \
  +quit

Por que a tentativa ingênua com Wine falha

Rodar o servidor direto do Wine bate em duas paredes seguidas:

  • Sem console: o servidor espera um terminal de verdade. Redirecionar de /dev/null dá CTextConsoleWin32::GetLine: !GetNumberOfConsoleInputEvents e ele nunca inicia.
  • Não foi possível carregar a biblioteca da Steam: mesmo depois de subir, ele imprime "Unable to load Steam support library" e nunca se registra na Steam, então ninguém consegue encontrá-lo nem entrar.

Ambas têm conserto. Aqui vai a receita completa.

Passo 1: dê a ele um terminal de verdade (PTY)

Uma máquina headless não tem terminal, e o servidor de console do Windows se recusa a rodar sem um. Envolva o lançamento em script, que aloca um pseudo-terminal, e use o Xvfb para um display falso:

Xvfb :99 -screen 0 1024x768x24 &
export DISPLAY=:99 WINEPREFIX=/wine
script -qfc "wine srcds_console.exe -console -condebug \
  -game <gamedir> +map <map> -port 27015" /tmp/server.log

Só isso já faz o servidor carregar um mapa e bindar sua porta de jogo. Mas ele ainda não consegue falar com a Steam.

Passo 2: duas DLLs da Steam, duas fontes diferentes

A engine Source precisa das DUAS, steamclient.dll e steam.dll, ao lado do exe do servidor, e aqui está a armadilha que nos custou uma rodada inteira a mais de depuração: elas vêm de lugares DIFERENTES, e o app 1007 só te dá UMA delas.

  • steamclient.dll: vem do app 1007 (Steamworks Common Redistributables), que você instalou no Passo 1. Canônica, com versão compatível, mantida pela Valve.
  • steam.dll: NÃO está no app 1007. Ela faz parte do CLIENTE Steam, e a única forma limpa de obtê-la é rodar o steamcmd.exe do Windows uma vez sob o Wine, que se autoatualiza e deposita steam.dll (mais steamclient.dll) na própria pasta.

Então dê bootstrap na steam.dll com steamcmd.exe sob o Wine, e depois copie as duas DLLs ao lado do exe do servidor:

# steam.dll: run Windows steamcmd once under Wine (needs Xvfb for a display)
cd "$WINEPREFIX/drive_c/steamcmd"
curl -fsSLO https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip
unzip -o steamcmd.zip
DISPLAY=:99 wine steamcmd.exe +quit    # lays down steam.dll + steamclient.dll

# place both next to the server exe
cd /path/to/server
cp "$WINEPREFIX/drive_c/steamcmd/steam.dll" .
[ -f steamclient.dll ] || cp "$WINEPREFIX/drive_c/steamcmd/steamclient.dll" .

Passo 3: por que steam.dll é a peça que importa

Esta é a parte que quase ninguém anota. O erro diz "Unable to load Steam support library," e a biblioteca de suporte a que ele se refere não é a steamclient.dll, é a steam.dll. A engine Source procura a steam.dll ao lado do próprio executável para dar bootstrap em toda a cadeia da Steam. Só com a steamclient.dll presente (que é tudo o que o app 1007 te dá) ainda falha; no momento em que a steam.dll fica ao lado do .exe, o log vira de falha para sucesso:

Connection to Steam servers successful.
VAC secure mode is activated.

O VAC não ativa a menos que o servidor seja um gameserver corretamente logado, então essa linha é sua prova de que ele se registrou. A maioria dos servidores Source loga de forma anônima aqui e não precisa de nenhum Game Server Login Token (GSLT). Só alguns jogos (como CS2) exigem um.

A armadilha: o A2S fica mudo mas o servidor está bem

Aqui vai o detalhe que nos custou mais tempo, e a razão pela qual quase desistimos. Sob o Wine o servidor NÃO responde ao A2S_INFO, a consulta UDP que as ferramentas usam para ler o nome, o mapa e a contagem de jogadores de um servidor. Consulte-o e cada porta dá timeout, até da mesma máquina. Se você usa o A2S como health check, o servidor parece completamente morto.

Ele não está morto. O A2S ficar mudo sob o Wine não impede jogadores reais de entrarem. O navegador de servidores dentro do jogo lista os servidores a partir da master list da Steam (para a qual o servidor envia por conta própria), e uma conexão direta usa o protocolo do jogo, não o A2S. Então o verdadeiro teste é um cliente conectando, não uma consulta respondendo. Quando finalmente tentamos, um jogador real conectou e jogou na primeira tentativa:

Client "player" connected (10.0.0.5:27005).
1/ 8 on map <mapname>

A lição prática: para um servidor hospedado com Wine, não faça health check com A2S. Cheque algo que de fato reflita se está vivo, como a linha "VAC secure mode is activated" no log, a linha da contagem de jogadores, ou uma simples verificação de que a porta UDP do jogo está bindada.

Isso funciona para todo jogo de Windows?

Seja honesto sobre o escopo. Provamos isso em um servidor de engine Source, e a mesma receita (PTY, um runtime construído pelo steamcmd, steam.dll ao lado do exe) deve funcionar para outros servidores dedicados Source só para Windows. Jogos em outras engines integram a Steam de forma diferente, então trate-os como experimentos separados. Duas coisas a esperar de qualquer jeito: os boots são mais lentos que no Linux nativo (Wine mais a etapa do steamcmd mais o login na Steam), e o comportamento de A2S mudo acima provavelmente vai valer para todos.

Ou pule tudo isso

Esse é o tipo de enrolação que come uma tarde inteira. Se você só quer o servidor, nós cuidamos da frota Linux e da encanação do Wine para você, por hora, com um IP público desde o primeiro minuto. Veja o que hospedamos na 2hours.gg.

Veja também

← Voltar para todos os guias