Do SSH em lote à automação com UI: gerenciando múltiplas VPS com Ansible Semaphore
Voltar para blog

Do SSH em lote à automação com UI: gerenciando múltiplas VPS com Ansible Semaphore

01/09/2026 · 4 min · DevOps

Por que mover a automação de terminais isolados para uma interface#

Gerenciar dezenas de servidores VPS no dia a dia chega a um ponto em que abrir terminais SSH manuais ou rodar scripts isolados se torna um gargalo operacional arriscado, gerando inconsistências de configuração (configuration drift).

Recentemente, estruturei uma interface gráfica local no meu computador para centralizar a orquestração de playbooks, disparar rotinas via formulários visuais (Surveys) e manter visibilidade sobre o inventário de servidores, sem perder o controle do código.

Durante a montagem do ambiente, enfrentei desde falhas de compilação do docker-compose legado no Python 3.12 até a complexidade de rodar o AWX localmente. Abaixo, compartilho os problemas encontrados, as causas raiz e o passo a passo da solução que adotei na prática.

1. O modelo declarativo para gerenciar servidores#

Tratar servidores como entidades únicas configuradas manualmente aumenta a chance de falhas humanas. O modelo recomendado organiza a infraestrutura em camadas declarativas:

Para transformar playbooks em ferramentas operacionais reutilizáveis no dia a dia, uma interface com suporte a Surveys (formulários que definem variáveis antes do disparo) é o componente ideal.

2. Obstáculo 1: a quebra do Docker-compose legado no Python 3.12#

Ao preparar o ambiente local para subir containers, a primeira tentativa de instalar o Docker Compose via pip3 falhou:

sudo pip3 install docker-compose --break-system-packages

Traceback do erro:

Collecting docker-compose
  Downloading docker_compose-1.29.2-py2.py3-none-any.whl.metadata (4.7 kB)
Collecting PyYAML<6,>=3.10 (from docker-compose)
  Downloading PyYAML-5.4.1.tar.gz (175 kB)
...
  AttributeError: 'build_ext' object has no attribute 'cython_sources'
error: subprocess-exited-with-error

Causa raiz:#

  1. O pacote docker-compose no PyPI refere-se à versão legada em Python (v1.29.2), dependente do PyYAML 5.4.1.
  2. No Python 3.12 com setuptools moderno, módulos legados do distutils foram removidos, quebrando a compilação do Cython.
  3. O Docker Compose moderno (V2) é um binário nativo e independente escrito em Go, empacotado como plugin CLI do Docker (docker compose).

3. Obstáculo 2: codename de distribuição derivada no repositório APT#

Ao tentar instalar o plugin oficial via APT em uma distribuição Linux derivada (como Linux Mint):

E: O repositório 'https://download.docker.com/linux/ubuntu zara Release' não tem um arquivo Release.

Causa raiz e solução:#

O mirror da Docker não possui árvores de pacotes para o codename derivado (zara). É necessário apontar para o codename base oficial da Canonical (noble, jammy):

# 1. Remover a entrada inválida
sudo rm /etc/apt/sources.list.d/docker.list

# 2. Adicionar com a base compatível
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  noble stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 3. Atualizar e instalar o plugin em Go
sudo apt-get update
sudo apt-get install docker-compose-plugin

Alternativamente, o binário estático pode ser instalado diretamente do GitHub:

sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

Validando a versão:

docker compose version

4. O desafio com o AWX: complexidade e consumo de recursos#

Com o Docker operacional, avaliei o AWX (versão open-source do Ansible Automation Controller). No entanto, o projeto oficial migrou completamente para o AWX Operator, exigindo um cluster Kubernetes (K3s ou Minikube) ativo e consumindo entre 4 GB e 8 GB de memória RAM apenas em repouso.

Para uma estação de trabalho local, esse overhead consome recursos excessivos da máquina.

5. A solução leve: Ansible Semaphore#

Direcionei o ambiente para o Ansible Semaphore, uma UI moderna, extremamente leve e escrita em Go.

RecursoAnsible AWXAnsible Semaphore
ArquiteturaKubernetes (AWX Operator)Binário Go ou Docker Compose simples
Consumo de Memória4 GB a 8 GB+ de RAMMenos de 200 MB de RAM
Suporte a SurveysSimSim (campos visuais que injetam extra_vars)
Complexidade de SetupAltaPronta em 1 minuto

Como funcionam os surveys na prática#

Ao criar um Job Template no Semaphore, é possível adicionar um formulário de Survey. Quando o operador dispara a tarefa na interface, os campos preenchidos são passados como variáveis extras (extra_vars):

---
- name: Manutencao de Servicos via Survey
  hosts: "{{ vps_environment }}"
  become: true
  tasks:
    - name: Garantir estado do servico selecionado
      ansible.builtin.service:
        name: "{{ target_service }}"
        state: restarted

Subindo o Semaphore com Docker compose#

O arquivo docker-compose.yml declara o Semaphore e a persistência em MySQL:

services:
  mysql:
    image: mysql:8
    container_name: semaphore-mysql
    restart: unless-stopped
    environment:
      - MYSQL_ROOT_PASSWORD=db_root_secure_pass
      - MYSQL_DATABASE=semaphore
      - MYSQL_USER=semaphore_user
      - MYSQL_PASSWORD=semaphore_db_pass
    volumes:
      - semaphore_db_data:/var/lib/mysql

  semaphore:
    image: semaphoreui/semaphore:latest
    container_name: semaphore-ui
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - SEMAPHORE_DB_USER=semaphore_user
      - SEMAPHORE_DB_PASS=semaphore_db_pass
      - SEMAPHORE_DB_HOST=mysql
      - SEMAPHORE_DB_PORT=3306
      - SEMAPHORE_DB_DIALECT=mysql
      - SEMAPHORE_DB=semaphore
      - SEMAPHORE_PLAYBOOK_PATH=/tmp/semaphore
      - SEMAPHORE_ADMIN_PASSWORD=admin_secure_pass
      - SEMAPHORE_ADMIN_NAME=Admin
      - SEMAPHORE_ADMIN_EMAIL=user@email.com
      - SEMAPHORE_ADMIN_USERNAME=admin
    depends_on:
      - mysql

volumes:
  semaphore_db_data:

Inicie os containers:

docker compose up -d

Acesse o painel em http://localhost:3000 para vincular repositórios Git de playbooks, importar chaves SSH e criar templates de tarefas interativas.

Lições práticas e escolha da stack#

  1. Evite pip para o Docker Compose: No Python 3.12, instale o plugin oficial em Go (docker-compose-plugin) via repositório APT ou binário do GitHub.
  2. Ajuste codenames de distros derivadas: Se o APT reclamar de release 404, substitua o codename interno pelo codename base oficial da Canonical no arquivo de repositório.
  3. Equilíbrio de ferramentas: O AWX é ideal para ambientes corporativos com governança complexa sobre Kubernetes, enquanto o Ansible Semaphore entrega automação ágil, baixo consumo de memória e facilidade operacional para gerenciar múltiplas VPSs.

Este artigo foi útil?

Deixe uma reação rápida para apoiar o conteúdo:

CC BY-NC

Este post está licenciado sob CC BY-NC.

Comentários

Participe da discussão abaixo.

0 comentários