DEV Community

Cover image for Adicionando Headers no Nginx com Ansible
Leonan Viana
Leonan Viana

Posted on • Edited on

Adicionando Headers no Nginx com Ansible

Como automatizar a inserção de security headers no Nginx usando Ansible — backup, remoção de duplicatas, incremento via AWK e restart em múltiplos hosts de uma vez.

Num projeto recente eu precisava adicionar security headers no Nginx de vários hosts ao mesmo tempo. Fazer isso na mão, host por host, estava fora de questão — qualquer mudança futura viraria uma dor de cabeça. Resolvi automatizar com Ansible, e foi mais simples do que esperava.

O repositório tá disponível no GitHub caso queira já ir direto ao código.

add-headers-nginx

🇧🇷 Português | 🇺🇸 English

Nginx Ansible Linux Security


Português

Playbooks Ansible para adição e remoção de security headers no Nginx de forma automatizada e idempotente.

Por que security headers?

Security headers protegem aplicações web contra ataques como XSS, clickjacking e MIME sniffing. São exigidos em auditorias de segurança e compliance (OWASP, PCI-DSS).

Estrutura

add-headers-nginx/
├── nginx.conf                      # Exemplo de configuração Nginx
└── playbooks/
    ├── headers_nginx.txt           # Headers a serem inseridos
    ├── add_headers_nginx.yml       # Playbook para adicionar headers
    └── remove_headers_nginx.yml    # Playbook para remover headers

Pré-requisitos

  • Ansible instalado
  • Acesso sudo ao host alvo
  • Nginx instalado

Como usar

1. Configure os paths no playbook conforme seu ambiente:

vars:
  PATH_ADD_HEADERS_TXT: /seu/path/playbooks/headers_nginx.txt
  PATH_NGINX_CONF: /etc/nginx/nginx.conf
Enter fullscreen mode Exit fullscreen mode

2. Adicionar headers:

ansible-playbook playbooks/add_headers_nginx.yml
Enter fullscreen mode Exit fullscreen mode

3. Remover headers:

ansible-playbook playbooks/remove_headers_nginx.yml
Enter fullscreen mode Exit fullscreen mode

O que o playbook faz

  1. Faz backup do nginx.conf (duas cópias de segurança)
  2. Remove headers existentes para evitar duplicação
  3. Injeta os novos headers após a diretiva gzip_vary on
  4. Mantém…

O problema

A aplicação web precisava de uma lista de headers específicos para não quebrar em certas páginas:

  • Strict-Transport-Security
  • Content-Security-Policy
  • X-XSS-Protection
  • X-Frame-Options
  • X-Content-Type-Options
  • Referrer-Policy
  • Permissions-Policy

Com muitos hosts e a possibilidade de ajustes frequentes nos valores, qualquer processo manual ia escalar mal. Ansible resolve isso.


Etapa 1 — arquivo de headers

Crio um arquivo headers_nginx.txt com todas as diretivas add_header que quero inserir:

add_header Strict-Transport-Security 'max-age=63072000; includeSubDomains; preload';
add_header Content-Security-Policy "connect-src 'self' www.google-analytics.com ...";
add_header X-XSS-Protection "1; mode=block";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header Referrer-Policy "strict-origin";
add_header Permissions-Policy "geolocation=(self),midi=(self),...";
Enter fullscreen mode Exit fullscreen mode

Esse arquivo é a fonte da verdade. Quando precisar mudar um header, edito aqui e rodo a playbook de novo — sem tocar no nginx.conf manualmente.


Etapa 2 — a Playbook

A playbook tem seis jobs em sequência:

  1. Backup do nginx.conf — duas formas, pelo fetch e pelo cp
  2. Remoção das linhas add_header existentes — evita duplicidade
  3. Remoção das linhas add_header comentadas com #
  4. Limpeza de linhas em branco que ficam após a remoção
  5. Inserção dos novos headers via AWK
  6. Restart do Nginx
- name: Adicionar Headers no Nginx
  hosts: localhost
  become: yes
  become_method: sudo

  vars:
    PATH_ADD_HEADERS_TXT: /Users/leonanviana/Repos/add_headers_nginx/playbooks/headers_nginx.txt
    PATH_NGINX_CONF: /opt/homebrew/etc/nginx/nginx.conf

  tasks:

    - name: Fazer backup do nginx.conf via fetch
      fetch:
        src: /opt/homebrew/etc/nginx/nginx.conf
        dest: /var/tmp/
        flat: yes
      become: true

    - name: Fazer backup do nginx.conf via cp
      shell: cp "{{ PATH_NGINX_CONF }}" /var/tmp/default_nginx_bkp

    - name: Remover linhas com add_header
      lineinfile:
        path: "{{ PATH_NGINX_CONF }}"
        state: absent
        regexp: '^(\s*add_header\s.*;)$'

    - name: Remover linhas add_header comentadas com #
      lineinfile:
        path: "{{ PATH_NGINX_CONF }}"
        state: absent
        regexp: '^(\s*#add_header\s.*;)$'

    - name: Remover linhas em branco
      replace:
        path: "{{ PATH_NGINX_CONF }}"
        regexp: '^\s*$'
        replace: ''

    - name: Inserir headers via AWK
      shell: >
        awk '/gzip_vary on;/ {print; system("cat \"{{ PATH_ADD_HEADERS_TXT }}\""); next} 1'
        "{{ PATH_NGINX_CONF }}" > tmpfile && mv tmpfile "{{ PATH_NGINX_CONF }}"

    - name: Restart Nginx
      service:
        name: nginx
        state: restarted
Enter fullscreen mode Exit fullscreen mode

Como o AWK funciona aqui

O job de inserção merece atenção. Ele usa awk para localizar a string gzip_vary on; dentro do nginx.conf como ponto de ancoragem. Quando encontra essa linha, imprime ela e logo em seguida injeta todo o conteúdo do headers_nginx.txt. O resultado vai para um arquivo temporário, que substitui o original se tudo correr bem.

Você pode trocar gzip_vary on; por qualquer outra string que já exista no seu nginx.conf — o comportamento é o mesmo.


Fluxo de execução

Com tudo configurado, o fluxo fica assim:

  1. nginx.conf sem nenhum add_header
  2. Playbook roda — backup, limpeza, inserção, restart
  3. nginx.conf com todos os headers no lugar certo

Se precisar remover os headers depois, criei uma segunda playbook específica para isso — sem precisar editar o arquivo na mão.


Conclusão

Parece simples porque é. O ganho real aparece quando você tem dezenas de hosts: um único ansible-playbook propaga a mudança em todos ao mesmo tempo, com backup automático e sem risco de duplicidade.

O código tá no GitHub — pull requests são bem-vindos.

Top comments (0)