Automatize servidores Linux com Ansible: guia passo a passo
Configurar dez servidores um por um — atualizar pacotes, criar usuário, ajustar timezone, subir um serviço — é o tipo de tarefa que não escala e que erra por cansaço, não por incompetência. O Ansible resolve isso descrevendo o estado desejado em YAML e aplicando via SSH, sem agente instalado nos hosts gerenciados. Este guia sobe um control node do zero, gerencia dois ou mais servidores Linux e explica por que cada decisão de configuração evita o erro mais comum de quem começa: playbook que funciona uma vez e quebra na segunda execução.
Por que Ansible e não um script Bash
Um script Bash executa comandos. Um playbook Ansible descreve estado: “este pacote deve estar instalado”, não “rode apt install”. A diferença importa porque o Ansible primeiro verifica a condição atual do host e só age se houver divergência — rodar o mesmo playbook dez vezes produz o mesmo resultado da primeira. Essa propriedade chama-se idempotência, e é ela que permite reexecutar automação em produção sem medo de duplicar usuários, reiniciar serviços à toa ou sobrescrever configuração manual.
Outra vantagem prática: Ansible é agentless. Não existe daemon rodando nos servidores gerenciados — só SSH e Python, que já estão lá na imersa maioria das distribuições Linux. Isso reduz superfície de ataque e elimina o trabalho de manter agente atualizado em cada host, ao custo de exigir que a rede permita SSH do control node até os alvos.
Pré-requisitos
- Um control node Linux (pode ser sua própria máquina ou um servidor de gestão) com acesso SSH aos hosts que serão gerenciados.
- Autenticação por chave SSH já configurada nos hosts-alvo — Ansible reutiliza sua chave, não pede senha a cada tarefa.
- Python instalado nos hosts gerenciados (presente por padrão em quase toda distro Linux moderna).
- Usuário com sudo nos hosts-alvo, para tarefas que exigem privilégio.
Passo a passo
1. Instalar o Ansible no control node
Em Debian/Ubuntu, o pacote já vem no repositório universe:
sudo apt update sudo apt install ansible -y ansible --version
O ansible --version confirma a versão do ansible-core instalado e o caminho do arquivo de configuração ativo — útil para descartar dúvida quando dois usuários da mesma máquina têm comportamentos diferentes.
2. Garantir SSH sem senha para os hosts gerenciados
Sem isso, cada tarefa do playbook para e pede senha, o que inviabiliza automação real:
ssh-keygen -t ed25519 -C "ansible-control" ssh-copy-id usuario@10.0.0.11 ssh-copy-id usuario@10.0.0.12
Use uma chave dedicada para automação, separada da sua chave pessoal. Se o control node for comprometido, você revoga uma chave específica sem precisar trocar todos os seus acessos.
3. Criar o inventário
O inventário é a lista de hosts que o Ansible enxerga, organizada em grupos. Crie inventory.ini:
[webservers] web1 ansible_host=10.0.0.11 web2 ansible_host=10.0.0.12 [webservers:vars] ansible_user=usuario ansible_python_interpreter=/usr/bin/python3
Agrupar por função (webservers, dbservers, switches) é o que permite mais tarde aplicar um playbook só ao grupo certo, em vez de acertar o parque inteiro por engano.
4. Testar a conectividade
ansible webservers -i inventory.ini -m ping
Uma resposta pong de cada host confirma SSH, autenticação e Python funcionando antes de você escrever qualquer lógica de configuração — é o passo que a maioria pula e depois perde tempo depurando um playbook complexo por causa de um problema de conectividade simples.
5. Escrever o primeiro playbook
Crie configura-web.yml com tarefas comuns de baseline — atualizar pacotes, garantir um pacote instalado, ajustar timezone e criar um usuário de operação:
---
- name: Baseline de servidores web
hosts: webservers
become: true
tasks:
- name: Atualizar cache de pacotes
apt:
update_cache: true
cache_valid_time: 3600
- name: Garantir nginx instalado
apt:
name: nginx
state: present
- name: Ajustar timezone
timezone:
name: America/Sao_Paulo
- name: Criar usuário de operação
user:
name: opsuser
groups: sudo
shell: /bin/bash
state: present
- name: Garantir nginx habilitado e ativo
service:
name: nginx
state: started
enabled: true
Repare que cada tarefa declara state: present ou state: started — é essa sintaxe declarativa, e não um comando imperativo, que garante a idempotência. O módulo apt só instala se o pacote não estiver presente; o módulo user só cria se o usuário não existir.
6. Validar antes de aplicar
Antes de rodar de verdade, simule a execução com --check e veja o que mudaria:
ansible-playbook -i inventory.ini configura-web.yml --check --diff
O --diff mostra a diferença exata de cada arquivo ou configuração que seria alterado. Em produção, pular esse passo é a causa mais comum de playbook que “deveria só instalar um pacote” e acaba reiniciando um serviço em horário de pico.
7. Executar o playbook
ansible-playbook -i inventory.ini configura-web.yml
O output lista cada tarefa com ok (nada mudou), changed (aplicou algo) ou failed. Rode o mesmo comando de novo em seguida: se o playbook está correto, a segunda execução deve mostrar tudo como ok, sem nenhum changed — essa é a prova prática de idempotência.
8. Organizar em roles quando o playbook crescer
Um único arquivo YAML fica difícil de manter acima de umas 40-50 linhas ou quando você reutiliza a mesma lógica em vários projetos. Nesse ponto, migre para roles — estrutura de pastas padronizada (tasks/, handlers/, templates/, vars/) que separa responsabilidades e permite reaproveitar a role “nginx” ou “hardening-ssh” em qualquer playbook novo:
ansible-galaxy init roles/nginx
Erros comuns
“UNREACHABLE” no ansible ping — geralmente é chave SSH não propagada, IP errado no inventário ou firewall bloqueando a porta 22 entre control node e host. Teste ssh usuario@host manualmente antes de suspeitar do Ansible.
Tarefa pede senha sudo no meio da execução — falta become: true no playbook, ou o usuário SSH não tem NOPASSWD configurado no sudoers para automação não interativa.
Playbook aplica a mesma mudança toda vez — normalmente é módulo usado de forma imperativa (ex.: shell: apt install nginx) em vez do módulo declarativo correto (apt: name=nginx state=present). Módulos declarativos são o que garante idempotência; comandos shell brutos, não.
Perguntas frequentes
Ansible precisa de agente instalado no servidor gerenciado?
Não. A única exigência é SSH acessível e Python no host de destino — o Ansible se conecta, copia um módulo temporário, executa e remove. Não há daemon residente.
Dá para gerenciar Windows com Ansible?
Sim, mas via WinRM em vez de SSH, com módulos próprios (prefixo win_). O fluxo de inventário e playbook é o mesmo; a camada de transporte muda.
Qual a diferença entre Ansible e Terraform?
Terraform provisiona infraestrutura (criar uma VM, uma VLAN, um bucket); Ansible configura o que já existe (instalar pacotes, ajustar arquivos, gerenciar serviços). Em pipelines maduros, os dois convivem: Terraform sobe o servidor, Ansible o configura.
Posso versionar os playbooks em Git?
Deveria. Playbook é código de infraestrutura — versionar em Git dá histórico de mudança, permite revisão por pull request e possibilita reverter uma configuração problemática com git revert em vez de corrigir manualmente sob pressão.
Ansible substitui um sistema de monitoramento como Zabbix?
Não. Ansible aplica configuração; não monitora estado contínuo. Os dois são complementares — é comum usar Ansible para implantar e configurar o próprio agente Zabbix nos servidores.
Conclusão
O ganho real do Ansible não aparece na primeira execução — aparece na vigésima, quando reaplicar o mesmo playbook em um servidor novo leva o mesmo tempo que levou no primeiro, sem reler anotação nem lembrar de nenhum passo manual. Comece pequeno: um playbook de baseline para um grupo de servidores, sempre com --check --diff antes de aplicar em produção. Depois de dominar tasks e inventário, migrar para roles é o próximo passo natural para reaproveitar automação entre projetos.