17 min de leitura · Guia técnico
Automatizar deploys no Linux com Ansible significa usar Playbooks YAML para orquestrar, de forma repetível e auditável, todas as etapas de publicação de uma aplicação — do pull do repositório à reinicialização do serviço — sem intervenção manual. Para montar seu checklist completo, siga estes passos:
- Instalar o Ansible no nó de controle e configurar acesso SSH aos servidores de destino.
- Criar o arquivo de inventário com os hosts de produção e staging.
- Escrever o Playbook principal com as tarefas de deploy (pull, build, migrate, reload).
- Organizar tarefas em Roles reutilizáveis para separar responsabilidades.
- Testar com
--check --diffantes de aplicar em produção. - Configurar pipeline de rollback com symlinks versionados.
Pré-requisitos para automatizar deploys com Ansible no Linux
- Nó de controle: qualquer máquina Linux com Python 3.9+ e Ansible 2.16+ instalado (Ubuntu 24.04 LTS, Debian 12 ou Rocky Linux 9 funcionam bem).
- Servidores de destino: Python 3 instalado (pacote
python3); sem necessidade de agente Ansible. - Acesso SSH: chave pública do nó de controle adicionada ao
~/.ssh/authorized_keysdo usuário remoto (preferencialmente um usuário dedicado, não root). - Permissões sudo: o usuário remoto deve ter permissão de
sudosem senha para os comandos necessários (reiniciar serviços, por exemplo). - Git instalado nos servidores de destino para operações de pull do repositório.
- Conhecimento básico de YAML e familiaridade com a estrutura de diretórios do Ansible.
Como instalar e configurar o Ansible para deploys automatizados
A automação de deploys com Ansible começa pela instalação correta do nó de controle. No Ubuntu 24.04 LTS, o repositório oficial da Ansible garante a versão mais recente:
sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install -y ansible
ansible --version
ansible [core 2.16.x]
config file = /etc/ansible/ansible.cfg
python version = 3.12.x
jinja version = 3.1.x
No Rocky Linux 9 ou AlmaLinux 9, use o repositório EPEL:
sudo dnf install -y epel-release
sudo dnf install -y ansible
ansible --version
Após a instalação, configure o arquivo global /etc/ansible/ansible.cfg ou crie um local no diretório do projeto:
[defaults]
inventory = ./inventory/hosts.ini
remote_user = deploy
private_key_file = ~/.ssh/id_ed25519
host_key_checking = False
retry_files_enabled = False
[privilege_escalation]
become = True
become_method = sudo
become_user = root
Teste a conectividade com todos os hosts antes de qualquer deploy:
ansible all -m ping
web01 | SUCCESS => {
"changed": false,
"ping": "pong"
}
web02 | SUCCESS => {
"changed": false,
"ping": "pong"
}
Se você ainda está configurando o acesso SSH ao seu VPS, consulte o guia Acessando servidores VPS Linux da AviraHost para os primeiros passos de conexão.
Estrutura do inventário e organização de ambientes
O arquivo de inventário é o mapa de infraestrutura do Ansible — ele define quais servidores recebem cada conjunto de tarefas. Para deploys profissionais, separe os ambientes em grupos distintos:
[staging]
staging01 ansible_host=192.168.1.10
[production]
web01 ansible_host=203.0.113.10
web02 ansible_host=203.0.113.11
[production:vars]
app_env=production
app_dir=/var/www/minha-app
[email protected]:empresa/minha-app.git
app_branch=main
nginx_service=nginx
[staging:vars]
app_env=staging
app_dir=/var/www/minha-app-staging
app_branch=develop
Para inventários dinâmicos (quando os IPs mudam com frequência, como em ambientes cloud), o Ansible suporta scripts Python ou plugins nativos. Para a maioria dos cenários com VPS fixos, o inventário estático acima é suficiente e mais fácil de auditar.
Organize o projeto completo seguindo a estrutura recomendada pela Ansible Galaxy:
deploy-project/
├── ansible.cfg
├── inventory/
│ └── hosts.ini
├── group_vars/
│ ├── all.yml
│ ├── production.yml
│ └── staging.yml
├── roles/
│ ├── deploy/
│ │ ├── tasks/
│ │ │ └── main.yml
│ │ ├── handlers/
│ │ │ └── main.yml
│ │ └── templates/
│ │ └── app.conf.j2
│ └── rollback/
│ └── tasks/
│ └── main.yml
└── site.yml
Escrevendo o Playbook de deploy com Ansible
O Playbook de deploy é o coração da automação — ele orquestra cada etapa da publicação de forma idempotente, garantindo que rodar duas vezes produza o mesmo resultado que rodar uma vez. Crie o arquivo site.yml:
---
- name: Deploy da aplicação em produção
hosts: production
serial: 1
gather_facts: true
roles:
- deploy
Agora crie o arquivo de tarefas principal em roles/deploy/tasks/main.yml:
---
- name: Garantir que o diretório de releases existe
file:
path: "{{ app_dir }}/releases"
state: directory
owner: "{{ remote_user }}"
mode: "0755"
- name: Registrar timestamp do release
command: date +%Y%m%d%H%M%S
register: release_timestamp
changed_when: false
- name: Definir caminho do release atual
set_fact:
release_path: "{{ app_dir }}/releases/{{ release_timestamp.stdout }}"
- name: Clonar repositório na versão correta
git:
repo: "{{ app_repo }}"
dest: "{{ release_path }}"
version: "{{ app_branch }}"
depth: 1
accept_hostkey: true
- name: Instalar dependências (exemplo: Node.js)
command: npm ci --production
args:
chdir: "{{ release_path }}"
environment:
NODE_ENV: "{{ app_env }}"
- name: Copiar arquivo de configuração de ambiente
template:
src: app.conf.j2
dest: "{{ release_path }}/.env"
mode: "0640"
- name: Executar migrações de banco de dados
command: ./bin/migrate.sh
args:
chdir: "{{ release_path }}"
when: app_env == "production"
- name: Atualizar symlink current para o novo release
file:
src: "{{ release_path }}"
dest: "{{ app_dir }}/current"
state: link
- name: Manter apenas os 5 releases mais recentes
shell: |
ls -dt {{ app_dir }}/releases/*/ | tail -n +6 | xargs rm -rf
changed_when: false
- name: Reiniciar o serviço da aplicação
notify: restart app service
Crie o handler em roles/deploy/handlers/main.yml:
---
- name: restart app service
systemd:
name: minha-app
state: restarted
daemon_reload: true
Atenção: a tarefa de migração de banco de dados é potencialmente destrutiva. Sempre faça backup antes de executar o Playbook em produção. Consulte as Dicas de Otimização de Servidores Linux para boas práticas de manutenção antes de deploys críticos.
Configurando o Playbook de rollback com symlinks versionados
A estratégia de rollback com Ansible usa a estrutura de releases versionados criada no deploy — basta redirecionar o symlink current para a versão anterior sem necessidade de novo upload. Crie roles/rollback/tasks/main.yml:
---
- name: Listar releases disponíveis
find:
paths: "{{ app_dir }}/releases"
file_type: directory
register: available_releases
- name: Ordenar releases por data de modificação
set_fact:
sorted_releases: "{{ available_releases.files | sort(attribute='mtime', reverse=True) | map(attribute='path') | list }}"
- name: Verificar se existe release anterior
fail:
msg: "Não há release anterior disponível para rollback."
when: sorted_releases | length < 2
- name: Definir release anterior
set_fact:
previous_release: "{{ sorted_releases[1] }}"
- name: Redirecionar symlink para release anterior
file:
src: "{{ previous_release }}"
dest: "{{ app_dir }}/current"
state: link
- name: Reiniciar serviço após rollback
systemd:
name: minha-app
state: restarted
Para executar o rollback em emergência:
ansible-playbook -i inventory/hosts.ini rollback.yml --limit production
PLAY [Rollback da aplicação] ***********************************
TASK [rollback : Redirecionar symlink para release anterior] ***
changed: [web01]
changed: [web02]
PLAY RECAP *****************************************************
web01 : ok=5 changed=2 unreachable=0 failed=0
web02 : ok=5 changed=2 unreachable=0 failed=0
Testando Playbooks com dry-run antes de aplicar em produção
O modo de verificação do Ansible permite simular toda a execução sem alterar nenhum arquivo ou serviço no servidor remoto — essencial antes de qualquer deploy em produção. Use sempre as flags --check e --diff juntas:
ansible-playbook -i inventory/hosts.ini site.yml --check --diff --limit staging
TASK [deploy : Atualizar symlink current para o novo release] ***
--- before
+++ after
@@ -1,4 +1,4 @@
{
- "path": "/var/www/minha-app/current -> /var/www/minha-app/releases/20240315120000"
+ "path": "/var/www/minha-app/current -> /var/www/minha-app/releases/20240316093045"
}
PLAY RECAP *****************************************************
staging01 : ok=8 changed=3 unreachable=0 failed=0 skipped=0
Algumas tarefas que dependem de resultados anteriores (como o timestamp do release) podem reportar skipped no modo --check — isso é comportamento esperado. Valide sempre em staging antes de promover para produção.
Para verificar a sintaxe do Playbook sem executar nada:
ansible-playbook site.yml --syntax-check
playbook: site.yml
Para listar todas as tarefas que seriam executadas, sem rodar nenhuma:
ansible-playbook site.yml --list-tasks
Automatizando deploys em múltiplos VPS com controle de paralelismo
O Ansible executa tarefas em paralelo por padrão em todos os hosts do inventário — o que pode causar downtime total se todos os servidores reiniciarem ao mesmo tempo. A diretiva serial no Playbook controla o deploy gradual (rolling deploy):
---
- name: Deploy gradual em produção
hosts: production
serial: 1
max_fail_percentage: 0
roles:
- deploy
Com serial: 1, o Ansible processa um servidor por vez. Com serial: "50%", processa metade dos hosts simultaneamente. A diretiva max_fail_percentage: 0 interrompe o deploy imediatamente se qualquer host falhar, evitando que o problema se propague.
Para deploys com health check entre cada servidor:
- name: Verificar saúde da aplicação após deploy
uri:
url: "http://{{ ansible_host }}/health"
status_code: 200
timeout: 30
retries: 5
delay: 10
register: health_check
until: health_check.status == 200
Esse padrão garante que o próximo servidor só receba o deploy após o anterior estar respondendo corretamente — fundamental para ambientes de alta disponibilidade.
Problemas comuns e como resolver
Sintoma: erro "Python not found" ao executar o Playbook
Causa: o servidor de destino não tem Python 3 instalado ou o Ansible está procurando no caminho errado. Em distribuições minimalistas como Debian 12 slim, o Python pode não estar presente por padrão.
Solução: adicione a variável ansible_python_interpreter no inventário ou instale o Python manualmente antes do primeiro Playbook. No inventário: web01 ansible_host=x.x.x.x ansible_python_interpreter=/usr/bin/python3. Para instalar: ansible all -m raw -a "apt-get install -y python3" (o módulo raw não requer Python).
Sintoma: tarefa "git clone" falha com "Host key verification failed"
Causa: o servidor de destino nunca se conectou ao host Git (GitHub, GitLab) e a chave do host não está no known_hosts do usuário remoto.
Solução: adicione accept_hostkey: true no módulo git do Playbook (já incluído no exemplo acima) ou pré-popule o known_hosts com uma tarefa dedicada: ansible all -m known_hosts -a "name=github.com key={{ lookup('pipe', 'ssh-keyscan github.com') }}".
Sintoma: handler "restart app service" não é executado
Causa: handlers só são disparados ao final do Play, e apenas se a tarefa que os notifica reportar changed: true. Se a tarefa anterior não alterou nada (idempotência), o handler não é chamado.
Solução: force a notificação explícita com changed_when: true na tarefa de atualização do symlink, ou use meta: flush_handlers para executar handlers imediatamente após um ponto específico do Playbook.
Sintoma: deploy falha com "sudo: no tty present and no askpass program specified"
Causa: o usuário remoto requer senha para sudo, mas o Ansible não tem como fornecê-la de forma interativa.
Solução: configure o sudoers no servidor de destino para permitir sudo sem senha para o usuário de deploy: adicione a linha deploy ALL=(ALL) NOPASSWD: ALL no arquivo /etc/sudoers.d/deploy. Use visudo para editar com validação de sintaxe.
Sintoma: Playbook demora muito em ambientes com muitos hosts
Causa: o fator de fork padrão do Ansible é 5, o que limita o paralelismo em inventários grandes.
Solução: aumente o valor de forks no ansible.cfg: forks = 20. Ative também o pipelining para reduzir o número de conexões SSH por tarefa: pipelining = True na seção [ssh_connection].
Perguntas frequentes sobre Ansible para deploys no Linux
O Ansible precisa de agente instalado nos servidores remotos?
Não. O Ansible opera sem agente (agentless), usando apenas SSH e Python no servidor remoto. Basta que o servidor de destino tenha Python 3 instalado e que a chave SSH do nó de controle esteja autorizada no arquivo authorized_keys do usuário remoto. Essa arquitetura simplifica enormemente a gestão de infraestrutura, pois não há processos adicionais rodando nos servidores de destino.
Qual a diferença entre um Playbook e um Role no Ansible?
Um Playbook é um arquivo YAML que descreve uma sequência de tarefas a executar em hosts específicos — é o ponto de entrada da automação. Um Role é uma estrutura de diretórios que organiza tarefas, variáveis, templates e handlers reutilizáveis, permitindo compartilhar e versionar configurações entre projetos diferentes. Pense no Playbook como o roteiro e no Role como um módulo reutilizável que o roteiro chama.
Como testar um Playbook Ansible sem aplicar mudanças reais no servidor?
Use o modo dry-run com a flag --check ao executar o comando ansible-playbook. Combine com --diff para visualizar exatamente quais linhas de arquivos seriam alteradas. Nenhuma mudança é aplicada ao servidor durante essa execução — é a forma mais segura de validar um Playbook antes de promovê-lo para produção.
É possível usar Ansible para fazer rollback de um deploy?
Sim. A prática mais comum é manter versões anteriores em diretórios numerados no servidor e usar um symlink apontando para a versão ativa. O Playbook de rollback simplesmente redireciona o symlink para a versão anterior e reinicia o serviço, sem necessidade de novo upload de arquivos. Essa abordagem torna o rollback quase instantâneo, independentemente do tamanho da aplicação.
Ansible funciona bem para gerenciar múltiplos VPS simultaneamente?
Sim. O Ansible executa tarefas em paralelo em múltiplos hosts definidos no arquivo de inventário. É possível controlar o grau de paralelismo com a diretiva serial no Playbook, útil para deploys graduais que evitam downtime total em ambientes com vários servidores. Aumentar o valor de forks no ansible.cfg também melhora a performance em inventários grandes.
Conclusão
- Comece pelo inventário e conectividade SSH: valide com
ansible all -m pingantes de escrever qualquer Playbook — problemas de acesso são a causa número um de falhas em deploys automatizados. - Adote a estrutura de Roles desde o início: mesmo para projetos pequenos, separar tarefas em Roles facilita a manutenção, o reuso e a colaboração em equipe à medida que a infraestrutura cresce.
- Nunca pule o dry-run em produção: execute sempre
--check --diffem staging antes de aplicar em produção, e mantenha pelo menos 5 releases versionados para garantir rollback rápido em caso de falha.
Leia também
- Checklist Completo para Configurar e Testar o Firewall UFW em VPS Linux e Servidores Dedicados
- Checklist de Segurança para Servidor Linux em Produção 2026
- Checklist para Otimização de VPS Linux: 15 Ajustes Essenciais
Precisa de ajuda com automação de deploys no seu servidor?
Ter uma infraestrutura Linux estável e bem configurada é o primeiro passo para que o Ansible funcione de forma confiável. Os planos de VPS da AviraHost oferecem acesso root completo, suporte a chaves SSH e Python 3 pré-instalado, prontos para receber seus Playbooks.