DevOps & CI/CD

Guia Completo de Ansible Avançado: Roles, Templates Jinja2 e Ansible Vault

22 min de leitura

Guia Completo de Ansible Avançado: Roles, Templates Jinja2 e Ansible Vault

Entendendo Roles: A Estrutura Profissional do Ansible Uma role no Ansible é um padrão de organização que encapsula lógica de configuração de forma reutilizável e modular. Diferentemente de playbooks lineares, roles oferecem uma estrutura de diretórios padronizada que facilita a manutenção, o versionamento e o compartilhamento de código entre projetos. Quando você trabalha em ambientes corporativos, a diferença entre um playbook monolítico e uma estrutura baseada em roles é a diferença entre caos e profissionalismo. Uma role segue convenções de diretórios. Ansible procura automaticamente por arquivos em locais específicos: para tarefas, para notificações, para arquivos Jinja2, para variáveis privadas e para valores padrão. Você também encontrará para arquivos estáticos, para dependências e para validação. Criando sua primeira role Para começar, use o comando . Isso gera a estrutura completa automaticamente. Vamos criar uma role para instalar e configurar Nginx: Dentro de , adicione: Em , defina valores padrão: Em , adicione variáveis que sobrescrevem defaults: Em , defina ações acionadas

<h2>Entendendo Roles: A Estrutura Profissional do Ansible</h2>

<p>Uma role no Ansible é um padrão de organização que encapsula lógica de configuração de forma reutilizável e modular. Diferentemente de playbooks lineares, roles oferecem uma estrutura de diretórios padronizada que facilita a manutenção, o versionamento e o compartilhamento de código entre projetos. Quando você trabalha em ambientes corporativos, a diferença entre um playbook monolítico e uma estrutura baseada em roles é a diferença entre caos e profissionalismo.</p>

<p>Uma role segue convenções de diretórios. Ansible procura automaticamente por arquivos em locais específicos: <code>tasks/</code> para tarefas, <code>handlers/</code> para notificações, <code>templates/</code> para arquivos Jinja2, <code>vars/</code> para variáveis privadas e <code>defaults/</code> para valores padrão. Você também encontrará <code>files/</code> para arquivos estáticos, <code>meta/</code> para dependências e <code>tests/</code> para validação.</p>

<pre><code>minha_aplicacao/

├── defaults/

│ └── main.yml

├── files/

│ └── aplicacao.conf

├── handlers/

│ └── main.yml

├── meta/

│ └── main.yml

├── tasks/

│ └── main.yml

├── templates/

│ └── nginx.conf.j2

├── tests/

│ ├── inventory

│ └── test.yml

└── vars/

└── main.yml</code></pre>

<h3>Criando sua primeira role</h3>

<p>Para começar, use o comando <code>ansible-galaxy init nome_da_role</code>. Isso gera a estrutura completa automaticamente. Vamos criar uma role para instalar e configurar Nginx:</p>

<pre><code class="language-bash">ansible-galaxy init webserver</code></pre>

<p>Dentro de <code>webserver/tasks/main.yml</code>, adicione:</p>

<pre><code class="language-yaml">---

  • name: Instalar Nginx

apt:

name: nginx

state: present

update_cache: yes

when: ansible_os_family == &quot;Debian&quot;

  • name: Ativar Nginx

systemd:

name: nginx

enabled: yes

state: started

  • name: Copiar configuração Nginx

template:

src: nginx.conf.j2

dest: /etc/nginx/sites-available/default

backup: yes

notify: restart nginx

  • name: Validar sintaxe Nginx

command: nginx -t

changed_when: false</code></pre>

<p>Em <code>webserver/defaults/main.yml</code>, defina valores padrão:</p>

<pre><code class="language-yaml">---

nginx_port: 80

nginx_user: www-data

nginx_worker_processes: auto

nginx_keepalive_timeout: 65

max_body_size: 20m</code></pre>

<p>Em <code>webserver/vars/main.yml</code>, adicione variáveis que sobrescrevem defaults:</p>

<pre><code class="language-yaml">---

nginx_conf_path: /etc/nginx/sites-available/default

nginx_service_name: nginx</code></pre>

<p>Em <code>webserver/handlers/main.yml</code>, defina ações acionadas por notificações:</p>

<pre><code class="language-yaml">---

  • name: restart nginx

systemd:

name: nginx

state: restarted

  • name: reload nginx

systemd:

name: nginx

state: reloaded</code></pre>

<h3>Usando roles em playbooks</h3>

<p>Para usar a role, crie um playbook <code>site.yml</code>:</p>

<pre><code class="language-yaml">---

  • hosts: webservers

become: yes

roles:

  • webserver</code></pre>

<p>Ou com variáveis inline:</p>

<pre><code class="language-yaml">---

  • hosts: webservers

become: yes

roles:

  • role: webserver

vars:

nginx_port: 8080

max_body_size: 50m</code></pre>

<p>Você também pode passar argumentos condicionalmente:</p>

<pre><code class="language-yaml">---

  • hosts: all

roles:

  • role: webserver

when: inventory_hostname in groups[&#039;webservers&#039;]

tags:

  • web
  • setup</code></pre>

<h2>Templates Jinja2: Dinamismo em Configurações</h2>

<p>Jinja2 é um motor de templates poderoso que permite gerar arquivos de configuração dinamicamente usando variáveis do Ansible. Em vez de manter múltiplas versões estáticas de um arquivo de configuração, você cria um template que se adapta ao contexto de cada host. Isso reduz drasticamente duplicação e erros humanos em ambientes heterogêneos.</p>

<p>A sintaxe Jinja2 usa <code>{{ variavel }}</code> para inserção de variáveis, <code>{% if condicao %}</code> para lógica condicional e <code>{% for item in lista %}</code> para loops. Dentro de um template, você tem acesso a todas as variáveis do Ansible (facts, vars, defaults) e pode aplicar filtros para transformar dados.</p>

<h3>Estrutura básica de templates</h3>

<p>Crie <code>webserver/templates/nginx.conf.j2</code>:</p>

<pre><code class="language-nginx">user {{ nginx_user }};

worker_processes {{ nginx_worker_processes }};

pid /run/nginx.pid;

events {

worker_connections 768;

}

http {

sendfile on;

tcp_nopush on;

tcp_nodelay on;

keepalive_timeout {{ nginx_keepalive_timeout }};

types_hash_max_size 2048;

include /etc/nginx/mime.types;

default_type application/octet-stream;

access_log /var/log/nginx/access.log;

error_log /var/log/nginx/error.log;

gzip on;

gzip_vary on;

gzip_proxied any;

gzip_comp_level 6;

gzip_types text/plain text/css text/xml text/javascript

application/json application/javascript application/xml+rss;

include /etc/nginx/sites-enabled/*;

}</code></pre>

<h3>Lógica condicional em templates</h3>

<p>Para adicionar blocos opcionais baseado em variáveis, edite o template:</p>

<pre><code class="language-nginx">http {

{% if enable_ssl %}

ssl_protocols TLSv1.2 TLSv1.3;

ssl_ciphers HIGH:!aNULL:!MD5;

ssl_prefer_server_ciphers on;

{% endif %}

{% if enable_compression %}

gzip on;

gzip_types text/plain text/css application/json application/javascript;

{% endif %}

{% if custom_headers %}

add_header X-Custom-Header &quot;{{ custom_header_value }}&quot;;

{% endif %}

}</code></pre>

<p>Em seu <code>defaults/main.yml</code>:</p>

<pre><code class="language-yaml">enable_ssl: false

enable_compression: true

custom_headers: false</code></pre>

<h3>Loops em templates</h3>

<p>Para gerar múltiplos blocos de configuração, use loops. Crie <code>webserver/templates/vhosts.conf.j2</code>:</p>

<pre><code class="language-nginx">{% for vhost in nginx_vhosts %}

server {

listen {{ vhost.port | default(80) }};

server_name {{ vhost.server_name }};

root {{ vhost.root | default(&#039;/var/www/html&#039;) }}; index {{ vhost.index | default(&#039;index.html&#039;) }};

{% if vhost.ssl_enabled | default(false) %}

listen 443 ssl;

ssl_certificate {{ vhost.ssl_cert }};

ssl_certificate_key {{ vhost.ssl_key }};

{% endif %}

location / {

try_files $uri $uri/ =404;

}

{% if vhost.proxy_pass %}

location /api {

proxy_pass {{ vhost.proxy_pass }};

proxy_set_header Host $host;

proxy_set_header X-Real-IP $remote_addr;

}

{% endif %}

}

{% endfor %}</code></pre>

<p>Defina em <code>vars/main.yml</code>:</p>

<pre><code class="language-yaml">nginx_vhosts:

  • server_name: &quot;exemplo.com&quot;

port: 80

root: &quot;/var/www/exemplo&quot;

proxy_pass: &quot;http://localhost:3000&quot;

  • server_name: &quot;api.exemplo.com&quot;

port: 80

root: &quot;/var/www/api&quot;

ssl_enabled: true

ssl_cert: &quot;/etc/ssl/certs/api.crt&quot;

ssl_key: &quot;/etc/ssl/private/api.key&quot;</code></pre>

<h3>Filtros Jinja2 essenciais</h3>

<p>Jinja2 oferece filtros que transformam dados. Alguns dos mais úteis no contexto Ansible:</p>

<pre><code class="language-jinja2">{{ variavel | default(&#039;valor_padrao&#039;) }} {{ lista | join(&#039;, &#039;) }} {{ string | upper }} {{ string | lower }} {{ numero | string }} {{ dados | to_nice_json }} {{ caminho | basename }} {{ string | regex_replace(&#039;^(.)$&#039;, &#039;prefixo_\\1&#039;) }} {{ lista | select(&#039;match&#039;, &#039;padrao.&#039;) | list }}</code></pre>

<p>Um exemplo prático no template:</p>

<pre><code class="language-nginx"># Comentário gerado em {{ ansible_date_time.iso8601 }}

Host: {{ inventory_hostname }}

OS: {{ ansible_distribution }} {{ ansible_distribution_version }}

error_log /var/log/nginx/error.log {{ log_level | default(&#039;warn&#039;) }};

access_log /var/log/nginx/access.log {% if access_log_format %}{{ access_log_format }}{% else %}combined{% endif %};</code></pre>

<h2>Ansible Vault: Segurança para Dados Sensíveis</h2>

<p>Ansible Vault é um sistema de criptografia que protege arquivos contendo informações sensíveis como senhas, chaves privadas e tokens de API. Toda organização que trabalha com configuração como código deve usar Vault; armazenar senhas em texto plano em repositórios Git é uma vulnerabilidade grave. O Vault usa criptografia AES-256 e requer uma senha para descriptografar arquivos durante a execução do playbook.</p>

<p>A estratégia é simples: você cria um arquivo Vault contendo valores sensíveis, referencia esses valores em seus playbooks e templates normalmente, e o Ansible descriptografa automaticamente quando necessário. Isso mantém o fluxo de trabalho transparente enquanto protege dados em repouso.</p>

<h3>Criando e editando arquivos Vault</h3>

<p>Para criar um novo arquivo criptografado:</p>

<pre><code class="language-bash">ansible-vault create credenciais.yml</code></pre>

<p>Você será solicitado a definir uma senha. Então um editor abre para você adicionar conteúdo:</p>

<pre><code class="language-yaml">---

db_password: &quot;senhaForte123!@#&quot;

api_key: &quot;sk-proj-1a2b3c4d5e6f7g8h9i0j&quot;

jwt_secret: &quot;seu-jwt-secret-muito-longo-aqui&quot;

backup_passphrase: &quot;backup@2024&quot;</code></pre>

<p>Para editar depois:</p>

<pre><code class="language-bash">ansible-vault edit credenciais.yml</code></pre>

<p>Para visualizar sem editar:</p>

<pre><code class="language-bash">ansible-vault view credenciais.yml</code></pre>

<p>Para mudar a senha:</p>

<pre><code class="language-bash">ansible-vault rekey credenciais.yml</code></pre>

<h3>Integrando Vault em playbooks</h3>

<p>Inclua o arquivo Vault em seu playbook referenciando-o normalmente:</p>

<pre><code class="language-yaml">---

  • hosts: database_servers

become: yes

vars_files:

  • credenciais.yml

tasks:

  • name: Configurar PostgreSQL

postgresql_query:

db: postgres

query: &quot;ALTER USER postgres WITH PASSWORD &#039;{{ db_password }}&#039;;&quot;

environment:

PGPASSWORD: &quot;{{ db_password }}&quot;

  • name: Gerar arquivo de configuração da aplicação

template:

src: app_config.yml.j2

dest: /etc/app/config.yml

mode: &#039;0640&#039;

owner: app_user

group: app_group

  • name: Registrar API key no serviço

uri:

url: &quot;https://api.exemplo.com/register&quot;

method: POST

body_format: json

body:

api_key: &quot;{{ api_key }}&quot;

environment: &quot;production&quot;</code></pre>

<p>Em <code>templates/app_config.yml.j2</code>:</p>

<pre><code class="language-yaml"># Configuração gerada automaticamente - não editar manualmente

database:

host: {{ db_host }}

port: {{ db_port }}

username: {{ db_user }}

password: {{ db_password }}

name: {{ db_name }}

api:

endpoint: {{ api_endpoint }}

key: {{ api_key }}

timeout: 30

backup:

enabled: true

passphrase: {{ backup_passphrase }}

retention_days: 30</code></pre>

<h3>Executando playbooks com Vault</h3>

<p>Para executar um playbook que use arquivos Vault, use a flag <code>--ask-vault-pass</code>:</p>

<pre><code class="language-bash">ansible-playbook site.yml --ask-vault-pass</code></pre>

<p>O Ansible solicitará a senha do Vault. Alternativamente, armazene a senha em um arquivo seguro:</p>

<pre><code class="language-bash"># Crie um arquivo com a senha (tenha cuidado com permissões)

echo &quot;minha-senha-vault&quot; &gt; ~/.vault_password

Configure permissões restritivas

chmod 600 ~/.vault_password

Execute o playbook

ansible-playbook site.yml --vault-password-file ~/.vault_password</code></pre>

<p>Ou configure no arquivo <code>ansible.cfg</code>:</p>

<pre><code class="language-ini">[defaults]

vault_password_file = ~/.vault_password</code></pre>

<h3>Criptografando valores individuais</h3>

<p>Você não precisa criptografar arquivos inteiros. Use <code>ansible-vault encrypt_string</code> para criptografar um valor específico:</p>

<pre><code class="language-bash">ansible-vault encrypt_string &#039;senhaForte123!@#&#039; --name &#039;db_password&#039;</code></pre>

<p>Saída:</p>

<pre><code class="language-yaml">db_password: !vault |

$ANSIBLE_VAULT;1.1;AES256

32643062306465613666336661666565356165303063666165653132613734623634303834306537

3237353461303061623162343739336666653535666234650a343438333436643631663539383639

31313665633439643363396164313364316437353235383164633761616465616266613264633736

3231656139386234300a346334396632393134626634643461363632616238346264653064383862

6266</code></pre>

<p>Copie e cole esse bloco em seus arquivos YAML:</p>

<pre><code class="language-yaml">---

  • hosts: all

vars:

db_password: !vault |

$ANSIBLE_VAULT;1.1;AES256

32643062306465613666336661666565356165303063666165653132613734623634303834306537

3237353461303061623162343739336666653535666234650a343438333436643631663539383639

31313665633439643363396164313364316437353235383164633761616465616266613264633736

3231656139386234300a346334396632393134626634643461363632616238346264653064383862

6266

tasks:

  • name: Usar senha descriptografada

debug:

msg: &quot;Senha é {{ db_password }}&quot;</code></pre>

<h3>Gerenciamento de segurança com Vault</h3>

<p>Para manter segurança em equipes, nunca commite o arquivo <code>.vault_password</code> no Git. Use um <code>.gitignore</code>:</p>

<pre><code>.vault_password

*.vault

*.key</code></pre>

<p>Para compartilhar a senha com colegas de trabalho, use um gerenciador de senhas corporativo ou passe de forma segura fora do repositório. Em ambientes de CI/CD, injete a senha como variável de ambiente:</p>

<pre><code class="language-bash">export ANSIBLE_VAULT_PASSWORD_FILE=/run/secrets/vault_password

ansible-playbook site.yml</code></pre>

<p>Em GitHub Actions:</p>

<pre><code class="language-yaml">- name: Run Ansible playbook

env:

ANSIBLE_VAULT_PASSWORD: ${{ secrets.ANSIBLE_VAULT_PASSWORD }}

run: |

echo &quot;$ANSIBLE_VAULT_PASSWORD&quot; &gt; /tmp/vault_pass

chmod 600 /tmp/vault_pass

ansible-playbook site.yml --vault-password-file /tmp/vault_pass

rm /tmp/vault_pass</code></pre>

<h2>Integrando Roles, Templates e Vault em um Projeto Real</h2>

<p>A verdadeira potência emerge quando combinamos esses três componentes. Vamos construir um cenário realista: implantar uma aplicação Node.js com Nginx como proxy reverso, usando uma role bem estruturada, templates dinâmicos e dados sensíveis protegidos.</p>

<p>Estrutura do projeto:</p>

<pre><code>ansible-projeto/

├── ansible.cfg

├── inventario.yml

├── site.yml

├── credenciais.yml (criptografado com Vault)

├── roles/

│ ├── nodejs-app/

│ │ ├── defaults/main.yml

│ │ ├── tasks/main.yml

│ │ ├── templates/

│ │ │ ├── app.env.j2

│ │ │ └── systemd-app.service.j2

│ │ ├── handlers/main.yml

│ │ └── vars/main.yml

│ └── nginx-proxy/

│ ├── defaults/main.yml

│ ├── tasks/main.yml

│ ├── templates/

│ │ └── nginx-app.conf.j2

│ ├── handlers/main.yml

│ └── vars/main.yml

└── group_vars/

└── app_servers.yml</code></pre>

<p>Arquivo <code>ansible.cfg</code>:</p>

<pre><code class="language-ini">[defaults]

inventory = inventario.yml

vault_password_file = ~/.vault_password

roles_path = ./roles

host_key_checking = False</code></pre>

<p>Arquivo <code>inventario.yml</code>:</p>

<pre><code class="language-yaml">---

all:

children:

app_servers:

hosts:

app01.exemplo.com:

ansible_user: deploy

app02.exemplo.com:

ansible_user: deploy</code></pre>

<p>Arquivo <code>credenciais.yml</code> (criptografado):</p>

<pre><code class="language-yaml">---

db_host: postgres.interno.com

db_user: app_user

db_password: !vault |

$ANSIBLE_VAULT;1.1;AES256

...conteudo_criptografado...

app_secret_key: !vault |

$ANSIBLE_VAULT;1.1;AES256

...conteudo_criptografado...</code></pre>

<p>Arquivo <code>group_vars/app_servers.yml</code>:</p>

<pre><code class="language-yaml">---

app_name: minha-app

app_user: app

app_group: app

app_port: 3000

app_version: 1.2.3

nodejs_version: 18

nginx_proxy_port: 80</code></pre>

<p>Arquivo <code>site.yml</code>:</p>

<pre><code class="language-yaml">---

  • hosts: app_servers

become: yes

vars_files:

  • credenciais.yml

pre_tasks:

  • name: Atualizar cache do apt

apt:

update_cache: yes

cache_valid_time: 3600

when: ansible_os_family == &quot;Debian&quot;

roles:

  • nodejs-app
  • nginx-proxy

post_tasks:

  • name: Validar status da aplicação

uri:

url: &quot;http://localhost/health&quot;

method: GET

status_code: 200

register: health_check

retries: 3

delay: 5

until: health_check is success</code></pre>

<p>Role <code>nodejs-app</code> - <code>roles/nodejs-app/tasks/main.yml</code>:</p>

<pre><code class="language-yaml">---

  • name: Instalar Node.js

block:

  • name: Adicionar NodeSource repository

shell: curl -fsSL https://deb.nodesource.com/setup_{{ nodejs_version }}.x | sudo -E bash -

args:

warn: false

  • name: Instalar Node.js

apt:

name: nodejs

state: present

  • name: Criar usuário da aplicação

user:

name: &quot;{{ app_user }}&quot;

shell: /bin/bash

home: &quot;/home/{{ app_user }}&quot;

createhome: yes

state: present

  • name: Clonar repositório da aplicação

git:

repo: &quot;{{ app_repo_url }}&quot;

dest: &quot;/var/www/{{ app_name }}&quot;

version: &quot;{{ app_version }}&quot;

update: yes

register: app_clone

become_user: &quot;{{ app_user }}&quot;

  • name: Instalar dependências Node.js

npm:

path: &quot;/var/www/{{ app_name }}&quot;

state: present

when: app_clone is changed

  • name: Gerar arquivo .env

template:

src: app.env.j2

dest: &quot;/var/www/{{ app_name }}/.env&quot;

owner: &quot;{{ app_user }}&quot;

group: &quot;{{ app_group }}&quot;

mode: &#039;0640&#039;

notify: restart app

  • name: Criar serviço systemd

template:

src: systemd-app.service.j2

dest: &quot;/etc/systemd/system/{{ app_name }}.service&quot;

owner: root

group: root

mode: &#039;0644&#039;

notify: restart app

  • name: Habilitar e iniciar serviço

systemd:

name: &quot;{{ app_name }}&quot;

enabled: yes

state: started

daemon_reload: yes</code></pre>

<p>Template <code>roles/nodejs-app/templates/app.env.j2</code>:</p>

<pre><code class="language-env"># Arquivo de configuração gerado automaticamente

Última atualização: {{ ansible_date_time.iso8601 }}

NODE_ENV=production

APP_PORT={{ app_port }}

APP_NAME={{ app_name }}

APP_VERSION={{ app_version }}

Database

DB_HOST={{ db_host }}

DB_USER={{ db_user }}

DB_PASSWORD={{ db_password }}

DB_NAME={{ app_name }}_prod

Security

SECRET_KEY={{ app_secret_key }}

SESSION_SECRET={{ app_session_secret | default(&#039;change-me&#039;) }}

Features

ENABLE_CACHE={{ enable_cache | default(&#039;true&#039;) }} ENABLE_LOGGING={{ enable_logging | default(&#039;true&#039;) }} LOG_LEVEL={{ log_level | default(&#039;info&#039;) }}</code></pre>

<p>Template <code>roles/nodejs-app/templates/systemd-app.service.j2</code>:</p>

<pre><code class="language-ini">[Unit]

Description={{ app_name }} Node.js Application

After=network.target

[Service]

Type=simple

User={{ app_user }}

Group={{ app_group }}

WorkingDirectory=/var/www/{{ app_name }}

ExecStart=/usr/bin/node server.js

Restart=on-failure

RestartSec=10

StandardOutput=journal

StandardError=journal

Environment=&quot;NODE_ENV=production&quot;

Environment=&quot;PORT={{ app_port }}&quot;

[Install]

WantedBy=multi-user.target</code></pre>

<p>Role <code>nginx-proxy</code> - <code>roles/nginx-proxy/tasks/main.yml</code>:</p>

<pre><code class="language-yaml">---

  • name: Instalar Nginx

apt:

name: nginx

state: present

  • name: Gerar configuração Nginx

template:

src: nginx-app.conf.j2

dest: &quot;/etc/nginx/sites-available/{{ app_name }}&quot;

owner: root

group: root

mode: &#039;0644&#039;

notify: test and reload nginx

  • name: Ativar site Nginx

file:

src: &quot;/etc/nginx/sites-available/{{ app_name }}&quot;

dest: &quot;/etc/nginx/sites-enabled/{{ app_name }}&quot;

state: link

notify: test and reload nginx

  • name: Habilitar e iniciar Nginx

systemd:

name: nginx

enabled: yes

state: started</code></pre>

<p>Template <code>roles/nginx-proxy/templates/nginx-app.conf.j2</code>:</p>

<pre><code class="language-nginx"># Configuração Nginx para {{ app_name }}

Gerada em {{ ansible_date_time.iso8601 }} em {{ inventory_hostname }}

upstream {{ app_name }}_backend {

server 127.0.0.1:{{ app_port }};

keepalive 32;

}

server {

listen {{ nginx_proxy_port }};

server_name {{ server_names | join(&#039; &#039;) }};

access_log /var/log/nginx/{{ app_name }}_access.log combined;

error_log /var/log/nginx/{{ app_name }}_error.log warn;

client_max_body_size 50m;

Health check endpoint

location /health {

access_log off;

proxy_pass http://{{ app_name }}_backend;

proxy_http_version 1.1;

proxy_set_header Connection &quot;&quot;;

}

API e aplicação

location / {

proxy_pass http://{{ app_name }}_backend;

proxy_http_version 1.1;

proxy_set_header Host $host;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_set_header X-Forwarded-Proto $scheme;

proxy_set_header Connection &quot;&quot;;

proxy_connect_timeout 60s;

proxy_send_timeout 60s;

proxy_read_timeout 60s;

}

{% if enable_gzip | default(true) %}

gzip on;

gzip_types text/plain text/css text/javascript application/json application/javascript;

gzip_min_length 1000;

{% endif %}

}</code></pre>

<p>Para executar:</p>

<pre><code class="language-bash"># Primeira execução - solicita senha do Vault

ansible-playbook site.yml --ask-vault-pass

Com arquivo de senha (mais seguro em CI/CD)

ansible-playbook site.yml --vault-password-file ~/.vault_password</code></pre>

<h2>Conclusão</h2>

<p>Dominar Roles, Templates Jinja2 e Ansible Vault transforma você de um usuário básico de Ansible para um profissional capaz de implementar infraestrutura como código em escala corporativa. As três competências trabalham juntas: Roles organizam sua lógica em estruturas reutilizáveis; Templates Jinja2 tornam configurações dinâmicas e adaptáveis; Vault protege dados sensíveis mantendo o fluxo transparente. Esse tripé é a base para automação confiável, auditável e segura.</p>

<p>Na prática, sempre pense em reutilização: uma role bem escrita deve funcionar em múltiplos contextos através de variáveis. Use templates para tudo que varia entre ambientes—nunca commite arquivos de configuração estáticos quando um template pode substituí-lo. E nunca, em hipótese alguma, commite senhas em repositórios; o Vault existe justamente para isso e seu custo de implementação é praticamente zero.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html" target="_blank" rel="noopener noreferrer">Ansible Roles - Documentação Oficial</a></li>

<li><a href="https://jinja.palletsprojects.com/" target="_blank" rel="noopener noreferrer">Jinja2 Template Engine - Documentação</a></li>

<li><a href="https://docs.ansible.com/ansible/latest/user_guide/vault.html" target="_blank" rel="noopener noreferrer">Ansible Vault - Protecting Sensitive Data</a></li>

<li><a href="https://galaxy.ansible.com/" target="_blank" rel="noopener noreferrer">Ansible Galaxy - Community Roles</a></li>

<li><a href="https://www.oreilly.com/library/view/infrastructure-as-code/9781491924334/" target="_blank" rel="noopener noreferrer">DevOps and Infrastructure as Code - Book by Kief Morris</a></li>

</ul>

<p>&lt;!-- FIM --&gt;</p>

Comentários

Mais em DevOps & CI/CD

Compliance como Código: OPA, Conftest e Policy Enforcement em Kubernetes na Prática
Compliance como Código: OPA, Conftest e Policy Enforcement em Kubernetes na Prática

O Que é Compliance como Código Compliance como Código é um paradigma que tran...

Incident Management: Runbooks, Post-mortems e Cultura de Confiabilidade na Prática
Incident Management: Runbooks, Post-mortems e Cultura de Confiabilidade na Prática

Incident Management: Fundamentos e Importância Incident Management é a discip...

Como Usar Shell Scripting Avançado: Processos, Sinais, Trap e Scripts Robustos em Produção
Como Usar Shell Scripting Avançado: Processos, Sinais, Trap e Scripts Robustos em Produção

Entendendo Processos em Shell Um processo em Unix/Linux é uma instância de um...