O Kamal não corre no seu VPS. É uma ferramenta de deploy que instala na sua própria máquina ou no seu runner de CI e que se liga ao servidor por SSH para fazer o trabalho. A Basecamp criou-a para publicar aplicações Rails sem Kubernetes, mas faz deploy de tudo o que se construa numa imagem Docker.
Essa distinção muda aquilo que anda à procura. O VPS é o destino do Kamal, por isso tem de ser suficientemente grande para a sua aplicação, as bases de dados dela e alguns dias de versões da imagem. A pegada do Kamal no servidor é nula.
O que o Kamal deixa realmente no servidor
O kamal setup liga-se por SSH (como root por omissão, autenticado pela sua chave SSH) e executa três passos: instalar o Docker se não existir, arrancar os acessórios declarados e depois fazer deploy da aplicação. A partir daí, o servidor corre:
- kamal-proxy — um proxy HTTP pequeno que ocupa as portas 80 e 443, obtém certificados Let’s Encrypt e retém os pedidos que chegam durante um deploy até o contentor substituto estar pronto.
- Os contentores da aplicação — um conjunto por cada papel definido em
config/deploy.yml. - Os acessórios — o Postgres, o Redis ou os outros serviços que listou na configuração.
O Kamal em si é uma gem (gem install kamal, 2.12.0 à data) e não deixa nenhum daemon a correr.
Pré-requisitos
Antes de começar, tenha:
- Um VPS com uma instalação Linux limpa e acesso SSH como root por chave (o Ubuntu 24.04 é uma escolha sensata)
- Um registo de contentores de onde o servidor possa descarregar — Docker Hub, GitHub Container Registry ou o do seu fornecedor
- Ruby localmente para o
gem install kamal; sem Ruby também pode correr o Kamal a partir de uma imagem de contentor, com algumas limitações - Um
Dockerfilefuncional para a sua aplicação
Escolher o fornecedor de VPS
Como o servidor apenas corre contentores, avalie os fornecedores pela fiabilidade da rede, pela margem de disco e pela rapidez com que consegue reconstruir um servidor:
| Fornecedor | Preço | Características | Ligação de afiliado |
|---|---|---|---|
| Contabo VPS | 5,99 EUR/mês | 400 GB de disco absorvem imagens grandes e um histórico longo de rollback | Contabo VPS |
| Hetzner Cloud | 5,49 EUR/mês | 2 vCPU / 4 GB / 40 GB NVMe, snapshots para reconstruir depressa | Hetzner Cloud |
| DigitalOcean | 6 USD/mês | A melhor documentação e API para automatizar o próprio servidor | DigitalOcean |
| Vultr | 5 USD/mês | Grande escolha de regiões para pôr a aplicação perto dos utilizadores | Vultr |
| Linode | 5 USD/mês | Preços previsíveis, configuração de rede simples | Linode |
Para uma comparação completa, consulte a nossa comparação de VPS.
A DigitalOcean é aqui o ponto de partida mais simples, porque a documentação cobre exactamente o trabalho ao nível do servidor que o Kamal não faz por si: regras de firewall, swap e actualizações automáticas.
Preparar o servidor
- Crie o VPS com uma imagem mínima de Ubuntu 24.04 e a sua chave SSH associada.
- Confirme que o acesso SSH como root funciona, já que é assim que o Kamal se liga por omissão:
ssh root@ip-do-seu-vps
- Abra apenas o necessário. O kamal-proxy termina o TLS no servidor, por isso bastam as portas 22, 80 e 443:
ufw allow 22,80,443/tcp && ufw enable
Não precisa de instalar o Docker: o Kamal trata disso no primeiro kamal setup se ele faltar.
Instalar o Kamal e escrever a configuração
Na sua própria máquina, dentro da pasta da aplicação:
gem install kamal
kamal init
O kamal init cria o config/deploy.yml. Uma configuração mínima funcional precisa de um nome de serviço, de uma imagem e de pelo menos um servidor:
service: myapp
image: your-registry-user/myapp
servers:
web:
hosts:
- 203.0.113.10
registry:
username: your-registry-user
password:
- KAMAL_REGISTRY_PASSWORD
proxy:
ssl: true
host: app.example.com
Os segredos ficam em .kamal/secrets, que o Kamal lê no momento do deploy. Procura primeiro .kamal/secrets-common e depois .kamal/secrets:
KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD
Mantenha esse ficheiro fora do controlo de versões e tire o valor do ambiente da shell ou de um gestor de palavras-passe.
O primeiro deploy
kamal setup
Este único comando instala o Docker, arranca os acessórios, constrói e envia a sua imagem e põe a aplicação a correr. Todos os deploys seguintes resumem-se a:
kamal deploy
Para ver o que está a correr no servidor:
kamal app containers
Onde a imagem é construída
Por omissão o Kamal constrói localmente, na máquina de onde o executa, e depois envia para o registo. O servidor apenas descarrega. Se o seu portátil for arm64 e o VPS amd64, fixe a arquitectura de destino ou aponte o Kamal para um builder remoto:
builder:
arch: amd64
remote: ssh://[email protected]
A compilação cruzada por emulação é lenta o suficiente para se notar em cada deploy. Se o VPS for a sua única máquina amd64, pode servir também de builder — mas então dimensione-o para uma construção Docker e não apenas para correr a aplicação, o que costuma implicar subir um plano.
Dimensionar o disco
O Kamal guarda contentores e imagens antigas no servidor para que o kamal rollback possa arrancar uma versão anterior sem voltar ao registo. Por omissão limpa-os ao fim de três dias. Conte com os dados próprios da aplicação mais cerca de três dias de versões da imagem e as camadas base partilhadas.
Uma imagem de 1 GB publicada algumas vezes por dia cabe com folga nos 40 GB NVMe da Hetzner. Uma imagem de 3 GB enche um disco de 25 GB numa semana, e um disco cheio parte o deploy seguinte, não o actual — o que torna o problema fácil de ignorar até se tornar urgente.
A comutação sem interrupções
O kamal-proxy só encaminha o tráfego para o contentor novo quando este responde 200 ao GET /up. Daí decorrem duas coisas:
- A sua aplicação precisa de um endpoint
/up. O Rails traz um; os outros frameworks costumam exigir umas poucas linhas. - Esse endpoint só deve devolver 200 quando a aplicação já consegue servir pedidos. Se responder antes de as ligações à base de dados estarem prontas, os utilizadores chegam cedo demais ao contentor novo.
Se a verificação de saúde nunca passar, o deploy expira e o Kamal deixa o contentor antigo a servir o tráfego.
Proteger o deploy
- O Kamal liga-se como root por SSH, por isso desactive por completo a autenticação por palavra-passe e apoie-se em chaves.
- Deixe o TLS a cargo do kamal-proxy. Pôr um segundo proxy inverso à frente só complica o caminho dos certificados.
- Acrescente swap nos servidores de 4 GB. Durante um deploy o contentor antigo e o novo coexistem por instantes, e um servidor que comece a fazer swap nesse momento fica lento o suficiente para ultrapassar o tempo limite da verificação de saúde.
- Guarde a palavra-passe do registo em
.kamal/secretse não emconfig/deploy.yml, que vai para o repositório.
Notas finais
- Passe a correr o
kamal deploya partir da CI assim que o caminho manual funcionar. A configuração é idêntica; muda apenas a origem dos segredos. - O
kamal rollback [versão]é imediato enquanto a imagem antiga estiver no disco, por isso verifique comkamal app containersse ainda existe um destino de rollback. - O deploy de uma segunda aplicação no mesmo servidor é suportado no Kamal 2 — o kamal-proxy encaminha por nome de anfitrião, portanto cada aplicação só precisa do seu próprio
serviceeproxy.host.
Para aprofundar a escolha do servidor, consulte a nossa comparação de VPS.
Frequently asked questions
O Kamal corre no VPS ou na minha própria máquina?
O Kamal corre na sua máquina ou no seu runner de CI. É uma gem de Ruby que se liga ao servidor por SSH, instala o Docker caso falte e arranca os seus contentores. No VPS ficam apenas o kamal-proxy e os contentores da aplicação e dos acessórios, nunca o próprio Kamal.
De quanto disco precisa um VPS usado como destino do Kamal?
Conte com os dados da sua aplicação mais cerca de três dias de versões da imagem, porque o Kamal guarda contentores e imagens antigas para os rollbacks e só os limpa ao fim de três dias. Uma imagem de 1 GB publicada várias vezes por dia cabe em 40 GB; uma de 3 GB num disco de 25 GB não cabe.
Porque é que o meu deploy com Kamal expira e reverte?
O kamal-proxy só desvia o tráfego quando o contentor novo responde 200 ao GET /up. Se a sua aplicação não expõe esse endpoint, ou se ainda devolve um erro enquanto está a arrancar, a verificação de saúde nunca passa e o Kamal repõe o contentor anterior.