Hospedar sua própria IA em uma VPS Linux com Ollama e Open WebUI significa manter as conversas no seu servidor e parar de pagar por requisição. O problema: a API do Ollama não tem nenhuma autenticação, então uma porta 11434 aberta na internet é IA de graça para quem a encontrar. Este guia mostra uma instalação em que só o Nginx, com HTTPS, fica acessível de fora.
Por que uma instância Ollama exposta é um problema
O Ollama oferece uma API REST muito prática, mas sem senha e sem chave. Qualquer pessoa que alcance a porta pode listar seus modelos, baixar novos até encher o disco, apagá-los ou disparar gerações que deixam a CPU da sua VPS no talo. Os mantenedores consideram que a autenticação é papel de um proxy reverso, então cabe a você configurá-la.
O risco é real. Em fevereiro de 2026, o buscador de vazamentos LeakIX contava mais de 12 mil instâncias Ollama acessíveis sem autenticação. No mesmo ano, uma falha de gravidade alta (CVE-2026-7482, apelidada de “Bleeding Llama”) permitia ler a memória de um servidor Ollama acessível, sem nenhuma credencial. Uma instância que só escuta localmente fica simplesmente fora do alcance desse tipo de ataque.
A arquitetura que vamos montar
- Ollama escuta apenas em
127.0.0.1:11434. - Open WebUI roda no Docker e escuta apenas em
127.0.0.1:3000. - Nginx é o único serviço público: recebe o tráfego HTTPS na porta 443 e repassa para o Open WebUI.
- O firewall só libera SSH, HTTP (para o certificado) e HTTPS.
- Open WebUI cuida das contas: um administrador e cadastros fechados.
O guia parte de uma VPS Linux com Ubuntu 24.04 ou Debian 12, acesso sudo, Docker já instalado e um subdomínio, por exemplo ia.seu-dominio.com.br, apontando para o IP do servidor.
Qual VPS escolher: tabela de RAM e CPU sem GPU
Em uma VPS sem placa de vídeo, tudo depende da RAM e do número de núcleos. O modelo precisa caber inteiro na memória, com folga para o contexto da conversa, para o Open WebUI (reserve cerca de 1 GB) e para o sistema. Os tamanhos abaixo são os das versões padrão (quantizadas em 4 bits) publicadas na biblioteca do Ollama.
| VPS | Modelos realistas | Exemplos (tamanho do download) | Uso |
|---|---|---|---|
| 4 GB de RAM, 2 vCPU | De 1 a 3 bilhões de parâmetros | gemma3:1b (806 MB), qwen3:1.7b (1,4 GB), llama3.2:3b (2,0 GB) | Testes, resumos curtos, assistente simples |
| 8 GB de RAM, 3 vCPU | Até 4B com folga, 8B possível mas no limite | qwen3:4b (2,5 GB), gemma3:4b (3,4 GB), qwen3:8b (5,2 GB) | Uso pessoal no dia a dia |
| 12 GB de RAM, 4 vCPU | 8B com folga, 12-14B possível mas no limite | qwen3:8b (5,2 GB), gemma3:12b (8,2 GB), qwen3:14b (9,3 GB) | Redação, código, equipe pequena |
| 32 GB de RAM ou mais (servidor dedicado) | De 27 a 32B | gemma3:27b (17 GB), qwen3:32b (20 GB) | Qualidade maior, respostas lentas sem GPU |
Na SoLinux, isso corresponde à VPS Linux 04G (4 GB, 2 núcleos, 45 GB NVMe), à VPS Linux 08G (8 GB, 3 núcleos, 50 GB NVMe) e à VPS Linux 12G (12 GB, 4 núcleos, 70 GB NVMe), sem fidelidade, a partir de 7 € por mês para a 04G, disponíveis na França, na Alemanha e em Nova York. Para uso frequente, a 08G é o melhor ponto de partida; a 12G vale a pena quando você quer um modelo 8B com folga ou vários usuários.
Seja realista quanto à velocidade: sem GPU, um modelo 7-8B escreve a resposta palavra por palavra, a poucas palavras por segundo, e a CPU fica em 100 % durante a geração. Modelos de 3-4B costumam ser o melhor equilíbrio. O armazenamento NVMe pesa sobretudo no carregamento inicial do modelo na memória.
Passo 1: preparar o servidor e o firewall
Comece atualizando o sistema e depois feche tudo o que não for indispensável. Com UFW:
sudo apt update && sudo apt upgrade -y
sudo apt install -y ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
Se preferir usar o nftables diretamente (e não junto com o UFW), este é o equivalente mínimo para a chain de entrada, em /etc/nftables.conf:
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
iif "lo" accept
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
tcp dport { 22, 80, 443 } accept
}
}
sudo nft -c -f /etc/nftables.conf # confere a sintaxe
sudo systemctl enable --now nftables
Armadilha clássica: uma porta publicada pelo Docker com -p 3000:8080 fica aberta em todas as interfaces e passa por cima das regras do UFW, porque o Docker escreve as próprias regras de firewall. Por isso este guia não publica nenhuma porta do Docker.
Passo 2: instalar o Ollama e mantê-lo local
O Ollama é instalado no Linux com o script oficial, que cria um usuário ollama e um serviço systemd:
curl -fsSL https://ollama.com/install.sh | sh
Depois, confira se o serviço está rodando:
ollama --version
sudo systemctl enable --now ollama
sudo systemctl status ollama
Por padrão, o Ollama escuta em 127.0.0.1:11434. Muitos tutoriais mandam colocar OLLAMA_HOST em 0.0.0.0 para o Docker conseguir acessá-lo: é exatamente isso que expõe a API. Em vez disso, fixe o endereço local de forma explícita, com um override do systemd que sobrevive às atualizações:
sudo systemctl edit ollama
Adicione estas linhas na área indicada:
[Service]
Environment="OLLAMA_HOST=127.0.0.1:11434"
Environment="OLLAMA_MAX_LOADED_MODELS=1"
Environment="OLLAMA_NUM_PARALLEL=1"
As duas últimas variáveis limitam o Ollama a um modelo carregado e uma requisição por vez, o que evita estourar a RAM de uma VPS sem GPU. Recarregue e confira a escuta:
sudo systemctl daemon-reload
sudo systemctl restart ollama
sudo ss -tlnp | grep 11434
# esperado: 127.0.0.1:11434, nunca 0.0.0.0:11434 nem [::]:11434
curl http://127.0.0.1:11434
# esperado: Ollama is running
Em seguida, baixe um modelo adequado à sua VPS e teste pela linha de comando:
ollama pull qwen3:4b
ollama run qwen3:4b "Explique em uma frase o que é um proxy reverso."
ollama list
Passo 3: subir o Open WebUI com Docker, sem porta pública
O comando de início rápido do Open WebUI publica a porta 3000 e acessa o Ollama via host.docker.internal, o que obriga o Ollama a escutar em todas as interfaces. Aqui fazemos diferente: o contêiner compartilha a pilha de rede do host (--network=host), acessa o Ollama em 127.0.0.1 e só escuta em 127.0.0.1:3000, graças às variáveis HOST e PORT.
# chave secreta fixa: sem ela, as sessões caem a cada reinício
sudo mkdir -p /etc/open-webui
openssl rand -hex 32 | sudo tee /etc/open-webui/secret > /dev/null
sudo chmod 600 /etc/open-webui/secret
DOMINIO=ia.seu-dominio.com.br # seu subdomínio
sudo docker run -d --name open-webui \
--network=host \
-e HOST=127.0.0.1 \
-e PORT=3000 \
-e OLLAMA_BASE_URL=http://127.0.0.1:11434 \
-e WEBUI_SECRET_KEY="$(sudo cat /etc/open-webui/secret)" \
-e CORS_ALLOW_ORIGIN="https://$DOMINIO" \
-v open-webui:/app/backend/data \
--restart always \
ghcr.io/open-webui/open-webui:main
O volume open-webui guarda contas, conversas e configurações. Em produção, você pode trocar a tag main por um número de versão específico e decidir quando atualizar. Confira a escuta depois de um minuto (a primeira inicialização demora um pouco):
sudo ss -tlnp | grep 3000
# esperado: 127.0.0.1:3000
curl -I http://127.0.0.1:3000
Passo 4: criar a conta de administrador antes de expor qualquer coisa
A primeira conta criada no Open WebUI vira administradora. Não deixe esse lugar para um desconhecido que encontre seu subdomínio antes de você: crie a conta antes de configurar o Nginx, por um túnel SSH. No seu computador:
ssh -L 3000:127.0.0.1:3000 usuario@IP_DA_VPS
Depois abra http://localhost:3000 no navegador do seu computador e crie a conta de administrador com uma senha longa e exclusiva. Em seguida, nas configurações de administração (seção de usuários ou de cadastros, conforme a versão):
- desative os novos cadastros;
- se precisar deixá-los abertos por um tempo, mantenha o papel padrão dos novos usuários como pendente (pending), para aprovar cada conta você mesmo;
- crie você mesmo as contas dos seus colegas pela gestão de usuários.
Nunca desative a autenticação (WEBUI_AUTH=False) em uma instância acessível pela internet.
Passo 5: Nginx com HTTPS na frente do Open WebUI
Instale o Nginx e o Certbot:
sudo apt install -y nginx certbot python3-certbot-nginx
Adicione um limite de tentativas de login em /etc/nginx/conf.d/limites.conf:
limit_req_zone $binary_remote_addr zone=owui_login:10m rate=5r/m;
Depois crie /etc/nginx/sites-available/open-webui. O Open WebUI usa WebSockets e transmite as respostas em streaming: é preciso usar HTTP/1.1, repassar os cabeçalhos Upgrade e desligar o buffering, senão as respostas chegam de uma vez só ou são cortadas.
server {
listen 80;
server_name ia.seu-dominio.com.br;
client_max_body_size 50M;
# limita as tentativas de senha
location = /api/v1/auths/signin {
limit_req zone=owui_login burst=5 nodelay;
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 1800s;
proxy_send_timeout 1800s;
}
}
Ative o site, teste a configuração e peça o certificado. O Certbot adiciona sozinho o bloco HTTPS na porta 443 e o redirecionamento a partir do HTTP:
sudo ln -s /etc/nginx/sites-available/open-webui /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d ia.seu-dominio.com.br --redirect
sudo certbot renew --dry-run
Para uma equipe pequena, você pode acrescentar uma segunda barreira com auth_basic no bloco location /, ou restringir o acesso a poucos IPs com allow e deny. Essas proteções se somam à conta do Open WebUI, não a substituem.
Conferir que nada está exposto
No servidor, liste as portas em escuta: só 22, 80 e 443 podem aparecer em um endereço público.
sudo ss -tlnp
No seu computador, teste o IP da VPS: as portas 11434 e 3000 devem recusar a conexão ou não responder. Só o seu subdomínio em HTTPS, aberto no navegador, deve mostrar a tela de login.
nc -zv -w 3 IP_DA_VPS 11434 # deve falhar
nc -zv -w 3 IP_DA_VPS 3000 # deve falhar
Manter a instalação atualizada
- Ollama: rode de novo o script de instalação oficial. O override do systemd é mantido; mesmo assim, confira a escuta com
ss -tlnpdepois de cada atualização. A falha CVE-2026-7482 está corrigida desde a versão 0.17.1: confira a sua comollama --versione não deixe uma versão antiga rodando. - Open WebUI:
docker pullda imagem, depoisdocker stop,docker rme o mesmo comandodocker run. O volume preserva seus dados. - Backups: faça backup regular do volume
open-webui(contas e conversas); os modelos podem ser baixados de novo. - Logs:
journalctl -u ollama,docker logs open-webuie/var/log/nginx/para identificar tentativas de login repetidas.
Perguntas frequentes
Preciso de GPU para rodar o Ollama em uma VPS?
Não. O Ollama funciona só com a CPU. As respostas são mais lentas do que com placa de vídeo, mas um modelo de 3 a 8 bilhões de parâmetros é perfeitamente usável em uma VPS com 8 a 12 GB de RAM.
Como usar a API do Ollama de outra máquina sem expô-la?
Use um túnel SSH: ssh -L 11434:127.0.0.1:11434 usuario@IP_DA_VPS e depois consulte http://localhost:11434 no seu computador. Para um aplicativo de terceiros, o Open WebUI também pode gerar chaves de API por usuário, atrás do seu Nginx com HTTPS.
O Open WebUI não mostra nenhum modelo. O que fazer?
Confira se ollama list retorna modelos, se curl http://127.0.0.1:11434 responde e se o contêiner foi iniciado com --network=host e OLLAMA_BASE_URL=http://127.0.0.1:11434. A conexão também pode ser verificada nas configurações de administração, na seção de conexões.
Quantas pessoas podem usar ao mesmo tempo?
Sem GPU, conte com uma geração por vez; as outras requisições aguardam na fila. Para dois ou três usuários ocasionais, uma VPS 12G com um modelo 4B ou 8B dá conta; acima disso, um servidor dedicado com mais núcleos e RAM passa a ser necessário.