DEV Community

Cover image for Como eu criei um servidor de PalWorld na AWS com start por bot no Discord — Parte 2
Magno Gouveia
Magno Gouveia

Posted on

Como eu criei um servidor de PalWorld na AWS com start por bot no Discord — Parte 2

Na primeira parte, ensinei como criar uma máquina virtual na AWS e instalar um servidor de Palworld. Porém, ainda precisamos resolver a questão da máquina ficar ligada o tempo todo, uma forma de permitir que qualquer pessoa inicie o servidor a partir do Discord e também ter acesso ao IP do server.

Desligando a máquina automaticamente:

Para automatizar a desativação do servidor, decidi criar um script que:

  1. Verifica se o servidor está iniciado.

  2. Verifica se há jogadores

  3. Desliga a máquina caso não haja mais jogadores.

Para isso, vamos criar um script chamado: shutdownServer.sh com o conteúdo abaixo:

#!/bin/bash

cd /home/ubuntu/palworld

# Execute o comando para obter a lista de jogadores e capturar possíveis erros
OUTPUT=$(docker-compose run --rm rcon ShowPlayers 2>&1)

# Filtra linhas indesejadas
CLEANED_OUTPUT=$(echo "$OUTPUT" | grep -v "Creating palworld_rcon_run")

# Verifica se ocorreu um erro na execução do comando
if echo "$CLEANED_OUTPUT" | grep -q "ERROR"; then
    echo "Erro ao executar o comando. Possivelmente, máquina está ligando."
    STOP_INSTANCE=false
else
    # Conta o número de jogadores
    NUM_PLAYERS=$(echo "$CLEANED_OUTPUT" | wc -l)
    NUM_PLAYERS=$((NUM_PLAYERS-1)) # Ajusta para subtrair o cabeçalho, se houver

    if [ "$NUM_PLAYERS" -le 0 ]; then
        echo "Nenhum jogador online."
        STOP_INSTANCE=true
    else
        echo "Há $NUM_PLAYERS jogadores online."
        echo "Lista de Jogadores:"
        echo "$CLEANED_OUTPUT" | cut -d ',' -f 1
        STOP_INSTANCE=false
    fi
fi

# Se não houver jogadores online ou ocorreu um erro, parar o container do Docker e desligar a máquina
if [ "$STOP_INSTANCE" = true ]; then
    # Encontra o ID do container que está executando a imagem especificada
    CONTAINER_ID=$(docker ps -q --filter ancestor=jammsen/palworld-dedicated-server:latest)

    # Verifica se um container foi encontrado
    if [ -n "$CONTAINER_ID" ]; then
        echo "Parando o container do Docker: $CONTAINER_ID"
        docker stop $CONTAINER_ID
    else
        echo "Nenhum container encontrado para a imagem especificada."
    fi

    echo "Desligando a máquina..."
    sudo shutdown -h now
fi
Enter fullscreen mode Exit fullscreen mode

Aqui estamos usando o programa rcon para obter uma lista de jogadores online e armazenando em OUTPUT.

Quando a máquina está iniciando, geralmente esse comando retorna um ERROR; neste caso, não vamos desligar a máquina.

Após isso, se houverem jogadores online, nós exibimos uma lista com os nomes, e caso não haja ninguém, o servidor irá desligar o Docker e após isso, desligar a própria máquina.

  • Depois de criar o script, dê permissões de execução com o comando:
$ chmod +x shutdownServer.sh
Enter fullscreen mode Exit fullscreen mode

Agora vamos criar um repetidor, para executar o script de 30 em 30 minutos:

  • Execute o seguinte comando como sudo:
$ sudo crontab -e
Enter fullscreen mode Exit fullscreen mode

Vá até o final do arquivo e adicione a linha:

*/30 * * * * /home/ubuntu/palworld/shutdownServer.sh >> /home/ubuntu/logs/log_$(date +\%Y_\%m_\%d_\%H_\%M).log 2>&1
Enter fullscreen mode Exit fullscreen mode

Com isso, o servidor irá executar o script de 30 em 30 minutos e guardar os logs na pasta “logs” na home. O script precisa ser executado como sudo para ter acesso a parar o container do Docker e também desligar a máquina.

Crie a pasta para guardar os logs:

$ mkdir /home/ubuntu/logs
Enter fullscreen mode Exit fullscreen mode

Criando sua função lambda

Antes de criar o bot propriamente dito, precisamos criar as funções que serão executadas por ele.

  • No seu console da AWS, procure pelo serviço “Lambda”

  • Crie uma nova função no botão superior direito

  • Dê um nome como “discord-lambda”

  • Escolha a linguagem “Node.js 20.x”

  • Clique em “Criar Função” no canto inferior direito.

Precisamos chamar um “gatilho” que irá executar essa Lambda quando um endereço for chamado, para isso:

  • Na “Visão geral da função”

  • Clique em “+ Adicionar gatilho”

  • Selecione API Gateway

  • Selecione “Create a new API”

  • Em “API type” Selecione “HTTP API”

  • Em Security Selecione “Open”

  • Abra a aba “Additional Settings”

  • Selecione a opção “Cross-origin resource sharing (CORS)”

(isso irá permitir o discord chamar sua função mesmo de outro domínio.)

  • Clique em “Adicionar”

  • Na aba “Configuração>Gatilhos” acesse o endereço “API endpoint”

  • Se abrir uma nova aba com o texto: “Hello from Lambda!”, tudo deu certo até então.

  • Copie esse endereço, vamos utilizá-lo mais tarde na criação do bot.

  • Com sua função criada, vamos baixar o código desse repositório: https://github.com/andarilhoz/discord-lambda

  • Dentro dele, acesse a pasta “aws” e execute o comando npm install para instalar a dependência tweetnacl que irá ler o request do discord.

  • Adicione todo conteúdo de dentro da pasta “aws” (incluindo o node_modules) para um arquivo .zip

  • No seu navegador, na lambda recém criada dentro da aba “Código” clique em “Fazer upload de” e escolha “Arquivo .zip”

  • Faça o upload do zip criado anteriormente

  • Na aba “Configuração” selecione “Variáveis de ambiente” e preencha as seguintes variáveis:

AWS_ECS_REGION -> a região da sua ecs, se você criou em São Paulo, será: "sa-east-1" (https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RegionsAndAvailabilityZones.html)
INSTANCE_ID -> O id da sua instancia EC2 criada no artigo passado
CHANNEL_ID -> O id do canal do seu servidor do discord onde o bot irá funcionar
ROLE_ID -> O id do cargo que terá permissão para executar os comandos
PUBLIC_KEY -> Será gerado mais a frente quando criarmos o bot no discord
Enter fullscreen mode Exit fullscreen mode

Essa lambda também requer permissão para executar scripts do EC2 **e **AWS Cost Explorer Service

  • No menu Configuração, selecione o sub-menu “Permissões”

  • Embaixo da label “Nome da função” clique no link com o nome [sua-lambda]-role-[id], isso abrirá o gerenciador de permissões da AWS

  • Selecione a Politica de Permissões criada automaticamente (terá um suffixo: AWSLambdaBasicExecutionRole)

  • Clique em “Editar”

Adicione a seguinte permissão no json, dentro da propriedade “Statement”:

    {
      "Sid": "AccessCostExplorer",
      "Effect": "Allow",
      "Action": [
        "ce:GetCostAndUsage",
        "ec2:DescribeInstances",
        "ec2:StartInstances",
        "ec2:StopInstances"
      ],
      "Resource": "*"
    }
Enter fullscreen mode Exit fullscreen mode

Isso dará a lambda permissões para:

  • Ver o custo e uso de seus serviços na AWS

  • Descrever uma instancia EC2

  • Iniciar uma instancia EC2

  • Pausar uma instancia EC2

Clique em “Próximo” e depois em “Salvar Alterações”.

Após salvar as permissões, só falta adicionarmos o PUBLIC_KEY que iremos gerar agora no Discord para finalizar a lambda.

Criando um bot no Discord

Abra o Developer Portal do discord,

  • Crie uma nova aplicação, e dê um nome.

  • Na aba “General Information” copie o “PUBLIC KEY” e adicione esse valor na variável da lambda criada no passo anterior.

  • Ainda em “General Information” preencha o campo “INTERACTIONS ENDPOINT URL” com a url da sua lambda criada no passo anterior.

  • Clique em “Save Changes”

  • Você deverá ver a mensagem: “All your edits have been carefully recorded.”

  • Vá na aba “OAuth2 > URL Generator”

  • Em “SCOPES” selecione “bot”

  • Em “BOT PERMISSIONS” selecione “Use Slash Commands”

  • Copie a URL gerada na parte de baixo, e use-a para adicionar o seu novo bot no servidor desejado.

  • Na aba “Bot” clique no botão “Reset Token”

  • Copie o código gerado que iremos utilizar no próximo passo.

  • Na aba “General Information” copie o código “APPLICATION ID” que também será necessário.

Adicionando comandos do bot:

BOT_TOKEN=ODUwMTk2NDDyMDc2MjgyOTAw.GpYcOB.q2XSa_IUw5A3sHId67s6kQzSoiZP_zfZFCyDvE //O Token Gerado anteriormente na aba "Bot" do discord
APP_ID=850196442076282900 //O App Id gerado anteriormente na aba "General Information"
GUILD_ID=337788789500449762 //O ID do seu servidor do discord.

Enter fullscreen mode Exit fullscreen mode
  • Execute o comando npm install na pasta “discord”

  • Execute o comando node addcommand.js

Se tudo ocorreu bem, você verá essas mensagens:

success
200
success
200
success
200
success
200
All commands sent
Enter fullscreen mode Exit fullscreen mode

Pronto! agora você pode executar os comandos do seu bot no seu servidor para iniciar o EC2, pausar, ver o status (e IP) e também ver o custo total de EC2 da sua aplicação.

Adicionando um IP Elástico

Um dos problemas de se ligar e desligar um servidor EC2 é que seu ip acaba mudando constantemente, vamos adicionar um IP Elástico que não irá mudar.

  • No seu console da AWS, busque por EC2

  • No menu esquerdo selecione “IPs elásticos”

  • Clique em “Alocar endereço de IP elástico”

  • Clique em **“Alocar” **no canto inferior direito

  • Agora selecione o IP na lista de endereços

  • Clique em “Ações” no botão direito superior

  • Clique em “Associar endereço IP elástico”

  • Abaixo da label “Instância” selecione seu servidor EC2

  • Clique em “Associar” no canto direito inferior.

Pronto, esse IP será fixo e será o ip permanente da sua máquina, e não mudara mesmo após desligá-la.

Conclusão

Como dito anteriormente, a máquina t3a.xlarge custaria mensalmente $170 USD, com essa alteração, considerando que você e seus amigos joguem cerca de 4 horas por dia, todos os dias, esse valor cai para: $29 USD. Existem outras maneiras de baratear esse custo, já que é uma máquina que tem capacidade para 32 jogadores simultâneos. Você pode testar máquinas com uma memória menor para 4 jogadores por exemplo.

Dessa forma, com a máquina t3a.xlarge, economizamos em um mês $141 USD, quase $700 Reais!

Daqui pra frente:

Um dos problemas dessa configuração é o “cold start” da lambda AWS, você pode transformar a lambda em um servidor EC2 nano, que além de garantir o baixo custo, sempre estará disponível!

Top comments (0)