Deploy com Kamal
Published on: 2026-09-27
Para o blog em si, em termos de seu funcionamento, não faltam exemplos bons nas interwebs. Por exemplo, temos o post do blog do Dashbit, e também essa lição sobre nimble_publisher do Elixir School.
Para servir o blog com o bandit, o que eu fiz foi apontar a configuração do bandit para um router, e criar as rotas específicas que eu precisava. O código abaixo exemplifica um pouco isso:
# Save this to a file, ie., server.exs, and run with "elixir server.exs"
Mix.install(
[
{:bandit, "~> 1.12"}
]
)
defmodule Server.Router do
use Plug.Router
plug(:match)
plug(:dispatch)
get "/" do
send_resp(conn, 200, "hello!")
end
get "/posts/:id" do
# This is just a super simple example, but in a nutshell you get the post and then render
# post = Blog.get_post_by_id!(id)
# send_resp(conn, 200, post)
end
match _ do
send_resp(conn, 404, "oops")
end
end
defmodule Server.Application do
use Application
def start(_type, _args) do
children = [
{Bandit, plug: Server.Router}
]
opts = [strategy: :one_for_one, name: Server.Supervisor]
Supervisor.start_link(children, opts)
end
end
{:ok, _} = Server.Application.start(:normal, [])
Process.sleep(:infinity)
Por padrão o bandit irá rodar o servidor na porta 4000; abra http://localhost:4000 para ver o resultado.
Kamal
Utilizar o Kamal é, de certa forma, bastante simples considerando o meu caso (somente um site estático, sem outros serviços como banco de dados). Eu tive que fazer alguns ajustes dado a minha escolha pelo Hetzner e por não ter um endereço IPV4 para o servidor.
O Kamal leva em conta que a sua aplicação esteja dockerizada e servida em algum repositório de containers, como por exemplo o Docker Hub. Não vou entrar em detalhes aqui pois já existem diversos exemplos bons na internet, inclusive o próprio Phoenix tem um comando mix para gerar um Dockerfile bem legal.
O primeiro passo é ter um servidor acessível via ssh, e um usuário com as permissões corretas. Comprei um servidor na Hetzner, o tier mais barato, que já dispõe de um endereço IPV6 (endereços IPV4 tem um custo extra).
Certifique-se que o servidor esteja acessível via ssh. Para facilitar eu criei uma entrada em ~/.ssh/config para apenas usar ssh hetzer e entrar como root no servidor.
Outro problema que tive foi em relação ao IPV6. No momento que eu estava configurando o deploy, meu roteador não estava com suporte a IPV6, assim eu não conseguia acessar o servidor diretamente. Eu usei o Cloudlare WARP para rotear o tráfego de modo que a "origem" também fosse IPV6:
desktop --(IPv4, túnel WARP)--> Cloudflare --(IPv6)--> servidor
Uma vez que a conexão ssh estava correta, Docker Hub configurado, eu consegui executar o kamal setup. Caso você queira que o Kamal forneça HTTPS via Let's Encrypt, certifique-se de ligar a config ssl no arquivo de deploy.