OpenVox: Gestão de Configuração em Linux
Numa PME com cinco ou mais servidores Linux, o padrão é quase sempre o mesmo: cada máquina foi montada à mão, com pacotes instalados por SSH e configurações ajustadas ficheiro a ficheiro. Passado um ano, dois servidores que deviam ser iguais já não o são. Um pacote actualizado aqui, uma linha acrescentada ali, e ninguém sabe ao certo o que corre em produção. É a deriva de configuração, e explica metade dos mistérios que surgem quando algo falha.
O OpenVox ataca o problema por outra via: em vez de descreveres os passos para instalar um serviço, descreves o estado desejado. O pacote ntpsec deve estar instalado, o ficheiro /etc/ntpsec/ntp.conf deve ter um certo conteúdo, o serviço deve estar a correr e activado no arranque. Um agente em cada servidor consulta um servidor central a cada 30 minutos, recebe a lista de diferenças e corrige o que for preciso, sem intervenção humana. Se alguém editar um ficheiro à mão e o partir, o ciclo seguinte repõe o estado correcto.
Duas notas antes de começar. No universo Puppet há o Puppet Enterprise, a edição paga da Perforce com consola web e orquestração, e houve um Puppet Open Source clássico, descontinuado no fim de 2024. A comunidade Vox Pupuli mantém o fork OpenVox, que é drop-in do Puppet 8: os comandos e os caminhos de configuração são os mesmos (puppet, puppetserver, /etc/puppetlabs/). É o OpenVox que serve de base a este tutorial, porque é a via livre activa em 2026. Duas ressalvas da documentação antes de migrar: faz backup da árvore /etc/puppetlabs/ e testa a migração — os pacotes OpenVox desinstalam e substituem os do Puppet, e os dois não podem estar instalados em simultâneo no mesmo sistema. Se o teu parque já tem Puppet da Perforce, tudo o que se segue aplica-se da mesma forma.
Neste artigo:
- Como o OpenVox funciona
- Instalar o servidor
- Primeiro agente
- O primeiro manifest
- Módulos e o Puppet Forge
- Facts e Hiera
- Ambiente prod/dev
- Diagnóstico
- Erros Comuns
- Checklist
- Artigos Relacionados
- Fontes Oficiais
1. Como o OpenVox funciona
A lógica é declarativa: escreves o estado final pretendido, nunca os comandos para lá chegar. O motor compara o estado actual do sistema com o desejado e aplica apenas as diferenças. Executar o mesmo manifest duas vezes seguidas não repete nada, o que torna as execuções seguras e repetíveis.
A arquitectura tem duas peças. O servidor (pacote openvox-server, equivalente ao puppetserver) guarda os manifests, os módulos e os dados, e responde aos agentes na porta 8140, por HTTPS. Em cada máquina gerida corre o agente (pacote openvox-agent), um serviço que por omissão aplica um ciclo a cada 30 minutos (parâmetro runinterval). Em cada ciclo, o agente recolhe os facts do sistema — distribuição, família de sistema operativo, endereço IP, memória — e envia-os ao servidor. Este compila o catálogo da máquina: a lista de recursos (packages, ficheiros, serviços) com os valores que cada um deve ter. O agente aplica o catálogo localmente, corrige só o que difere e devolve um relatório.
Os manifests escrevem-se no Puppet DSL, em ficheiros .pp organizados em classes e módulos. Os dados que variam de nó para nó ficam no Hiera. Toda a comunicação usa certificados emitidos pela CA que o próprio servidor traz consigo: no primeiro contacto, o agente gera um pedido de certificado que assinas no servidor, uma única vez por máquina.

2. Instalar o servidor
A Vox Pupuli publica pacotes para Debian e Ubuntu no apt.voxpupuli.org. No servidor (Ubuntu 24.04 no exemplo):
sudo wget https://apt.voxpupuli.org/openvox8-release-ubuntu24.04.deb
sudo dpkg -i openvox8-release-ubuntu24.04.deb
sudo apt-get update
sudo apt-get install -y openvox-server
Em Debian 12 o pacote do repositório é openvox8-release-debian12.deb. Confirma sempre o ficheiro do teu codename na página do apt.voxpupuli.org antes de descarregar.
O servidor é uma aplicação Java. O ficheiro /etc/default/puppetserver tem a linha JAVA_ARGS com os limites de memória da JVM (-Xms e -Xmx). A documentação oficial estima cerca de 512 MB de RAM por instância JRuby em actividade, mais uns 512 MB para o resto do processo. Numa VM pequena podes fixar JAVA_ARGS=”-Xms1g -Xmx1g” e reduzir o max-active-instances em /etc/puppetlabs/puppetserver/puppetserver.conf para 1. São estimativas: o consumo real depende do número de agentes, da dimensão dos módulos e catálogos, dos dados Hiera e das execuções simultâneas. Em produção, dimensiona medindo, não pelo valor de partida.
Antes do primeiro arranque, cria a autoridade certificadora (CA). O comando prepara a CA por omissão, com certificado raiz e intermédio:
sudo puppetserver ca setup
sudo systemctl start puppetserver
sudo systemctl enable puppetserver
sudo puppetserver ca list --all
Saída representativa de um servidor recém-instalado:
Signed Certificates:
Unsigned Certificates:
A lista vazia é normal: ainda nenhum agente pediu certificado.
3. Primeiro agente
No cliente Linux, instala o agente a partir do mesmo repositório:
sudo wget https://apt.voxpupuli.org/openvox8-release-ubuntu24.04.deb
sudo dpkg -i openvox8-release-ubuntu24.04.deb
sudo apt-get update
sudo apt-get install -y openvox-agent
Por omissão, o agente procura um servidor com o nome puppet no DNS. Se o teu servidor se chamar de outra forma, indica-o em /etc/puppetlabs/puppet/puppet.conf:
[agent]
server = puppet.pme.local
A primeira execução é manual e gera o pedido de certificado:
sudo puppet agent -t
Como o certificado ainda não foi assinado, a execução termina com um erro — saída representativa:
Info: Creating a new SSL key for cliente01
Info: Creating a new SSL certificate request for cliente01
Info: Certificate Request fingerprint (SHA256): 4A:9B:C1:77:F2:E0:11:3D:D8:5A:60:2C:BE:14:9F:71:35:08:D2:6E:1C:44:AA:F3:B9:52:07:8D:63:E1:2B:C5
Exiting; no certificate found and waitforcert is disabled
No servidor, lista os pedidos e assina o do agente — a impressão digital SHA256 deve coincidir com a que o agente mostrou:
sudo puppetserver ca list --all
sudo puppetserver ca sign --certname cliente01
De volta ao cliente, o mesmo comando corre agora o primeiro ciclo completo:
sudo puppet agent -t
Saída representativa de uma primeira execução bem-sucedida, ainda sem manifests a aplicar:
Info: Using configured environment 'production'
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Caching catalog for cliente01
Info: Applying configuration version '1758792000'
Notice: Applied catalog in 0.28 seconds
A partir daqui, o serviço do agente repete o ciclo a cada 30 minutos. Quando quiseres aplicar uma alteração de imediato, corre puppet agent -t à mão.
4. O primeiro manifest
Os manifests vivem em /etc/puppetlabs/code/environments/production/. O ponto de entrada é o site.pp, na subdirectoria manifests/:
sudo mkdir -p /etc/puppetlabs/code/environments/production/modules/base/manifests
sudo nano /etc/puppetlabs/code/environments/production/manifests/site.pp
node default {
include base
}
O bloco node default aplica-se a qualquer máquina sem regra própria, pelo que os agentes novos ficam logo cobertos. O módulo base declara três recursos: um pacote, um ficheiro e um serviço. Em modules/base/manifests/init.pp:
class base {
package { 'ntpsec':
ensure => installed,
}
file { '/etc/ntpsec/ntp.conf':
mode => '0644',
content => "server 0.pt.pool.ntp.org iburst\nserver 1.pt.pool.ntp.org iburst\n",
require => Package['ntpsec'],
notify => Service['ntpsec'],
}
service { 'ntpsec':
ensure => running,
enable => true,
require => File['/etc/ntpsec/ntp.conf'],
}
}
Repara nos require e no notify: por omissão, a ordem entre recursos distintos não é garantida, e o metaparâmetro require declara que um recurso só se aplica depois de outro estar resolvido — o equivalente inverso é before. O notify no ficheiro faz o serviço ser reiniciado sempre que o conteúdo muda numa execução posterior; sem ele, um ficheiro alterado não reiniciava o serviço que já estava a correr. O exemplo usa o ntpsec porque é isso que o Ubuntu 24.04 traz: o pacote ntp é de transição e instala o ntpsec, com configuração em /etc/ntpsec/ntp.conf e serviço ntpsec — os caminhos clássicos /etc/ntp.conf e serviço ntp já não se aplicam a esta versão.
Na próxima execução do agente, o catálogo aplica as três alterações — saída representativa:
Notice: /Stage[main]/Base/Package[ntpsec]/ensure: created
Notice: /Stage[main]/Base/File[/etc/ntpsec/ntp.conf]/content: content changed '{md5}a13b8f2c...' to '{md5}91cf7d04...'
Notice: /Stage[main]/Base/Service[ntpsec]/ensure: ensure changed 'stopped' to 'running'
Notice: /Stage[main]/Base/Service[ntpsec]: Triggered 'refresh' from 1 event
Notice: Applied catalog in 2.51 seconds
Na passagem seguinte, sem nada a fazer, a saída resume-se a uma linha Applied catalog. É esta idempotência que torna o OpenVox seguro para repetir.
5. Módulos e o Puppet Forge
Escrever tudo à mão escala mal. O Puppet Forge é o repositório público de módulos da comunidade, com milhares de módulos para serviços comuns: ntp, apache, postgresql, docker, fail2ban. Os módulos do Forge funcionam no OpenVox sem alterações. Para instalar o módulo oficial do NTP:
cd /etc/puppetlabs/code/environments/production
sudo puppet module install puppetlabs-ntp
Saída representativa:
Notice: Preparing to install into /etc/puppetlabs/code/environments/production/modules ...
Notice: Downloading from https://forgeapi.puppet.com ...
Notice: Installing -- do not interrupt ...
/etc/puppetlabs/code/environments/production/modules
└── puppetlabs-ntp (v11.2.0)
O módulo traz uma classe pronta a usar, que já trata das diferenças entre Debian, Ubuntu e Red Hat:
class { 'ntp':
servers => [ '0.pt.pool.ntp.org', '1.pt.pool.ntp.org' ],
}
Um módulo tem uma estrutura fixa: manifests/init.pp com a classe principal, files/ para ficheiros estáticos e templates/ para modelos. Em ambientes maiores, os módulos e as versões ficam declarados num Puppetfile e geridos por r10k, mas para começar o puppet module install chega. Antes de instalares um módulo, confere a compatibilidade com a tua versão do Puppet na página do módulo.
6. Facts e Hiera
Os facts são variáveis de leitura que o facter recolhe em cada ciclo. Acedes-lhes pelo hash $facts:
notice($facts['os']['family'])
notice($facts['networking']['ip'])
Com os facts escreves manifests que se adaptam ao sistema, por exemplo para escolher o pacote conforme a família da distribuição:
$pkg = $facts['os']['family'] ? {
'RedHat' => 'chrony',
default => 'ntpsec',
}
package { $pkg:
ensure => installed,
}
Os dados que variam por nó ou por ambiente ficam no Hiera, fora dos manifests. Um exemplo mínimo. Em /etc/puppetlabs/code/environments/production/hiera.yaml:
version: 5
defaults:
datadir: data
data_hash: yaml_data
hierarchy:
- name: "Comum"
path: "common.yaml"
Em data/common.yaml:
base::ntp_servers:
- '0.pt.pool.ntp.org'
- '1.pt.pool.ntp.org'
A classe passa a declarar o parâmetro, e o Hiera preenche-o automaticamente pelo nome base::ntp_servers:
class base (
Array[String] $ntp_servers,
) {
# usa $ntp_servers no conteúdo do ficheiro de configuração
}
Quando precisas de um valor fora de classes parametrizadas, a função lookup() vai buscá-lo ao Hiera: lookup(‘base::ntp_servers’). A regra prática: lógica nos manifests, dados no Hiera.
7. Ambiente prod/dev
O OpenVox organiza tudo em environments, subdirectorias independentes dentro de /etc/puppetlabs/code/environments/. A por omissão chama-se production. Cria ao lado uma development, com os mesmos manifests e módulos, e testa aí antes de publicar:
sudo puppet agent -t --environment development
Podes fixar o ambiente do agente em puppet.conf, na secção [agent], com environment = development. Cada ambiente tem os seus manifests, módulos e dados Hiera, pelo que um erro em development nunca chega às outras máquinas. Quando os testes passam, publica o conteúdo em production (idealmente via git, e não copiando ficheiros à mão).

8. Diagnóstico
Antes de aplicar mudanças, simula-as. A opção –noop percorre o catálogo e mostra o que mudaria, sem tocar no sistema:
sudo puppet agent -t --noop
Saída representativa de uma simulação:
Notice: /Stage[main]/Base/File[/etc/ntpsec/ntp.conf]/content: current_value '{md5}a13b8f2c...', should be '{md5}91cf7d04...' (noop)
Notice: Applied catalog in 0.09 seconds
Erros de sintaxe detectam-se sem servidor: puppet parser validate init.pp não devolve nada quando o ficheiro está correcto.
Quando algo falha, os logs do servidor ficam em /var/log/puppetlabs/puppetserver/puppetserver.log e os do agente saem no journal do systemd (journalctl -u puppet). Correr o agente à mão com puppet agent -t é a forma mais rápida de ver o erro completo no ecrã. Os espinhos mais comuns são: certificado do agente por assinar, DNS que não resolve o nome do servidor, relógio dessincronizado (os certificados SSL exigem horas certas) e ficheiros editados à mão que o OpenVox repõe no ciclo seguinte, que é exactamente o comportamento pretendido.
Erros Comuns
| Erro | Causa provável | Resolução |
|---|---|---|
Exiting; no certificate found |
Certificado do agente ainda por assinar | sudo puppetserver ca sign --certname <nome> no servidor |
Could not retrieve catalog from remote server |
Erro de sintaxe num manifest ou módulo | puppet parser validate nos ficheiros e consulta ao log do servidor |
Failed to open TCP connection ... :8140 |
Firewall ou DNS mal resolvido | Abrir a porta 8140 e confirmar o parâmetro server em puppet.conf |
Duplicate declaration: Class[X] is already declared |
Classe declarada duas vezes | Usar include em vez de class { } repetido |
| Ficheiro editado à mão volta ao anterior | Comportamento normal do agente | Alterar o manifest (ou testar primeiro com –noop) |
certificate verify failed após reinstalar o servidor |
Certificados antigos nos agentes | Confirmar que a CA foi preservada, limpar só os certificados afectados com puppetserver ca clean — destrutivo, revoga o que remove — e assinar de novo |
Checklist
- [ ] O DNS interno resolve o nome do servidor OpenVox a partir de cada agente
- [ ] A porta 8140 está aberta entre agentes e servidor
- [ ] A memória da JVM está ajustada em /etc/default/puppetserver
- [ ] A CA foi criada com puppetserver ca setup antes do primeiro arranque
- [ ] Todos os certificados dos agentes estão assinados (puppetserver ca list –all)
- [ ] Os manifests e módulos estão guardados em git
- [ ] Os testes correm primeiro em development (puppet agent -t –environment development)
- [ ] Antes de aplicar em produção, há sempre uma simulação com –noop
- [ ] Os dados que variam por nó estão no Hiera, não escritos à mão nos manifests
Artigos Relacionados
- Ansible: Automação de Configuração para PMEs
- Monit: Monitorização e Reparação Automática de Serviços Linux
- NixOS: Gestão Declarativa e Reprodutível de Servidores
Fontes Oficiais
- Instalar OpenVox (guia oficial da Vox Pupuli): https://voxpupuli.org/openvox/install/
- Repositório APT da Vox Pupuli (pacotes openvox8-release): https://apt.voxpupuli.org/
- Documentação do Puppet 8 (língua, configuração, agente): https://www.puppet.com/docs/puppet/8/puppet_index.html
- Comandos da CA (puppetserver ca): https://help.puppet.com/core/current/Content/PuppetCore/puppet_server_ca_cli.htm
- Agente como serviço (runinterval, 30 minutos): https://help.puppet.com/core/current/Content/PuppetCore/nix_agent_as_service.htm
- Guia de afinação do Puppet Server (memória JVM): https://help.puppet.com/core/current/Content/PuppetCore/server/tuning_guide.htm
- Puppet Forge — módulo puppetlabs-ntp: https://forge.puppet.com/modules/puppetlabs/ntp