O seu próprio mirror RPM, e construir a correção antes de a distribuição a publicar
Como operar um mirror RPM local consistente e, quando a correção existe upstream mas ainda não como pacote, construí-la de forma limpa para que o pacote oficial a substitua mais tarde.

Quando uma vulnerabilidade grave é publicada, duas coisas decidem quanto tempo os seus servidores ficam expostos: a rapidez com que consegue obter pacotes, e se o pacote corrigido já existe. Um mirror local resolve a primeira. A capacidade de construir um pacote limpo por si, a partir da própria especificação do maintainer, resolve a segunda. É assim que fazemos ambas em Enterprise Linux, e como fazê-lo sem deixar pacotes caseiros por aí depois de os oficiais chegarem.
Porquê sequer operar um mirror próprio
Os mirrors públicos são operados por pessoas e organizações generosas, e num dia normal são rápidos. No dia em que sai uma correção crítica, todos os servidores do mundo pedem os mesmos pacotes ao mesmo tempo. Um mirror local dentro da sua própria rede transforma isso numa operação de cópia local. Permite-lhe também corrigir servidores que estão deliberadamente isolados da internet, como sistemas de backup e de gestão, sem os abrir.
Há um benefício mais discreto: um mirror que guarda o histórico completo de pacotes permite-lhe reconstruir um servidor para um estado conhecido, ou reverter um pacote, a partir da sua própria cópia.
Fazer mirror sem nunca servir um repositório meio sincronizado
O mirror ingénuo é um rsync ou reposync diretamente para o diretório que o seu web server publica. Se um cliente executar dnf enquanto a sincronização vai a meio, pode ver metadados novos que referem pacotes que ainda não chegaram, ou metadados antigos a apontar para pacotes que acabaram de ser removidos. O resultado são erros confusos exatamente no pior momento.
Em vez disso, sincronize em duas fases:
- Primeiro os pacotes. Descarregue os pacotes para o diretório publicado. Os metadados antigos continuam a descrever um conjunto consistente, porque nada do que referem foi ainda removido.
dnf reposync --repoid=os-baseos --arch=x86_64 --arch=noarch \
--delete --norepopath -p /srv/repo/os/baseos
- Depois os metadados, trocados de uma só vez. Descarregue o
repodata/upstream para um diretório irmão (todos os ficheiros que orepomd.xmlreferencia), verifique-o, e depois substitua os metadados publicados com uma única renomeação. Os clientes veem o repositório antigo ou o novo, nunca uma mistura.
mv /srv/repo/os/baseos/repodata /srv/repo/os/baseos/repodata.old
mv /srv/repo/os/baseos/repodata.new /srv/repo/os/baseos/repodata
Usar os metadados upstream, em vez de regenerar os seus com createrepo_c, mantém o repositório exatamente como o editor o construiu.
Dê a cada tarefa de sincronização um lock para que duas execuções nunca se sobreponham, escreva um pequeno ficheiro de estado com o resultado e a hora, e alerte alguém quando uma tarefa falhar. Um mirror que deixou silenciosamente de sincronizar no mês passado é pior do que nenhum mirror, porque toda a gente confia nele.
Os clientes usam então um ficheiro de repositório simples a apontar para o seu mirror:
[local-baseos]
name=Local mirror: BaseOS
baseurl=https://mirror.example.internal/os/baseos/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-oracle
Quando a correção existe mas o pacote não
Por vezes o projeto upstream publica uma versão corrigida e o maintainer da distribuição ou do repositório ainda não a empacotou. Muitas vezes esse intervalo é de horas. Por vezes é de dias.
A regra que seguimos: construa a versão upstream a partir do empacotamento do próprio maintainer, não altere mais nada, e garanta que o pacote oficial substitui o seu automaticamente.
Construa numa sala limpa
Use um container fresco da mesma versão de distribuição dos servidores de destino, para que o ambiente de build seja conhecido e descartável:
podman run --rm -it -v ./build:/build:Z oraclelinux:<release> bash
dnf install -y rpm-build rpmdevtools dnf-plugins-core
rpmdev-setuptree
Parta do source package (SRPM) mais recente do maintainer para o branch que executa, instale-o, e instale as suas dependências de build:
rpm -ivh php-<current>.src.rpm
dnf builddep -y ~/rpmbuild/SPECS/php.spec
Altere apenas a versão, e verifique a origem
Descarregue o tarball upstream corrigido do site oficial do projeto e verifique-o contra o checksum que o projeto publica.
sha256sum php-<fixed>.tar.xz
No spec file, atualize Version para a versão corrigida e substitua a source. Deixe patches, opções de configure e listas de ficheiros como o maintainer os escreveu. Se um patch do maintainer já não se aplicar à nova versão, pare e perceba porquê antes de avançar.
Escolha um release que se afaste
Este é o passo de que as pessoas se esquecem. O seu pacote tem de ordenar abaixo do eventual pacote oficial do maintainer da mesma versão, para que um dnf upgrade normal substitua o seu. Um release que comece por 0. faz isso de forma fiável:
Release: 0.1.local%{?dist}
Verifique-o antes de construir o que quer que seja, usando a mesma comparação que o rpm usa:
rpmdev-vercmp 0:X.Y.Z-0.1.local.elN 0:X.Y.Z-1.elN.maint
O release oficial deve sair como mais recente. Se não sair, altere a sua string de release até sair.
Construa, teste, guarde as evidências
rpmbuild -ba ~/rpmbuild/SPECS/php.spec
Guarde os pacotes construídos com os seus checksums e uma nota com o checksum do source tarball, para que qualquer pessoa possa dizer mais tarde exatamente o que foi instalado e de onde veio.
Publique os seus builds num repositório separado no seu mirror, não misturados na cópia do repositório do vendor. Quando o pacote oficial chegar ao repositório em mirror, a atualização normal seguinte substitui o seu, e o seu repositório separado pode ser esvaziado.
O mérito a quem o merece
Nada disto substitui as pessoas que mantêm os pacotes. Maintainers de repositórios como Remi Collet, em cujos repositórios de PHP grande parte do mundo Enterprise Linux se apoia, publicam correções com uma rapidez notável. Construir a partir da especificação deles é uma forma de cobrir as últimas horas, não um substituto do seu trabalho. Durante as correções do PHP2Shell escrevemos sobre ambos os lados disso: PHP2Shell: patched PHP packages e Respect to Remi.
Uma checklist para a sua própria plataforma
- De onde é que os seus servidores obtêm pacotes, e o que acontece se esse sítio estiver lento?
- Os seus servidores isolados podem ser corrigidos sem serem abertos à internet?
- Poderia um cliente alguma vez ver um repositório meio sincronizado no seu mirror?
- Alguém é avisado quando uma sincronização do mirror falha?
- Se tivesse de construir um pacote esta noite, a sua string de release deixa o oficial substituí-lo?
Se quiser ajuda para montar um mirror ou um processo de builds de emergência, os nossos engenheiros partilham com gosto o que funciona. Fale com um engenheiro
Related
- /what-we-do/operations/package-builds-mirror/
- /what-we-do/operations/emergency-vulnerability-response/
- /what-we-do/data-web/php-upgrades-security-patching/
Publicado em 8 de setembro de 2026.
Todas as notas de campo