Deploy de aplicação usando curl

Existem vários desafios para pequenas equipes distribuírem binários atualmente. Se você simplesmente colocar um aplicativo para download em um site, imediatamente as ferramentas de busca vão marcar seu site como conteúdo suspeito. Os navegadores colocam um aviso assustador para o usuário e não existe como remover esse aviso, mesmo com o binário assinado. O aviso só é removido se houver usuários suficientes fazendo download do seu binário sem reportar problemas.

Permitir que o usuário baixe o binário de algum site já conhecido, mesmo o GitHub não é interessante, principalmente em aplicativos de código fechado.

Empacotar o binário suportando os vários formatos de gerenciamento de pacotes para as várias versões de Linux é trabalhoso demais para uma equipe pequena.

Uma alternativa é usar curl com scripts bash como no exemplo abaixo.

curl -fsSL https://example.com | bash

Os parâmetros -fsSL são para silenciar a saída, seguir redirecionamentos, e usar SSL.

  • -f: Falha silenciosamente em erros HTTP.
  • -s: Silencia a barra de progresso.
  • -S: Quando usado com -s, mostra erros HTTP (mas não a barra de progresso).
  • -L: Segue redirecionamentos de localização.

Essa abordagem, entretanto, não é perfeita, tem várias implicações de segurança, muitos usuários, principalmente os avançados, vão torcer o nariz para essa abordagem e com razão. 

Mesmo com desenvolvedores bem intencionados, existe uma grande possibilidade que um script bash não tão perfeito arruíne um sistema que está perfeitamente configurado.

É sempre interessante inspecionar o que o script de instalação faz antes de executar.

curl -fsSL https://example.com | less

Para o desenvolvedor, além de tornar o deploy muito mais simples também é possível fazer um script que verifica se a máquina destino tem as dependências e informa o usuário do que precisa ser instalado.

O script de instalação também já detecta a arquitetura e o sistema operacional, de forma que o usuário não precisa se preocupar em qual versão instalar.

Entretanto, existe sempre a possibilidade de falha e é muito frustrante para o usuário se um script falhar no meio da operação, então aqui vão algumas dicas para tornar ter o melhor resultado.

  • Mantenha seu script de instalação pequeno e fácil de ser lido, adicione comentários relevantes.

  • Se precisar usar arquivos temporários use sempre a variável $TMPDIR para não espalhar arquivos por qualquer lugar do sistema.

  • Se o usuário precisar fazer alguma configuração manual, como ajustar o PATH, por exemplo, coloque isso em uma mensagem bem clara no fim da execução do script.

  • O binário que vai ser distribuído precisa ter o mínimo de dependências possível, idealmente sendo completamente estático para não depender de nada, nem mesmo da libc. Dessa forma será muito mais fácil a instalação ser bem sucedida e o aplicativo ser executado sem problemas.

  • Configurações devem ficar nos lugares adequados e esperados como o .config/nome_do_aplicativo ou /etc/nome_do_aplicatio e bem documentada.

  • É interessante que a instalação não precise de permissões de superusuário para funcionar, mas daí você precisa perguntar para o usuário onde colocar o binário e alertá-lo para ajustar a variável PATH. Se preferir que a instalação seja feita por um superusuário você poderá colocar o binário em /usr/local/bin que já deve estar no PATH, por um lado isso evita que o usuário tenha que alterar o sistema, por outro lado, ele está dando um voto de confiança muito grande no seu trabalho.

  • Ao fim da instalação lembre-se de informar também como remover o seu programa.

Aqui tem um exemplo de script de instalação muito básico, mas que já detecta sistema operacional e arquitetura.

#!/bin/bash

# Determine OS, architecture, and download URL
OS=$(uname)
ARCH=$(uname -m)
BASE_URL="https://example.com"
BIN_DIR="/usr/local/bin"
BIN_NAME="appname"

# Prepare the download URL
DOWNLOAD_URL="$BASE_URL/$OS/$ARCH/$BIN_NAME"

# Download and install
echo "Downloading $DOWNLOAD_URL to $BIN_DIR/$BIN_NAME"
curl -sSL $DOWNLOAD_URL -o $BIN_DIR/$BIN_NAME
if [ $? -ne 0 ]; then
    echo "Failed to install $BIN_NAME"
    exit 1
fi

chmod +x $BIN_DIR/$BIN_NAME
echo "Installed $BIN_NAME to $BIN_DIR/$BIN_NAME"

O que podemos concluir é que não é a forma ideal de distribuir software, mas é sem dúvida uma das menos problemáticas, principalmente se seus usuários têm algum conhecimento técnico.

Cesar Gimenes

Última modificação