Depois que a frota de workers CaptchaAI passa de um punhado de servidores, editar cada host na mão vira gargalo. A solução é dividir responsabilidades: o Terraform cria os servidores, o Ansible cuida do que roda dentro deles. Este guia traz um projeto Ansible completo para workers CaptchaAI — inventário por ambiente, role reutilizável, deploy, rolling update sem downtime, healthcheck e dimensionamento da frota.
Pré-requisitos antes de rodar os playbooks
Confirme estes pontos antes do primeiro ansible-playbook:
- Nó de controle com Ansible 2.14+ e Python 3 instalados.
- Acesso SSH por chave a todos os hosts da frota (
ssh-copy-id user@host). - Hosts Debian/Ubuntu com
aptdisponível — a role usaansible.builtin.apt; adapte paradnf/yumem distribuições RHEL. - Uma chave de API válida da CaptchaAI, pronta para ser criptografada com o Ansible Vault.
Estrutura do projeto Ansible
ansible/
├── inventory/
│ ├── production.yml
│ └── staging.yml
├── roles/
│ └── captcha-worker/
│ ├── tasks/
│ │ └── main.yml
│ ├── templates/
│ │ ├── captcha-worker.service.j2
│ │ └── config.yaml.j2
│ ├── handlers/
│ │ └── main.yml
│ └── defaults/
│ └── main.yml
├── playbooks/
│ ├── deploy.yml
│ ├── rolling-update.yml
│ └── health-check.yml
└── ansible.cfg
Inventário: produção e staging
Dois arquivos de inventário separam claramente staging e produção, cada um com sua própria concorrência (threads) e nível de log:
# inventory/production.yml
all:
children:
captcha_workers:
hosts:
worker-1:
ansible_host: 10.0.1.10
worker-2:
ansible_host: 10.0.1.11
worker-3:
ansible_host: 10.0.1.12
vars:
captchaai_concurrency: 20
captchaai_poll_interval: 3
captchaai_log_level: warning
worker_version: "1.3.0"
# inventory/staging.yml
all:
children:
captcha_workers:
hosts:
staging-worker-1:
ansible_host: 10.0.2.10
vars:
captchaai_concurrency: 5
captchaai_poll_interval: 5
captchaai_log_level: debug
worker_version: "1.4.0-rc1"
Dica de latência: na AWS, prefira hosts na região sa-east-1 (São Paulo) — o RTT até o endpoint da CaptchaAI cai bastante, o que importa quando captchaai_poll_interval está baixo.
Role: captcha-worker
Variáveis padrão
# roles/captcha-worker/defaults/main.yml
captchaai_concurrency: 10
captchaai_poll_interval: 5
captchaai_log_level: info
captchaai_timeout: 300
captchaai_retries: 3
worker_version: "latest"
worker_user: captcha
worker_dir: /opt/captcha-worker
worker_venv: /opt/captcha-worker/venv
Tarefas
# roles/captcha-worker/tasks/main.yml
---
- name: Create worker user
ansible.builtin.user:
name: "{{ worker_user }}"
system: true
shell: /usr/sbin/nologin
home: "{{ worker_dir }}"
- name: Create worker directory
ansible.builtin.file:
path: "{{ worker_dir }}"
state: directory
owner: "{{ worker_user }}"
mode: "0755"
- name: Install system dependencies
ansible.builtin.apt:
name:
- python3
- python3-venv
- python3-pip
state: present
update_cache: true
- name: Create Python virtual environment
ansible.builtin.command:
cmd: python3 -m venv {{ worker_venv }}
creates: "{{ worker_venv }}/bin/activate"
- name: Install Python dependencies
ansible.builtin.pip:
name:
- requests>=2.31.0
- pyyaml>=6.0
virtualenv: "{{ worker_venv }}"
- name: Deploy worker application
ansible.builtin.copy:
src: captcha_worker.py
dest: "{{ worker_dir }}/captcha_worker.py"
owner: "{{ worker_user }}"
mode: "0644"
notify: restart captcha-worker
- name: Deploy configuration
ansible.builtin.template:
src: config.yaml.j2
dest: "{{ worker_dir }}/config.yaml"
owner: "{{ worker_user }}"
mode: "0600"
notify: restart captcha-worker
- name: Deploy systemd service
ansible.builtin.template:
src: captcha-worker.service.j2
dest: /etc/systemd/system/captcha-worker.service
mode: "0644"
notify:
- reload systemd
- restart captcha-worker
- name: Enable and start service
ansible.builtin.systemd:
name: captcha-worker
enabled: true
state: started
Modelos
# roles/captcha-worker/templates/config.yaml.j2
# CaptchaAI Worker Configuration
# Managed by Ansible — do not edit manually
concurrency: {{ captchaai_concurrency }}
poll_interval: {{ captchaai_poll_interval }}
timeout: {{ captchaai_timeout }}
retries: {{ captchaai_retries }}
log_level: {{ captchaai_log_level }}
# roles/captcha-worker/templates/captcha-worker.service.j2
[Unit]
Description=CaptchaAI CAPTCHA Solving Worker
After=network.target
Wants=network-online.target
[Service]
Type=simple
User={{ worker_user }}
WorkingDirectory={{ worker_dir }}
ExecStart={{ worker_venv }}/bin/python {{ worker_dir }}/captcha_worker.py
Environment=CAPTCHAAI_API_KEY={{ captchaai_api_key }}
Restart=always
RestartSec=10
TimeoutStopSec=30
# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ReadWritePaths={{ worker_dir }}
[Install]
WantedBy=multi-user.target
Manipuladores
# roles/captcha-worker/handlers/main.yml
---
- name: reload systemd
ansible.builtin.systemd:
daemon_reload: true
- name: restart captcha-worker
ansible.builtin.systemd:
name: captcha-worker
state: restarted
Três playbooks cobrem o ciclo de vida do worker: implantar do zero, atualizar em produção sem downtime e checar a saúde da frota — cada um independente, rode só o que precisar.
Playbook de deploy: do zero ao worker rodando
O deploy.yml monta o worker em um host novo: pede a chave de API, aplica a role captcha-worker e confirma que o serviço está active.
# playbooks/deploy.yml
---
- name: Deploy CaptchaAI Workers
hosts: captcha_workers
become: true
vars_prompt:
- name: captchaai_api_key
prompt: "Enter CaptchaAI API key"
private: true
pre_tasks:
- name: Verify connectivity
ansible.builtin.ping:
roles:
- captcha-worker
post_tasks:
- name: Wait for worker to start
ansible.builtin.wait_for:
port: 8080
timeout: 30
ignore_errors: true
- name: Check worker status
ansible.builtin.systemd:
name: captcha-worker
register: worker_status
- name: Report status
ansible.builtin.debug:
msg: "Worker {{ inventory_hostname }}: {{ worker_status.status.ActiveState }}"
Atualização contínua (rolling update) sem downtime
O rolling-update.yml usa serial: 1: atualiza um host de cada vez, drena as tarefas antes de parar o serviço e só avança quando o healthcheck responde 200. Se um host falhar, max_fail_percentage: 0 interrompe o rollout na hora.
# playbooks/rolling-update.yml
---
- name: Rolling Update CaptchaAI Workers
hosts: captcha_workers
become: true
serial: 1 # Update one host at a time
max_fail_percentage: 0
tasks:
- name: Drain current tasks
ansible.builtin.command:
cmd: "{{ worker_venv }}/bin/python {{ worker_dir }}/drain.py"
timeout: 120
ignore_errors: true
- name: Stop worker
ansible.builtin.systemd:
name: captcha-worker
state: stopped
- name: Deploy new version
ansible.builtin.copy:
src: "captcha_worker.py"
dest: "{{ worker_dir }}/captcha_worker.py"
owner: "{{ worker_user }}"
mode: "0644"
- name: Update dependencies
ansible.builtin.pip:
requirements: "{{ worker_dir }}/requirements.txt"
virtualenv: "{{ worker_venv }}"
- name: Start worker
ansible.builtin.systemd:
name: captcha-worker
state: started
- name: Verify worker health
ansible.builtin.uri:
url: "http://localhost:8080/health"
return_content: true
register: health
until: health.status == 200
retries: 6
delay: 10
- name: Report update result
ansible.builtin.debug:
msg: "{{ inventory_hostname }} updated — {{ health.content }}"
Verificação de saúde da frota
O health-check.yml não altera nada, só lê: confere o serviço systemd em cada host e, uma vez (run_once: true), consulta o saldo via getbalance para confirmar que a chave configurada ainda é válida.
# playbooks/health-check.yml
---
- name: Check CaptchaAI Worker Health
hosts: captcha_workers
become: false
gather_facts: false
tasks:
- name: Check systemd service
ansible.builtin.systemd:
name: captcha-worker
register: service_status
become: true
- name: Check API connectivity
ansible.builtin.uri:
url: "https://ocr.captchaai.com/res.php?key={{ captchaai_api_key }}&action=getbalance&json=1"
return_content: true
register: api_check
delegate_to: localhost
run_once: true
- name: Summary
ansible.builtin.debug:
msg: |
Host: {{ inventory_hostname }}
Service: {{ service_status.status.ActiveState }}
API Balance: {{ (api_check.content | from_json).request }}
Segurança dos workers: Vault e hardening do systemd
A role já aplica várias camadas de segurança por padrão — vale entender cada uma antes de ir para produção. worker_user roda sem shell (/usr/sbin/nologin), config.yaml sai com mode: "0600", e NoNewPrivileges=true + ProtectSystem=strict no systemd limitam o que o processo toca no sistema de arquivos.
- Nunca commite a chave de API em texto puro no repositório do playbook.
- Prefira
ansible-vault encrypt_stringavars_promptem pipelines automatizados. - Rotacione a chave periodicamente pelo painel da CaptchaAI e atualize o Vault.
- Restrinja o acesso de leitura ao arquivo
.vault_pass, se usar um. - Audite o
journalctl -u captcha-workerapós cada rotação.
Nunca deixe a chave de API em texto puro em um playbook versionado — sempre via Ansible Vault ou injetada por uma variável de ambiente no momento do deploy.
Observabilidade da frota
O health-check.yml cobre o básico; numa frota maior, vale registrar estes sinais em um lugar central em vez de rodar o playbook manualmente:
| Sinal | Onde aparece | O que verificar |
|---|---|---|
| Estado do serviço | systemctl status captcha-worker / journalctl -u captcha-worker |
Reinícios frequentes indicam crash loop |
| Saldo da API | getbalance no res.php |
Saldo caindo rápido pode indicar concorrência maior que o esperado |
| Latência de polling | Logs do captcha_worker.py |
Tempo entre envio e resposta acima do normal para o tipo de CAPTCHA |
Com Prometheus já rodando, exportar essas métricas via
node_exportertextfile collector, alimentado pelo própriohealth-check.yml, é mais simples do que integrar um agente novo.
Dimensionando a frota: threads por plano CaptchaAI
A CaptchaAI cobra por thread simultânea, não por solve — cada plano inclui solves ilimitados dentro das threads contratadas. O que importa para dimensionar é o pico de workers ativos ao mesmo tempo, não o total de servidores.
| Tamanho da frota | Plano recomendado | Threads incluídas |
|---|---|---|
| 1–3 workers, baixo volume | BASIC (US$ 15/mês) | 5 |
| Staging + produção pequena | STANDARD (US$ 30/mês) | 15 |
| Produção com múltiplos workers | ADVANCE (US$ 90/mês) | 50 |
| Frota grande, alta concorrência | ENTERPRISE (US$ 300/mês) | 200 |
Ajuste captchaai_concurrency no inventário conforme o plano contratado.
Comandos de execução
Comandos prontos para rodar os playbooks em staging, em produção ou limitados a um único host:
# Deploy to staging
ansible-playbook -i inventory/staging.yml playbooks/deploy.yml
# Rolling update in production
ansible-playbook -i inventory/production.yml playbooks/rolling-update.yml
# Health check
ansible-playbook -i inventory/production.yml playbooks/health-check.yml
# Limit to specific hosts
ansible-playbook -i inventory/production.yml playbooks/deploy.yml --limit worker-1
Solução de problemas comuns
Os problemas mais frequentes ao rodar esses playbooks — e como resolver cada um:
| Problema | Causa | Correção |
|---|---|---|
| Host "Unreachable" | Chave SSH não configurada | Adicione a chave: ssh-copy-id user@host |
| Serviço não inicia | Variável de ambiente da chave de API ausente | Verifique o vars_prompt ou use o Ansible Vault |
| Rolling update travado | Falha na verificação de integridade | Verifique journalctl -u captcha-worker; aumente retries/delay |
| Configuração não aplicada | Handler não acionado | Rode com --force-handlers ou adicione changed_when: true |
| Health check retorna erro de conexão | Porta 8080 ainda não exposta, serviço subindo | Aumente retries/delay no wait_for; confira o log do worker |
getbalance retorna erro na resposta |
captchaai_api_key inválida, expirada ou mal escapada no Vault |
Gere uma chave nova no painel da CaptchaAI e atualize o valor no Vault |
Quando nada acima resolve, siga esta ordem antes de abrir uma issue interna:
- Rode
health-check.ymlisolado para descartar problema de infraestrutura. - Confira
journalctl -u captcha-worker -n 100no host afetado. - Rode o playbook de deploy com
-vvvpara ver exatamente qual task falhou.
Perguntas frequentes
Como armazeno a chave de API do CaptchaAI com segurança no Ansible?
Use o Ansible Vault: ansible-vault encrypt_string 'sua-chave-de-api' --name 'captchaai_api_key'. Guarde o valor criptografado no inventário ou nas group vars — nunca em texto puro no playbook.
Quantas threads eu configuro em captchaai_concurrency?
Nunca ultrapasse as threads do plano contratado (BASIC tem 5, STANDARD tem 15, ADVANCE tem 50). Configurar acima do limite não acelera nada, só enfileira no host.
Dá para usar o mesmo playbook de deploy com Docker em vez de systemd?
Sim. Basta trocar as tasks do systemd pelo módulo community.docker.docker_container; o Ansible passa a gerenciar o ciclo de vida do contêiner em vez do serviço.
Vale a pena rodar o health-check.yml antes de um rolling update?
Sim. Confirma que a frota já está saudável antes de mexer nela.
Como limito um deploy a um único host da frota?
Use a flag --limit: ansible-playbook -i inventory/production.yml playbooks/deploy.yml --limit worker-1.
Próximos passos
Escale sua frota de workers sem editar servidor por servidor: crie sua conta e obtenha a chave de API da CaptchaAI e implante com os playbooks Ansible deste guia.
Guias relacionados:
- Infraestrutura como código com Terraform
- Deploy de workers CaptchaAI com Docker
- Gerenciamento de configuração em produção