O maior portal de MU Online do Brasil — desde 2003
Tutorial Avançado Infra

Como montar um script de deploy contínuo (CI/CD) para servidor de MU Online

Construa um pipeline de deploy contínuo para o seu servidor de MU Online, automatizando build do emulador, migração de banco, distribuição de arquivos de cliente e reinício seguro do GameServer/ConnectServer.

BR Bruno · Atualizado em 20 mar 2025 · ⏱ 16 min de leitura
Resposta rápida

Manter um servidor de MU Online privado atualizado manualmente — copiando DLLs, editando configs e reiniciando serviços na mão — funciona enquanto o projeto é pequeno, mas vira fonte de erro humano assim que a equipe cresce ou a frequência de updates aumenta. Um script de deploy contínuo (CI/CD) res

Manter um servidor de MU Online privado atualizado manualmente — copiando DLLs, editando configs e reiniciando serviços na mão — funciona enquanto o projeto é pequeno, mas vira fonte de erro humano assim que a equipe cresce ou a frequência de updates aumenta. Um script de deploy contínuo (CI/CD) resolve isso: cada alteração no código do emulador, nos arquivos de configuração ou no banco de dados passa por um pipeline repetível, testado e reversível. Este tutorial mostra como estruturar esse pipeline do zero, dos requisitos de infraestrutura ao script de rollback, cobrindo GameServer, ConnectServer, banco de dados e arquivos de configuração.

Por que automatizar o deploy de um servidor de MU

Um servidor de MU típico tem múltiplos componentes que precisam ser atualizados em conjunto: o binário do GameServer (compilado a partir do código do emulador, ex. IGCN/MuEMU/OpenMU), o ConnectServer, os arquivos .txt/.xml de configuração de itens e monstros, e o schema do banco (MSSQL ou MySQL, dependendo do emulador). Atualizar esses componentes fora de ordem — por exemplo, subir um ItemList.txt novo sem a stored procedure correspondente — é a causa mais comum de crash pós-update. Um pipeline de deploy contínuo garante que tudo suba na ordem certa, com validação em cada etapa.

Pré-requisitos de infraestrutura

  • Repositório de código versionado (Git) com o código-fonte do emulador e os arquivos de configuração.
  • Um ambiente de staging — réplica do servidor de produção, mesmo que menor, para validar builds antes de liberar.
  • Acesso via SSH/WinRM ao(s) servidor(es) de produção, com uma conta de serviço dedicada (não a conta pessoal do administrador).
  • Um runner de CI (GitHub Actions, GitLab CI, Jenkins ou até um script agendado via Task Scheduler/cron) que execute o pipeline.
  • Backup automatizado do banco de dados e dos arquivos de configuração antes de qualquer deploy.

Estrutura do repositório

Organize o repositório separando claramente o que é código-fonte compilável do que é configuração de dados de jogo:

mu-server/
├── src/               # código-fonte do emulador (GameServer, ConnectServer)
├── config/            # arquivos .ini/.txt de configuração de ambiente
├── db/
│   ├── migrations/    # scripts .sql numerados sequencialmente
│   └── seed/          # dados iniciais (itens, monstros, mapas)
├── deploy/
│   ├── deploy.sh       # script principal de deploy
│   ├── rollback.sh     # script de rollback
│   └── healthcheck.sh  # validação pós-deploy
└── .github/workflows/deploy.yml

Essa separação permite versionar mudanças de gameplay (um evento novo, um item novo) independentemente de mudanças de infraestrutura (uma correção de bug no core do emulador).

Etapa 1 — Build do emulador

O pipeline começa compilando o código-fonte do GameServer/ConnectServer. Um exemplo de etapa de build em bash, assumindo um projeto C++ com CMake:

#!/bin/bash
set -euo pipefail

echo "[deploy] Compilando GameServer..."
cd src/GameServer
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release -j"$(nproc)"

if [ ! -f build/GameServer.exe ]; then
  echo "[deploy] ERRO: build falhou, binário não gerado."
  exit 1
fi
echo "[deploy] Build concluída com sucesso."

Se o seu emulador é distribuído como binário fechado (sem recompilação), essa etapa vira apenas a validação de integridade do pacote baixado (checksum) antes de seguir.

Etapa 2 — Migração de banco de dados

Toda alteração de schema deve viver em um arquivo de migração numerado e versionado, nunca aplicada manualmente via SSMS/HeidiSQL direto em produção. Um exemplo de script de aplicação de migrações incrementais:

#!/bin/bash
set -euo pipefail
DB_HOST="$1"
LAST_APPLIED=$(sqlcmd -S "$DB_HOST" -Q "SELECT MAX(version) FROM SchemaMigrations" -h -1)

for file in db/migrations/*.sql; do
  version=$(basename "$file" | cut -d'_' -f1)
  if [ "$version" -gt "$LAST_APPLIED" ]; then
    echo "[deploy] Aplicando migração $file"
    sqlcmd -S "$DB_HOST" -i "$file"
    sqlcmd -S "$DB_HOST" -Q "INSERT INTO SchemaMigrations (version, applied_at) VALUES ($version, GETDATE())"
  fi
done

Nunca use DROP TABLE ou ALTER COLUMN destrutivo em uma migração sem antes confirmar que o backup pré-deploy foi concluído com sucesso.

Etapa 3 — Backup automático antes do deploy

O passo de backup deve ser bloqueante: se ele falhar, o pipeline inteiro para e nada é implantado. Um exemplo mínimo:

#!/bin/bash
set -euo pipefail
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backups/mu/$TIMESTAMP"
mkdir -p "$BACKUP_DIR"

sqlcmd -S "$DB_HOST" -Q "BACKUP DATABASE MuOnline TO DISK='$BACKUP_DIR/MuOnline.bak'"
cp -r /opt/mu-server/config "$BACKUP_DIR/config"
tar -czf "$BACKUP_DIR/binaries.tar.gz" /opt/mu-server/bin

echo "[deploy] Backup salvo em $BACKUP_DIR"

Mantenha ao menos os últimos 7 backups diários e 4 semanais, com rotação automática para não estourar o disco.

Etapa 4 — Distribuição dos arquivos ao servidor

Com a build validada e o backup concluído, o pipeline copia os artefatos para o(s) servidor(es) de produção. Usando rsync sobre SSH:

rsync -avz --delete \
  --exclude 'config/local.ini' \
  build/GameServer.exe deploy/ \
  usuario@mu-prod:/opt/mu-server/bin/

O --exclude é importante: arquivos de configuração específicos do ambiente (senhas de banco, chaves de licença) não devem ser sobrescritos pelo pipeline — eles vivem fora do controle de versão, geridos por variáveis de ambiente ou um cofre de segredos (Vault, AWS Secrets Manager).

Etapa 5 — Reinício seguro dos serviços

Reiniciar o GameServer derruba todos os jogadores conectados, então essa etapa deve ser cronometrada e comunicada. Um script de restart controlado:

#!/bin/bash
set -euo pipefail
echo "[deploy] Avisando jogadores sobre reinício em 5 minutos..."
echo "notice Servidor reiniciará em 5 minutos para manutenção" > /opt/mu-server/gs_console_pipe

sleep 300

systemctl stop mu-gameserver
systemctl stop mu-connectserver
cp /tmp/new_build/GameServer.exe /opt/mu-server/bin/
systemctl start mu-connectserver
systemctl start mu-gameserver

Prefira sempre reiniciar o ConnectServer por último a subir, para que ele só aceite novas conexões quando o GameServer já estiver de pé.

Etapa 6 — Healthcheck pós-deploy

Depois do restart, valide automaticamente que os serviços subiram corretamente antes de declarar o deploy como concluído:

#!/bin/bash
RETRIES=10
for i in $(seq 1 $RETRIES); do
  if nc -z localhost 44405; then
    echo "[deploy] ConnectServer respondendo na porta 44405."
    exit 0
  fi
  echo "[deploy] Aguardando ConnectServer subir... ($i/$RETRIES)"
  sleep 10
done
echo "[deploy] ERRO: ConnectServer não respondeu. Iniciando rollback."
exit 1

Se o healthcheck falhar, o pipeline deve acionar automaticamente o script de rollback, sem esperar intervenção manual.

Etapa 7 — Script de rollback

O rollback restaura o backup gerado na Etapa 3 e reverte os binários:

#!/bin/bash
set -euo pipefail
BACKUP_DIR="$1"

systemctl stop mu-gameserver mu-connectserver
sqlcmd -S "$DB_HOST" -Q "RESTORE DATABASE MuOnline FROM DISK='$BACKUP_DIR/MuOnline.bak' WITH REPLACE"
tar -xzf "$BACKUP_DIR/binaries.tar.gz" -C /
systemctl start mu-connectserver mu-gameserver

echo "[deploy] Rollback concluído a partir de $BACKUP_DIR"

Teste esse script periodicamente em staging — um rollback nunca testado tem grande chance de falhar exatamente no momento em que você mais precisa dele.

Integrando com GitHub Actions

Um exemplo de workflow que orquestra as etapas acima, disparado em push na branch main após aprovação de pull request:

name: Deploy MU Server
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build
        run: ./deploy/build.sh
      - name: Backup produção
        run: ./deploy/backup.sh
      - name: Migrar banco
        run: ./deploy/migrate.sh ${{ secrets.DB_HOST }}
      - name: Distribuir arquivos
        run: ./deploy/rsync-deploy.sh
      - name: Reiniciar serviços
        run: ssh deploy@mu-prod './deploy/restart.sh'
      - name: Healthcheck
        run: ./deploy/healthcheck.sh || ./deploy/rollback.sh

Mantenha os segredos (host do banco, chaves SSH) em Secrets do repositório, nunca hardcoded no YAML.

Ambiente de staging como gate obrigatório

Nenhuma build deve ir direto para produção. Configure o pipeline para primeiro implantar em staging, rodar um smoke test automatizado (login, criação de personagem, teleporte, drop de item) e só então liberar o deploy de produção — manual ou automaticamente, dependendo da maturidade da equipe. Esse gate é o que separa deploy contínuo de "deploy no escuro".

Erros comuns e soluções

SintomaCausa provávelSolução
GameServer não sobe após deployDLL/binário incompatível com schema de banco atualRode as migrações antes de trocar o binário, nunca depois
Rollback falhaScript de rollback nunca testado em stagingTeste o rollback a cada release maior, não só documente
Jogadores caem sem avisoRestart não avisado com antecedênciaAdicione mensagem in-game/Discord automatizada antes do restart
Pipeline trava no backupDisco cheio no servidor de bancoConfigure rotação de backups antigos e monitore espaço livre
Configuração local sobrescritarsync sem exclude de arquivos de ambienteListe explicitamente os arquivos de config que não vêm do repositório

Checklist de implementação do pipeline

  • Repositório versionado com separação entre código, config e migrações de banco.
  • Ambiente de staging funcional para validar builds antes de produção.
  • Script de backup automático bloqueante antes de cada deploy.
  • Migrações de banco numeradas e aplicadas em ordem.
  • Script de restart com aviso prévio aos jogadores.
  • Healthcheck automatizado pós-deploy.
  • Script de rollback testado periodicamente em staging.
  • Segredos (senhas, chaves) fora do controle de versão.

Com o pipeline de deploy contínuo no ar, o próximo passo é aplicar essa mesma disciplina de automação à configuração inicial do ambiente — veja o tutorial de criação de servidor de MU Online para entender a base sobre a qual esse pipeline foi construído.

Perguntas frequentes

Preciso de um servidor de CI dedicado (Jenkins/GitLab) para isso?

Não é obrigatório. Você pode começar com um script bash/PowerShell disparado manualmente ou por uma task agendada, e evoluir para GitHub Actions/GitLab CI/Jenkins conforme a equipe crescer. O importante é que o processo seja repetível e versionado, não a ferramenta em si.

É seguro automatizar o deploy em um servidor de MU em produção?

Sim, desde que o pipeline inclua backup automático antes de cada deploy, um ambiente de staging para validar a build e um passo de rollback testado. Deploy manual tende a ser mais arriscado que um pipeline bem desenhado, porque depende de memória humana.

Como lidar com o cliente do jogo no deploy contínuo?

O cliente (arquivos que o jogador baixa) normalmente tem um pipeline separado do servidor, publicando pacotes de atualização via launcher. O deploy do servidor deve verificar compatibilidade de versão de protocolo antes de liberar a atualização do cliente.

O que fazer se o deploy quebrar o GameServer em produção?

O pipeline deve ter um passo de rollback automático: restaurar o binário/DLL anterior e o dump de banco do backup pré-deploy, então reiniciar os serviços. Esse rollback precisa ser testado periodicamente, não só escrito e esquecido.

Dá para fazer deploy sem derrubar os jogadores online?

Parcialmente. Trocar DLLs do GameServer normalmente exige reinício do processo, então o ideal é agendar deploys em janelas de baixo tráfego e avisar a comunidade com antecedência. Para o ConnectServer e serviços web, é possível fazer deploy com zero downtime usando um balanceador simples.

BR
Editor de eventos, mapas e itens

Bruno é especialista em eventos, mapas, bosses e economia de itens do MU Online. Documenta cada detalhe com base em jogo real.

Continue lendo

Artigos relacionados