Git para Sysadmins: Controlo de Versões de Configuração em 2026

Sysadmins gerem dezenas de ficheiros de configuração — Nginx, Postfix, Docker Compose, scripts PowerShell, cron jobs, Ansible playbooks. Quando algo para de funcionar, a primeira pergunta é “o que mudou?”. Sem controlo de versões, a resposta é “não sei”. Com Git, cada alteração fica registada com autor, data e mensagem. Este artigo mostra como usar Git para gerir configuração de servidores, com repositórios remotos, branching para mudanças, e integração com Ansible — sem ser developer (Git docs).

Neste artigo

  1. Entender Git para Configuração de Sistemas
  2. Pré-requisitos e Instalação
  3. Passo 1 — Inicializar Repositório de Configuração
  4. Passo 2 — Trabalhar com Repositório Remoto (Gitea/GitHub)
  5. Passo 3 — Branching para Mudanças em Produção
  6. Passo 4 — Hooks e Deploy Automático
  7. Passo 5 — Git com Ansible
  8. Passo 6 — Auditoria e Histórico de Mudanças
  9. Git vs Outras Abordagens — Comparação
  10. Erros Comuns
  11. Checklist Rápido de Verificação

1. Entender Git para Configuração de Sistemas

Git é um sistema de controlo de versões distribuído. Cada ficheiro tem histórico completo de alterações. Podes voltar a qualquer versão anterior, ver quem mudou o quê e quando, e mergear mudanças de múltiplas pessoas sem conflitos.

Analogia: Git é como um caderno de registos com fotocopiadora integrada. Cada vez que alteras uma página, o caderno guarda a versão anterior. Se alguém altera a mesma página noutro caderno, a fotocopiadora mergeia as duas versões. Se algo corre mal, voltas à página de ontem em 2 segundos.

Conceito Git Equivalente sysadmin Utilidade
Repository (repo) Pasta de configuração com histórico Guardar todos os configs num só sítio
Commit Snapshot de uma alteração “Mudei a porta do Nginx de 80 para 8080”
Branch Linha paralela de mudanças Testar mudanças sem afectar produção
Merge Juntar branch na linha principal Aplicar mudanças testadas em produção
Remote Cópia do repo noutro servidor Backup + colaboração
Clone Cópia local do repo Trabalhar offline no servidor
Pull / Push Sincronizar mudanças Enviar configs para o servidor central
.gitignore Lista de ficheiros a ignorar Não versionar secrets, logs, caches

Para sysadmins, Git resolve três problemas concretos:

  1. “O que mudou?”git log mostra todas as alterações com data e autor
  2. “Como voltar atrás?”git checkout restaura qualquer versão anterior
  3. “Quem fez isto?”git blame mostra quem alterou cada linha (Git Pro book)

2. Pré-requisitos e Instalação

Requisito Detalhe
Git 2.40+ (qualquer versão recente)
Editor de texto vim, nano, ou VS Code
Servidor remoto (opcional) Gitea self-hosted, GitHub, GitLab
SSH key Para autenticação com remoto

Instalar Git:

Ubuntu/Debian:

sudo apt update && sudo apt install git

Fedora/RHEL:

sudo dnf install git

Arch Linux:

sudo pacman -S git

macOS:

brew install git

Se brew não estiver instalado, instalar primeiro: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)".

Configurar identidade (uma vez por máquina):

git config –global user.name “Duarte Spínola”
git config –global user.email “[email protected]
git config –global init.defaultBranch main

O que cada config faz:

  • user.name — nome que aparece em cada commit
  • user.email — email que aparece em cada commit
  • init.defaultBranch main — usa main em vez de master como branch inicial (convenção moderna)

3. Passo 1 — Inicializar Repositório de Configuração

Criar um repositório para guardar a configuração de todos os servidores:

sudo mkdir -p /srv/git/configs
cd /srv/git/configs
sudo git init

Criar estrutura de pastas por servidor:

sudo mkdir -p nginx postfix docker-scripts ansible cron-jobs

Copiar configs actuais para o repositório:

sudo cp /etc/nginx/nginx.conf nginx/
sudo cp /etc/nginx/sites-available/* nginx/
sudo cp /etc/postfix/main.cf postfix/
sudo cp -r /etc/ansible/playbooks/* ansible/

Criar .gitignore para excluir ficheiros sensíveis:

sudo tee .gitignore > /dev/null << 'EOF' # Secrets — nunca versionar
*.key
*.pem
*.p12
.env
shadow
passwd

# Logs
*.log
*.log.*

# Caches
__pycache__/
*.pyc
.vagrant/
EOF

O que o .gitignore faz: diz ao Git para ignorar estes ficheiros — nunca os committa, nunca os envia para o remoto. Ficheiros .key e .pem contêm chaves privadas que NUNCA devem ir para um repositório Git (Git ignore docs).

⚠️ Atenção

Se já fizeste commit de um ficheiro secret, removê-lo do .gitignore não apaga o histórico. Usar git filter-branch ou BFG Repo-Cleaner para remover do histórico. Depois rodar todas as chaves comprometidas.

Fazer o primeiro commit:

sudo git add .
sudo git commit -m “Estado inicial: configs nginx, postfix, ansible, cron”

O que cada comando faz:

  • git add . — adiciona todos os ficheiros da pasta ao staging area (ficheiros a serem commitados)
  • git commit -m — regista um snapshot com mensagem descritiva

4. Passo 2 — Trabalhar com Repositório Remoto (Gitea)

Para backup e colaboração, configurar um repositório remoto. Gitea é leve e self-hosted — ideal para PME.

Instalar Gitea com Docker:

docker run -d –name gitea \
-p 3000:3000 \
-p 2222:22 \
-v /srv/gitea:/data \
–restart always \
gitea/gitea:latest

O que cada parâmetro faz:

  • -p 3000:3000 — porta web do Gitea
  • -p 2222:22 — porta SSH para git push/pull
  • -v /srv/gitea:/data — persiste dados do Gitea no host
  • --restart always — reinicia automaticamente se o Docker ou o servidor reiniciar

No Gitea (acessível em http://servidor:3000), criar utilizador e repositório configs. Depois ligar o repo local ao remoto:

sudo git remote add origin ssh://git@servidor:2222/admin/configs.git
sudo git push -u origin main

O que cada comando faz:

  • git remote add origin — define o servidor remoto onde o repo vai ser sincronizado
  • git push -u origin main — envia a branch main para o remoto e define upstream (future git push sem argumentos)

5. Passo 3 — Branching para Mudanças em Produção

Antes de alterar uma config em produção, criar uma branch para testar:

cd /srv/git/configs
sudo git checkout -b feature/nginx-rate-limiting

O checkout -b cria uma nova branch e muda para ela imediatamente. A branch main fica intacta.

Fazer as alterações necessárias:

sudo vim nginx/nginx.conf
# Adicionar rate limiting no bloco http

Commitar as mudanças na branch:

sudo git add nginx/nginx.conf
sudo git commit -m “Adicionar rate limiting no Nginx (100 rps por IP)”

Para aplicar em produção, fazer merge para main:

sudo git checkout main
sudo git merge feature/nginx-rate-limiting

E copiar a config para o local de produção:

sudo cp nginx/nginx.conf /etc/nginx/nginx.conf
sudo nginx -t && sudo systemctl reload nginx

ℹ️ Nota: O nginx -t testa a configuração sem recarregar — sempre correr antes de reload. Se o teste falhar, NÃO fazer reload.

6. Passo 4 — Hooks e Deploy Automático

Git hooks são scripts que correm automaticamente em eventos Git. O hook post-merge pode deployar configs automaticamente:

sudo tee /srv/git/configs/.git/hooks/post-merge > /dev/null << 'EOF' #!/bin/bash
# Deploy automático após merge

# Nginx
if git diff –name-only HEAD@{1} HEAD | grep -q “^nginx/”; then
cp nginx/nginx.conf /etc/nginx/nginx.conf
cp nginx/sites-available/* /etc/nginx/sites-available/
nginx -t && systemctl reload nginx
echo “Nginx config deployed and reloaded”
fi

# Postfix
if git diff –name-only HEAD@{1} HEAD | grep -q “^postfix/”; then
cp postfix/main.cf /etc/postfix/main.cf
postfix check && systemctl reload postfix
echo “Postfix config deployed and reloaded”
fi

# Ansible
if git diff –name-only HEAD@{1} HEAD | grep -q “^ansible/”; then
echo “Ansible playbooks updated — run manually: ansible-playbook ansible/site.yml”
fi
EOF
sudo chmod +x /srv/git/configs/.git/hooks/post-merge

O que o hook faz:

  • Verifica que ficheiros mudaram entre o estado anterior e o actual (git diff --name-only)
  • Se ficheiros na pasta nginx/ mudaram, copia para /etc/nginx/ e recarrega
  • Se ficheiros na pasta postfix/ mudaram, copia para /etc/postfix/ e recarrega
  • Para Ansible, apenas avisa (não corre playbooks automaticamente — demasiado perigoso)

7. Passo 5 — Git com Ansible

O Ansible já usa ficheiros YAML para playbooks. Combinar com Git dá versionamento completo de automação.

Estrutura recomendada:

ansible/
├── inventory/
│ ├── production.yml
│ └── staging.yml
├── group_vars/
│ ├── all.yml
│ └── webservers.yml
├── playbooks/
│ ├── site.yml
│ ├── nginx.yml
│ └── security-hardening.yml
├── roles/
│ ├── nginx/
│ ├── postfix/
│ └── common/
└── ansible.cfg

Workflow:

  1. Criar branch para nova role ou playbook
  2. Testar com ansible-playbook --check (dry run)
  3. Aplicar em staging
  4. Merge para main e aplicar em produção
# Testar em dry-run
ansible-playbook playbooks/nginx.yml –check –diff -i inventory/staging.yml

# Aplicar em staging
ansible-playbook playbooks/nginx.yml -i inventory/staging.yml

# Se OK, merge e aplicar em produção
git checkout main
git merge feature/nginx-role
ansible-playbook playbooks/nginx.yml -i inventory/production.yml

O --check simula mudanças sem as aplicar. O --diff mostra o que mudaria em cada ficheiro. Em produção, sempre fazer --check --diff primeiro (Ansible docs).

8. Passo 6 — Auditoria e Histórico de Mudanças

Ver histórico de alterações

git log –oneline –graph –all

Output típico:

* a3f5e2c (HEAD -> main, origin/main) Adicionar rate limiting no Nginx
* b8d1f4a Actualizar postfix main.cf — relay para Microsoft 365
* c2e9a8b Estado inicial: configs nginx, postfix, ansible, cron

Ver quem alterou uma linha específica

git blame nginx/nginx.conf

Mostra, para cada linha: commit hash, autor, data, e conteúdo da linha.

Ver o que mudou entre dois commits

git diff c2e9a8b..a3f5e2c — nginx/

Mostra as diferenças na pasta nginx/ entre o commit inicial e o actual.

Voltar a uma versão anterior de um ficheiro

git checkout c2e9a8b — nginx/nginx.conf

Restaura o nginx.conf para a versão do commit c2e9a8b. Depois commitar a reversão:

git commit -m “Reverter nginx.conf para estado inicial — rate limiting causava 503s”

9. Git vs Outras Abordagens — Comparação

Abordagem Tracking Backup Rollback Colaboração Auditoria
Git Completo Sim (remoto) Instantâneo Sim Excelente
Backups manuais Nenhum Sim Lento Não Fraca
Pasta de versões Básico Sim Manual Não Fraca
etckeeper (Git em /etc) Completo Sim (remoto) Instantâneo Sim Excelente
Ansible sem Git Nenhum Nenhum Não Não Nenhuma

etckeeper é uma ferramenta que automaticamente faz commit de /etc/ após cada alteração com apt/dnf. Para PME que quer zero esforço:

sudo apt install etckeeper
# Auto-inicializa repo Git em /etc e auto-commits após cada package install

10. Erros Comuns

Problema Causa Solução
git push rejeitado Remote tem commits que não tens localmente git pull --rebase origin main antes de push
Merge conflict Dois commits alteraram as mesmas linhas Editar ficheiro, resolver conflitos (<<<<<<< ======= >>>>>>>), depois git add + git commit
Ficheiro secret no histórico Commit acidental de .key ou .env git filter-branch --tree-filter 'rm -f ficheiro.key' HEAD ou BFG Repo-Cleaner
git status mostra ficheiros que não queres .gitignore mal configurado Adicionar padrão ao .gitignore. Se já tracked: git rm --cached ficheiro
Hook não executa Sem permissão de execução chmod +x .git/hooks/post-merge
Perdi o meu trabalho Commit esquecido antes de mudar de branch git stash guarda mudanças não commitadas. git stash pop recupera
detached HEAD Checkout de um commit em vez de branch Criar branch: git checkout -b nova-branch
Push para branch errada git push origin develop em vez de main Verificar branch actual com git branch antes de push

11. Checklist Rápido de Verificação

  • [ ] Git instalado e identidade configurada (git config --global)
  • [ ] Repositório inicializado em /srv/git/configs
  • [ ] .gitignore configurado (secrets, logs, caches)
  • [ ] Estrutura de pastas por serviço (nginx/, postfix/, ansible/)
  • [ ] Repositório remoto configurado (Gitea ou GitHub)
  • [ ] git push funciona sem erros
  • [ ] Hook post-merge configurado para deploy automático
  • [ ] Branch de teste criada antes de alterar produção
  • [ ] nginx -t / postfix check antes de reload
  • [ ] Histórico limpo: git log --oneline mostra mensagens descritivas

Artigos Relacionados

Este artigo foi útil?

Duarte Spínola

Deixe um Comentário