Nos últimos anos, tivemos um salto no processamento de linguagem natural (NLP). O surgimento da IA Generativa não apenas refinou tarefas antigas, mas abriu bastantes possibilidades em lidar com textos e dados não estruturados, melhorias em experiências de aplicações já existentes, classificações mais simples e demais tarefas. No entanto, para muitas organizações, trouxe um dilema crítico: como escalar o uso dessas tecnologias mantendo o controle absoluto sobre os dados?
Para setores que lidam com informações sensíveis ou que operam sob regulamentações rígidas de privacidade, submeter dados a LLMs públicos via APIs externas não é apenas um risco, mas muitas vezes uma impossibilidade jurídica. É aqui que a soberania de dados se torna o pilar central da estratégia de tecnologia. Rodar modelos abertos em uma infraestrutura nacional e controlada, como a Magalu Cloud, não é mais apenas uma alternativa de custo, é uma necessidade de segurança e conformidade.
Neste tutorial, vamos explorar como você pode unir o estado da arte dos modelos do Hugging Face com o vLLM, garantindo performance de nível de produção sem abrir mão da privacidade.
O que é vLLM?
O vLLM não é apenas uma biblioteca de inferência; é um sistema de gerenciamento de memória virtualizado para GPUs.
O problema central da inferência de LLMs não é computação (FLOPs), é I/O de memória. Engines tradicionais alocam VRAM contígua para o Key-Value (KV) Cache, resultando em fragmentação massiva (60-80% de desperdício) e impedindo o paralelismo.
O vLLM resolve isso com o PagedAttention: um algoritmo de atenção que permite armazenar o KV Cache em blocos de memória não contíguos. Isso desacopla a memória lógica (sequência de tokens) da memória física (VRAM), permitindo:
- Desperdício Zero: Quase nenhuma fragmentação de memória (<4%).
- Continuous Batching: A capacidade de injetar novas requisições na GPU token-a-token, sem esperar que o lote anterior termine.
- Copy-on-Write: Mecanismo eficiente para decodificação paralela (como em Beam Search), onde múltiplos "caminhos" compartilham a mesma memória física até divergirem.
Você pode conhecer mais sobre o vLLM neste blog post
Passo a passo para configuração do ambiente
Para este tutorial, provisionamos uma máquina virtual equipada com a GPU NVIDIA L40S. A escolha é estratégica pois a L40S é baseada na arquitetura Ada Lovelace, possui o Transformer Engine com suporte nativo a precisão FP8. Isso garante que o modelo Qwen3-30B-A3B-FP8 rode muito bem tirando proveito dos 18.176 núcleos CUDA e da alta disponibilidade de memória. Com 48GB de VRAM GDDR6 (ECC) e uma largura de banda de 864 GB/s, eliminamos gargalos de transferência, assegurando estabilidade e alta vazão durante a inferência.
Então dado o contexto vamos iniciar a mão na massa.
Criação da máquina
Etapas para criarmos a máquina
-
1 - Início e Seleção do Serviço
- No Console da Magalu Cloud, localize o card com o texto "Virtual Machine".
- Clique no botão azul "Criar instância".
-
2 - Configurações de região e sistema operacional
- Zona de Disponibilidade: Selecione a zona desejada (no meu caso, foi escolhida a
br-se1-amas escolha o que preferir). - Escolha de Imagem: Selecione a distribuição Ubuntu.
- Versão: No menu suspenso que aparece, escolha a versão Ubuntu 24.04 LTS.
- Zona de Disponibilidade: Selecione a zona desejada (no meu caso, foi escolhida a
-
3 - Hardware
- Habilitar GPU (muito importante): Marque a caixa de seleção "Habilitar GPU" para visualizar as instâncias de alta performance.
- Tipo de Instância:
- Role até a seção de GPUs (GPU NVIDIA L40S, indicada para IA generativa e LLMs).
- Selecione a configuração desejada. Neste caso escolha a instância L40S-1x-DP8-64-100 (que oferece 8 vCPUs, 64 GB de RAM e 100 GB de disco).
-
4 - Conectividade e Acesso
- Acesso Público: Mantenha marcada a opção "Atribuir IPv4 público para essa instância" (padrão).
- Chave SSH (muito importante para poder acessar sua máquina):
- Selecione a opção "Selecionar chave já utilizada anteriormente" caso tenha uma ou cadastre uma nova clicando em " Inserir uma chave própria nova".
- Caso esteja inserindo uma nova chave, consulte-a com o seguinte comando Linux/macos
cat ~/.ssh/id_ed25519.pub(o nome da sua chave deve ser diferente deid_ed25519.pub, mas ela deve finalizar com.pub), copie o valor que aparecer no seu terminal e cole no campo "Insira sua chave SSH" e depois dê um nome para essa chave ssh ser utilizada.
-
5 - Nomeando a máquina
- Nome da Instância: Defina um nome identificável para o servidor. No meu caso, usei o nome
llm_server-vllm. - Clique no botão "Criar instância" no canto inferior direito.
- Você será redirecionado para a lista de instâncias, onde poderá ver seu novo servidor com o status "Criando".
- Nome da Instância: Defina um nome identificável para o servidor. No meu caso, usei o nome
Acessando nossa máquina virtual para efetuarmos nossas configurações
Depois de criarmos nossa máquina virtual, agora precisaremos acessar ela para fazermos as instalações necessárias para rodarmos nossa LLM em produção com proxy reverso e SSL.
Requisito obrigatório:
Para nosso proxy reverso funcionar corretamente, será preciso configurar seu domínio apontando o IP da sua máquina que poderá pegar essa informação acessando a página de detalhes da nossa VM.
No meu caso utilizo a Cloudflare para gerir meu DNS, e você pode seguir a documentação deles para configurar seu DNS, mas caso use outro local para gerenciar seu DNS busque e faça a configuração, para este tutorial eu vou utilizar o seguinte domínio vllm-mgc.glaucio.tec.br , dito isto vamos seguir para acesso.
Primeiro acesso a nossa VM via SSH
Na página da nossa máquina virtual como no print acima, há um ícone azul para copiar o seu IPv4 Público e seu usuário.
e execute o comando ssh ubuntu@201.23.79.32 no seu terminal como no print abaixo
No primeiro acesso irá aparecer esta mensagem da imagem acima no seu terminal, apenas digite yes e aperte enter e agora com acesso ao servidor podemos iniciar a instalação das dependências.
Instalação do Docker
Para instalar o Docker rapidamente vamos automatizar esta parte, para isso abra algum editor pelo terminal como VIM ou nano, no meu caso para ser mais fácil irei utilizar o nano para criar o script de instalação do nosso Docker com o comando:
nano install_docker.sh
e você irá ver a seguinte tela, com o nosso editor nano aberto com um arquivo de texto em memória sem conteúdo algum
Para facilitar esta etapa de instalação do Docker, copie e cole o shell script abaixo.
#!/bin/bash
set -e
# 0. Antes de rodar o script lembre de executar `chmod +x install_docker.sh`
# 1. Limpeza de tentativas anteriores (Resolve o erro 'Malformed entry')
echo "🧹 Limpando configurações antigas..."
sudo rm -f /etc/apt/sources.list.d/docker.list
sudo apt-get update
# 2. Instalar dependências essenciais
echo "📦 Instalando dependências..."
sudo apt-get install -y ca-certificates curl gnupg lsb-release
# 3. Baixar Chave GPG
echo "🔑 Configurando chave GPG..."
sudo install -m 0755 -d /etc/apt/keyrings
# Se a chave já existir, removemos para baixar a mais nova
sudo rm -f /etc/apt/keyrings/docker.asc
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# 4. Adicionar Repositório (Fixo para 'noble' - Ubuntu 24.04)
echo "📂 Adicionando repositório 'noble'..."
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu noble stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 5. Instalar Docker
echo "⬇️ Instalando pacotes do Docker..."
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 6. Configurar permissão de usuário
echo "👤 Adicionando usuário '$USER' ao grupo docker..."
sudo usermod -aG docker $USER
echo "---"
echo "✅ Instalação concluída"
echo "⚠️ Para usar imediatamente, rode: newgrp docker"
echo "Valide instalação com docker run hello-world"
e deve ficar da seguinte forma
Agora aperte as teclas Ctrl e x para salvar e confirme para salvar o conteúdo que adicionamos ao nosso arquivo.
Feito isso, confirme se o nosso script foi salvo com sucesso e deve ter o mesmo texto do script acima, rode o comando:
cat install_docker.sh
e confira se está tudo ok. Feito isso precisamos fazer nosso script ser executável, para isso vamos precisar rodar o seguinte comando:
chmod +x install_docker.sh
Feito isso, podemos rodar nosso script de instalação do Docker com o comando:
./install_docker.sh
e correndo tudo bem irá aparecer no seu terminal as seguintes mensagens:
e então siga as instruções que foram exibidas para alterar o GID (Group ID) da sua sessão do terminal para o grupo "docker", sem que você precise deslogar e logar e rodar um container de hello-world para dar sorte haha e validar se a instalação correu bem.
Ao rodar os comandos sugeridos, você deve ter o seguinte resultado no seu terminal:
Se você teve os mesmos resultados dos prints acima, estamos prontos para instalar as dependências para que o Docker consiga se comunicar com a nossa GPU.
Instalação de drivers e nvidia-container-toolkit
Assim como a etapa de instalação do Docker criaremos um script para agilizar nossa instalação e facilitar a reprodutibilidade.
Crie nosso arquivo de setup da nossa máquina com o seguinte comando:
nano setup_nvidia.sh
cole o script abaixo como fizemos na etapa do Docker:
#!/bin/bash
set -e
# Configuração - Altere conforme necessário
NVIDIA_DRIVER_VERSION="${NVIDIA_DRIVER_VERSION:-570}"
# Cores para output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo -e "${GREEN}╔════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ Instalação NVIDIA Driver + Container Toolkit ║${NC}"
echo -e "${GREEN}║ Driver versão: ${NVIDIA_DRIVER_VERSION} ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════════════════════╝${NC}"
echo ""
# 0. Verificar se está rodando como root ou com sudo
if [ "$EUID" -eq 0 ]; then
echo -e "${RED}❌ Não execute este script como root. Use seu usuário normal.${NC}"
exit 1
fi
# 1. Verificar se driver já está instalado
echo "🔍 Verificando instalação existente..."
if command -v nvidia-smi &> /dev/null; then
echo -e "${YELLOW}⚠️ Driver NVIDIA já está instalado:${NC}"
nvidia-smi --query-gpu=driver_version,name --format=csv,noheader
read -p "Deseja continuar mesmo assim? (s/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Ss]$ ]]; then
echo "Instalação cancelada."
exit 0
fi
fi
# 2. Verificar se Docker está instalado
echo "🐳 Verificando Docker..."
if ! command -v docker &> /dev/null; then
echo -e "${RED}❌ Docker não encontrado. Execute primeiro o script 01-docker_install_script.sh${NC}"
exit 1
fi
echo -e "${GREEN}✓ Docker encontrado${NC}"
# 3. Atualizar sistema
echo ""
echo "📦 Atualizando lista de pacotes..."
sudo apt-get update
# 4. Instalar Driver NVIDIA
echo ""
echo "🎮 Instalando driver NVIDIA versão ${NVIDIA_DRIVER_VERSION}..."
sudo apt-get install -y nvidia-driver-${NVIDIA_DRIVER_VERSION}
# 5. Instalar NVIDIA Container Toolkit
echo ""
echo "📦 Configurando repositório NVIDIA Container Toolkit..."
# Adicionar chave GPG
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \
sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg --yes
# Adicionar repositório
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list > /dev/null
# Instalar toolkit
echo "⬇️ Instalando nvidia-container-toolkit..."
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
# 6. Configurar Docker para usar runtime NVIDIA
echo ""
echo "🔧 Configurando Docker para usar GPU NVIDIA..."
sudo nvidia-ctk runtime configure --runtime=docker
# 7. Reiniciar Docker
echo "🔄 Reiniciando serviço Docker..."
sudo systemctl restart docker
# 8. Resumo final
echo ""
echo -e "${GREEN}╔════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ ✅ Instalação concluída! ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${YELLOW}⚠️ IMPORTANTE: Reinicie a máquina para carregar o driver:${NC}"
echo ""
echo " sudo reboot"
echo ""
echo -e "${GREEN}Após reiniciar, valide a instalação com:${NC}"
echo ""
echo " # Verificar driver no host"
echo " nvidia-smi"
echo ""
echo " # Testar GPU no Docker"
echo " docker run --rm --gpus all nvidia/cuda:12.3.1-base-ubuntu22.04 nvidia-smi"
echo ""
salve com as teclas Ctrl e x e siga os caminhos para salvar e agora dê permissão para que ele também seja executável com o comando:
chmod +x setup_nvidia.sh
e agora vamos rodar com o comando:
./setup_nvidia.sh
e correndo tudo bem na instalação, você verá o seguinte resultado no seu terminal
e seguindo as instruções, vamos reiniciar a máquina para aplicar as novas configurações de driver.
com o comando:
sudo reboot
aguarde alguns segundos para a máquina reiniciar, aproveite para pegar um café, um chá ou uma água.
Agora vamos precisar acessar nossa máquina via SSH novamente, com o seguinte comando:
ssh ubuntu@ip-da-sua-maquina
Antes de seguirmos para a mão na massa para subir o nosso servidor e LLM, vamos validar se nossos passos anteriores funcionaram e tudo foi instalado corretamente com o comando:
docker run --rm --gpus all nvidia/cuda:12.3.1-base-ubuntu22.04 nvidia-smi
e caso tenha o seguinte resultado, suas instalações estão corretas e podemos ir para a etapa de subir o nosso servidor de LLM. 🎉
Subindo aplicação
Agora antes de partirmos para configurações e deploy, vale passarmos pela forma que foi pensada e arquitetada a essa nossa aplicação, passando por como ela vai ser servida, protegendo rotas do vLLM que não validam nosso token de autenticação e podem ser alvo de exploração por entidades mal-intencionadas.
Arquitetura da aplicação
Como podemos observar na imagem acima, a porta de entrada para o modelo é o servidor Caddy, pois quando expomos um servidor de LLM à internet, não basta configurar uma API Key e achar que está tudo protegido. O vLLM, por padrão, expõe endpoints como /health , /metrics e /docs que não validam autenticação, criando uma superfície de ataque significativa para scanners automatizados e potenciais explorações. Seguindo as recomendações oficiais de segurança do vLLM, implementamos uma arquitetura de "defense in depth": o vLLM roda em uma rede interna do Docker, completamente isolado da internet, enquanto o Caddy atua como nosso portão de entrada único. No Caddyfile, configuramos um allowlist restrita apenas com as rotas /v1/chat/completions , /v1/completions , /v1/models (opcional e pode ser removida) e /v1/embeddings (opcional e pode ser removida) que são encaminhadas para o vLLM. Todo o resto, incluindo os endpoints críticos /metrics e o /health interno do vLLM, é bloqueado com abort, retornando 403 Forbidden. Isso significa que mesmo que alguém descubra o IP do servidor, não consegue extrair métricas de performance, status detalhados do modelo ou acessar documentação sensível. Complementamos com TLS 1.2/1.3 forçado via Caddy e a API Key do vLLM protegendo os endpoints OpenAI e com isto temos um servidor que segue as recomendações de segurança da documentação oficial do vLLM, minimizamos os endpoints expostos, colocamos tudo atrás de um proxy reverso confiável, e mantemos o motor de inferência completamente inacessível diretamente e sua LLM roda segura, privada e pronta para produção.
- Não cheguei a configurar o rate limit, mas deixo como dever de casa caso tenha interesse.
Agora contextualizados, vamos à mão na massa.
Configurações importantes
Para subirmos a aplicação, vamos precisar criar os seguintes arquivos:
-
.env: Onde incluiremos as nossas variáveis de ambiente usadas pelo Caddy e pelo vLLM. -
Caddyfile: Configurações do nosso servidor de aplicação para fazer proxy reverso para o vLLM. -
compose.yml: Docker compose para orquestrarmos nossa aplicação de forma fácil.
e para termos uma organização, vamos criar uma pasta para envolver os arquivos que vamos precisar criar, e para criar a pasta e os arquivos rode o seguinte comando no seu terminal:
mkdir llm-server; cd llm-server; touch .env Caddyfile compose.yml
e depois valide se tudo correu bem, se sim terá um resultado como o seguinte:
Feito isto, vamos configurar nosso .env com as variáveis necessárias para rodar nossos containers, e para isso vamos utilizar o nano, o conteúdo que vamos precisar inserir no nosso arquivo são:
O que é cada variável?
-
vLLM
- VLLM_API_KEY: Será o token que a API do vLLM vai validar a presença para permitir a inferência, pode gerar um para nosso teste com o comando
openssl passwd -6 "uma chave bem segura aqui" - HF_TOKEN: Token para baixar modelos privados, caso você tenha algum fine tuning e deseja servir ele, para conseguir este token pode seguir a documentação oficial. Neste caso como vamos utilizar um modelo aberto, pode deixar qualquer valor.
- MODEL_NAME: Nome do modelo do Hugging Face que iremos utilizar

- Fica até como desafio, servir outro modelo como o gpt-oss-20b.
- VLLM_API_KEY: Será o token que a API do vLLM vai validar a presença para permitir a inferência, pode gerar um para nosso teste com o comando
-
Caddy
- DOMAIN: O domínio em que vamos servir nossa aplicação.
- EMAIL_SSL: O email que o caddy utiliza para que o CertMagic renove seus certificados.
# vLLM Configuration
VLLM_API_KEY=sua-chave-api-segura
HF_TOKEN=hf_seu_token_huggingface
MODEL_NAME=Qwen/Qwen3-30B-A3B-FP8
# Caddy/SSL Configuration
DOMAIN=vllm-mgc.glaucio.tec.br
EMAIL_SSL=meuemail+vllm-server@lorem.com
Agora contextualizados vamos preencher nosso .env , abra o arquivo com o comando:
nano .env
e cole suas variáveis preenchidas com seus dados, use Ctrl + x e quando aparecer "Save modified buffer?" confirme apertando a tecla y e depois quando aparecer "File Name to Write: .env", aperte Enter .
Vamos para o nosso arquivo Caddyfile , abra ele com o nano como já descrito no passo do .env e cole nele o seguinte conteúdo:
{$DOMAIN} {
# Habilita compressão Gzip/Zstd para performance
encode gzip zstd
# Configuração de Log (Opcional, bom para auditoria)
log {
output file /var/log/caddy/access.log
}
# REGRAS DE SEGURANÇA E ROTEAMENTO
# Bloqueia tudo por padrão, exceto o bloco 'handle' abaixo
# Página de status para verificar se o Caddy está online
handle /health {
respond "OK - Caddy is running on {$DOMAIN}" 200
}
# Página inicial com informações básicas
handle / {
header Content-Type text/html
respond `<!DOCTYPE html>
<html>
<head>
<title>vLLM API Server</title>
<style>
body { font-family: system-ui, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; background: #1a1a2e; color: #eee; }
h1 { color: #00d9ff; }
.status { background: #16213e; padding: 20px; border-radius: 8px; margin: 20px 0; }
.ok { color: #00ff88; }
code { background: #0f3460; padding: 2px 6px; border-radius: 4px; }
</style>
</head>
<body>
<h1>vLLM API Server</h1>
<div class="status">
<p class="ok">Proxy: Online</p>
<p>Domain: {$DOMAIN}</p>
</div>
<h3>API Endpoints:</h3>
<ul>
<li><code>/v1/chat/completions</code></li>
<li><code>/v1/completions</code></li>
<li><code>/v1/models</code></li>
<li><code>/v1/embeddings</code></li>
</ul>
<p><small>Health check: <a href="/health">/health</a></small></p>
</body>
</html>` 200
}
# Define o matcher para rotas OpenAI (Chat, Completions, Models, Embeddings)
@openai_routes {
path /v1/chat/completions
path /v1/completions
path /v1/models # pode remover caso não queria expor
path /v1/embeddings # como vamos servir apenas LLM não é muito útil aqui no nosso caso
}
# Processa apenas as rotas permitidas
handle @openai_routes {
reverse_proxy vllm:8000 {
# Configurações de timeout para streaming longo (LLMs)
flush_interval -1
transport http {
response_header_timeout 300s
}
}
}
# Captura qualquer outra rota (metrics, health, root) e retorna 403 Forbidden
handle {
abort
}
# TLS Configuration (Automático, mas forçando protocolos seguros)
tls {$EMAIL_SSL} {
protocols tls1.2 tls1.3
}
}
E por último nosso arquivo compose.yml para subirmos a aplicação, abra ele com nano compose.yml e cole o seguinte conteúdo:
services:
vllm:
image: vllm/vllm-openai:latest
container_name: vllm_inference
restart: unless-stopped
oom_score_adj: -500
environment:
- VLLM_API_KEY=${VLLM_API_KEY}
- HUGGING_FACE_HUB_TOKEN=${HF_TOKEN}
volumes:
- ./vllm_cache:/root/.cache/huggingface
deploy:
resources:
limits:
cpus: '6.0'
memory: 56G
reservations:
cpus: '4.0'
memory: 32G
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
ipc: host
shm_size: '16gb'
command: >
--model ${MODEL_NAME}
--served-model-name "qwen3-30b-a3b-fp8"
--host 0.0.0.0
--port 8000
--max-model-len 16384
--gpu-memory-utilization 0.95
--kv-cache-dtype fp8
--enable-prefix-caching
--max-num-seqs 8
--disable-log-requests
--reasoning-parser deepseek_r1
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8000/health || exit 1"]
interval: 15s
timeout: 10s
retries: 5
start_period: 300s # 5 minutos para carregar o modelo
proxy:
image: caddy:alpine
container_name: caddy_secure_proxy
restart: unless-stopped
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 64M
extra_hosts:
- "host.docker.internal:host-gateway"
ports:
- "80:80"
- "443:443"
- "443:443/udp"
environment:
- DOMAIN=${DOMAIN}
- EMAIL=${EMAIL_SSL}
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./caddy_data:/data
- ./caddy_config:/config
depends_on:
vllm:
condition: service_healthy
Com nossos arquivos preenchidos, podemos executar o comando para subir nosso docker compose:
docker compose --env-file .env up
e com isso começará a baixar as imagens que vamos utilizar:
Depois de ter baixado as imagens dos nossos containers, vai aparecer na sua tela a inicialização do vLLM
e após o vLLM baixar os pesos do modelo ele irá iniciar o caddy e aguarde um tempo para configurações de SSL sejam feitas
Aí agora para deixar os containers rodando em background, aperte a tecla d como sugerido na parte inferior do terminal
e para não ter de passar por isso na próxima, suba os containers com -d no comando para subir os containers e já liberar o terminal
docker compose --env-file .env up -d
Agora feito tudo isso, nossa aplicação está rodando lindamente, mas ainda não está respondendo pois precisaremos fazer as configurações de rede para liberar as portas 80 e 443 do nosso servidor.
No próximo passo irei explicar como resolver o erro do servidor não responder
Configuração de rede para liberar acessos externos pelo nosso DNS
Agora vamos para a última etapa de configuração antes de podermos usar nossa LLM, e fazer nossas tão desejadas chamadas à API.
Acesse novamente seu console do Magalu Cloud, estando na tela inicial, clique no menu sanduíche no lado superior direito e com isto irá abrir o menu lateral.
depois clique na opção com o texto "Network", ele irá abrir um submenu flutuante à esquerda dele e então clique na opção "Grupo de Segurança" e você será redirecionado para a tela de Grupo de Segurança.
Chegando na tela Grupo de Segurança, clique no botão "Criar grupo de segurança" e irá abrir uma tela para nomear e dar uma descrição para seu novo grupo de segurança, e preencha com um nome que vá lembrar, no meu caso coloquei "tutorial-vllm-l40s" como pode ser visto na imagem abaixo.
e confirmando a criação do nosso grupo, voltaremos para a página inicial de Grupo de Segurança, agora vamos precisar clicar no novo grupo que criamos, no meu caso foi "tutorial-vllm-l40s".
Clicando nele, iremos para a página do nosso Grupo de Segurança e nela iremos clicar no botão "Adicionar regra", preencha o formulário para que nosso servidor possa responder às requisições que faremos para ele. Devemos liberar a porta 443 para entrada, aceitando requisições de qualquer origem; ou, caso você tenha um IP fixo que sempre chamará a API, pode incluí-lo no preenchimento. O meu ficou da seguinte forma:
Clique em "Adicionar regra", e após fechar a tabela onde lista as regras deve conter agora a regra de entrada para a porta 443:
agora vá até a página da nossa máquina virtual e clique na "Tabzinha" (Contornada na imagem em vermelho) de rede e verá uma tela como a do print abaixo.
Estando nesta página, clique no botão azul com o texto "Adicionar grupo de segurança", na modal que irá abrir, busque o Grupo de segurança que criamos e configuramos.
Após adicionar, podemos validar se o nosso domínio está respondendo às requisições
Caso suas configurações estiverem corretas, você verá uma tela como acima, mas com o seu domínio.
Agora podemos fazer chamadas para nosso modelo com o seguinte comando:
curl -X POST 'https://vllm-mgc.glaucio.tec.br/v1/chat/completions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer sua-chave-api-segura' \
--data '{
"model": "qwen3-30b-a3b-fp8",
"messages": [
{
"role": "system",
"content": "Você é um assistente muito inteligente, que pensa antes de qualquer resposta, que segue a ciência, e deve ser muito dedicado a acertar."
},
{
"role": "user",
"content": "você conhece o acre? /no_think"
}
]
}'
Como estamos servindo um modelo com capacidade de "raciocínio", para habilitar enviamos na mensagem o texto /think e para desabilitar envie /no_think e configuramos o parser --reasoning-parser deepseek_r1 , então quando o "raciocínio" for ativado ele virá em choices[0].message.reasoning e caso esteja desativado, essa chave terá o valor nulo.
Exemplo de resposta com /think :
{
"id": "chatcmpl-871a1a570fd3a0d9",
"object": "chat.completion",
"created": 1769888901,
"model": "qwen3-30b-a3b-fp8",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "\n\nSim, conheço o **acre**! Ele pode se referir a **dois conceitos principais**:\n\n---\n\n### 1. **Unidade de área (acre)** \nO **acre** é uma unidade de medida de área do sistema imperial, amplamente usada em países como os Estados Unidos, Reino Unido e outros. \n- **Definição**: 1 acre = **4.046,86 metros quadrados** (m²). \n- **Equivalência**: \n - 1 acre ≈ 0,4047 hectares (ha). \n - 1 hectare ≈ 2,471 acres. \n- **Uso comum**: Medição de terrenos, campos de futebol, fazendas, etc. \n - Por exemplo, um campo de futebol oficial tem cerca de **0,71 acre**.\n\n---\n\n### 2. **Estado do Acre (Brasil)** \nO **Acre** também é um **estado da Amazônia brasileira**, localizado no **norte do Brasil**, na região da **Amazônia Ocidental**. \n- **Capital**: **Rio Branco**. \n- **Características**: \n - Faz parte da **Bacia do Rio Amazonas**. \n - Conhecido por sua **floresta tropical**, riqueza em biodiversidade e culturas indígenas. \n - Tem uma economia baseada em **extrativismo (como a seringueira)** e **agricultura**. \n - O **Parque Nacional do Acre** e a **Reserva da Biosfera do Acre** são áreas protegidas. \n- **População**: Cerca de **900.000 habitantes** (estatísticas de 2023). \n\n---\n\nSe você se referia a algo específico (como uma empresa, termo técnico ou outro contexto), me avise que posso aprofundar! 😊",
"refusal": null,
"annotations": null,
"audio": null,
"function_call": null,
"tool_calls": [],
"reasoning": "\nOkay, the user is asking if I know about Acre. First, I need to confirm what exactly they're referring to. Acre can mean a few things. The most common is the unit of area, which is 4,046.86 square meters. But there's also Acre as a place, like the Acre state in Brazil, or maybe even a company or a term in another context.\n\nI should start by acknowledging that Acre can refer to multiple things. Let me break it down. First, the unit of area. Explain that it's a unit used in the imperial system, commonly used in countries like the US, UK, and others. Mention its conversion to square meters and other units. Then, mention the Brazilian state, Acre, located in the northwest of Brazil, part of the Amazon region. Highlight its geography, maybe the capital, Rio Branco, and some key points about the state, like its natural resources or cultural aspects.\n\nWait, the user might be asking about the state, but I should cover both possibilities. Also, check if there's another context, like a company or a term in a different field. But I think the two main ones are the unit and the state. Make sure to present both clearly. Avoid any confusion by structuring the answer with headings or bullet points. Also, verify the accuracy of the information, like the exact area of an acre, the location of Acre state, and its capital. Maybe mention that the state is known for its rainforests and biodiversity. Double-check the conversion factors to ensure they're correct. Alright, that should cover the main points.\n",
"reasoning_content": "\nOkay, the user is asking if I know about Acre. First, I need to confirm what exactly they're referring to. Acre can mean a few things. The most common is the unit of area, which is 4,046.86 square meters. But there's also Acre as a place, like the Acre state in Brazil, or maybe even a company or a term in another context.\n\nI should start by acknowledging that Acre can refer to multiple things. Let me break it down. First, the unit of area. Explain that it's a unit used in the imperial system, commonly used in countries like the US, UK, and others. Mention its conversion to square meters and other units. Then, mention the Brazilian state, Acre, located in the northwest of Brazil, part of the Amazon region. Highlight its geography, maybe the capital, Rio Branco, and some key points about the state, like its natural resources or cultural aspects.\n\nWait, the user might be asking about the state, but I should cover both possibilities. Also, check if there's another context, like a company or a term in a different field. But I think the two main ones are the unit and the state. Make sure to present both clearly. Avoid any confusion by structuring the answer with headings or bullet points. Also, verify the accuracy of the information, like the exact area of an acre, the location of Acre state, and its capital. Maybe mention that the state is known for its rainforests and biodiversity. Double-check the conversion factors to ensure they're correct. Alright, that should cover the main points.\n"
},
"logprobs": null,
"finish_reason": "stop",
"stop_reason": null,
"token_ids": null
}
],
"service_tier": null,
"system_fingerprint": null,
"usage": {
"prompt_tokens": 58,
"total_tokens": 836,
"completion_tokens": 778,
"prompt_tokens_details": null
},
"prompt_logprobs": null,
"prompt_token_ids": null,
"kv_transfer_params": null
}
Exemplo de resposta com /no_think :
{
"id": "chatcmpl-a0710ba10d25e658",
"object": "chat.completion",
"created": 1769889464,
"model": "qwen3-30b-a3b-fp8",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "\n\nClaro, eu conheço o Acre! O Acre é um estado da Amazônia brasileira, localizado no extremo oeste do Brasil, fazendo fronteira com a Bolívia e o Peru. É um dos estados mais extensos do Brasil e é conhecido por sua vasta floresta tropical, rica em biodiversidade e por ser um dos últimos grandes territórios preservados da Amazônia.\n\nAlguns pontos interessantes sobre o Acre:\n\n- **Capital**: Rio Branco\n- **População**: Cerca de 900 mil habitantes (dados aproximados)\n- **Cultura**: Mistura de influências indígenas, brasileiras e bolivianas.\n- **Economia**: Baseada principalmente na agricultura (como a seringueira, o cauim, o açaí), na pecuária e na exploração de recursos naturais.\n- **Ecologia**: É uma das regiões mais preservadas da Amazônia, com muitas áreas de proteção ambiental.\n- **História**: Foi cedido ao Brasil pela Bolívia em 1903, através do Tratado de Petrópolis.\n\nO Acre também é famoso por sua paisagem única, com rios, florestas e uma cultura rica e diversificada. Se quiser, posso te contar mais sobre algum aspecto específico do Acre!",
"refusal": null,
"annotations": null,
"audio": null,
"function_call": null,
"tool_calls": [],
"reasoning": "\n\n",
"reasoning_content": "\n\n"
},
"logprobs": null,
"finish_reason": "stop",
"stop_reason": null,
"token_ids": null
}
],
"service_tier": null,
"system_fingerprint": null,
"usage": {
"prompt_tokens": 60,
"total_tokens": 380,
"completion_tokens": 320,
"prompt_tokens_details": null
},
"prompt_logprobs": null,
"prompt_token_ids": null,
"kv_transfer_params": null
}
Então a partir de agora é só ser feliz.
Em breve trarei mais um post fazendo múltiplas requisições para nosso modelo, trazendo números de tempo de resposta e qualidade das respostas do modelo.
























Top comments (0)