Manter uma frota de sistemas Gentoo, ou lutar para compilar pacotes em um servidor subdimensionado, pode ser um processo incrivelmente tedioso. Esperar horas pela compilação de um único pacote pode rapidamente se acumular e, eventualmente, você pode acabar querendo tocar fogo no seu home lab.

A menos que você seja rico, seus servidores domésticos provavelmente são equipamentos de 10 anos atrás feitos de restos de PC que ficaram guardados. Uma solução parcial é simplesmente não alterar as flags do Portage de forma alguma e usar o binhost fornecido pelo próprio Gentoo. Mas isso apresenta dois problemas: nem tudo o que está disponível no Portage existe como pacote binário nos espelhos do binhost deles, e o segundo é que você abre mão da personalização dos pacotes que realmente utiliza.

A solução que não envolve abandonar seu amado Gentoo? Um Binhost. Para simplificar: pegue aquele PC principal bruto, poderoso, e faça ele trabalhar compilando as coisas para seus servidores.

Pré-requisitos

  • Uma máquina rodando Gentoo (esta será a máquina host que executará a compilação), com acesso root.
  • Os processadores (CPUs) do seu host e dos servidores devem ter a mesma arquitetura, não irei entrar aqui em cross-compiling para ARM.
  • Acesso a todos os clientes Gentoo que receberão os pacotes binários (para copiar o arquivo world e as configurações de /etc/portage/ deles).
  • Placeholders: Ao longo deste guia, você verá <host> e <keyid>.
    • <host>: Substitua pelo nome da máquina (hostname) que você pretende servir com esses binários.
    • <keyid>: Substitua pelo ID único da sua chave GPG recém-gerada.

Etapa 1: Gerando e Exportando Chaves GPG

O Portage exige que os pacotes binários sejam assinados por uma chave GPG para garantir sua integridade e autenticidade. Sim, você pode desabilitar isso, mas é uma má ideia. Antes de começarmos a construir nosso ambiente, precisamos gerar um par de chaves em nosso host principal.

Execute o seguinte comando para iniciar o assistente de geração de chaves:

gpg --full-generate-key

Quando solicitado pelo assistente, siga estas etapas específicas:

  • Selecione 1 (RSA e RSA): Este algoritmo fornece um padrão seguro e amplamente compatível para assinatura de pacotes.
  • Selecione 0 (chave não expira): Como esta chave será usada para assinar pacotes pelos próximos anos, configurá-la para nunca expirar evita as dores de cabeça de o Portage de repente se recusar a validar pacotes quando a chave expirar.
  • Nome e E-mail: Preencha com o nome do seu binhost e um e-mail de contato.
  • Senha de proteção (Passphrase): Deixe isso em branco. Como este binhost é destinado a compilações automatizadas, ter uma senha exigiria intervenção manual toda vez que o Portage tentar assinar um pacote.

Uma vez gerada a chave, precisamos encontrar seu ID único. Execute:

gpg --list-keys --fingerprint

Procure pela chave recém-criada na saída e copie o ID (este será seu <keyid>).

Em seguida, exporte tanto a chave pública quanto a privada. Precisaremos mover essas chaves para dentro do nosso ambiente chroot mais tarde:

gpg --armor --export <keyid> > binhost-public.asc
gpg --armor --export-secret-keys <keyid> > binhost-private.asc

Etapa 2: Preparando o Diretório Raiz do Binhost

Agora configuraremos uma estrutura de diretórios dedicada que servirá como a raiz do sistema de arquivos para nosso ambiente chroot.

mkdir ~/binhost/<host>
cd binhost/<host>

(Nota: Se você estiver compilando binários para várias máquinas com exatamente a mesma arquitetura e CFLAGS, você pode usar um nome genérico aqui. Se diferirem, deve criar diretórios separados para cada uma).

Baixe o último tarball do Stage 3. Ele fornece os arquivos mínimos necessários para inicializar (bootstrap) um sistema Gentoo. O link abaixo apontava para o mais recente na época em que isto foi escrito. No entanto, tenha em mente: ele deve corresponder ao stage 3 usado em seus servidores. O link abaixo é o mínimo usando OpenRC.

wget https://distfiles-cdn-origin.gentoo.org/releases/amd64/autobuilds/current-stage3-amd64-openrc/stage3-amd64-openrc-20260614T170130Z.tar.xz

Extraia o tarball no diretório atual. A flag --numeric-owner é crucial para garantir que as permissões dos arquivos correspondam aos IDs numéricos exatos esperados pelo Gentoo:

tar xpvf stage3-*.tar.xz --xattrs-include='*.*' --numeric-owner

Para garantir que o binhost compile exatamente os mesmos pacotes (e com as mesmas flags USE) que sua máquina de destino, copie o arquivo world e a configuração do Portage de seus servidores. (Certifique-se de substituir user@servidor.dominio pelas credenciais SSH reais e pelo hostname da sua máquina de referência, e preste atenção para a pasta de destino não ter a barra inicial /!! Você está dentro da pasta binhost/).

scp -r user@servidor.dominio:/var/lib/portage/world var/lib/portage/world
scp -r user@servidor.dominio:/etc/portage/ etc/

Etapa 3: Sincronizando e Preparando o Ambiente Chroot

Antes de entrarmos no chroot, precisamos sincronizar a árvore do Portage e preparar as montagens (mounts) necessárias do sistema de arquivos.

Sincronize a árvore do Portage na máquina host:

emerge --sync

Copie o repositório recém-sincronizado para nosso diretório chroot:

cp -a /var/db/repos/gentoo/ var/db/repos/

Mova as chaves GPG exportadas anteriormente para o diretório home do root do chroot, para que fiquem acessíveis dentro do ambiente:

mv ~/*.asc ./home/root

Monte os sistemas de arquivos necessários para dar ao ambiente chroot acesso aos recursos do sistema:

mount --types proc /proc proc
mount --rbind /dev dev

Para permitir que o ambiente chroot acesse a internet (o que é necessário para o emerge buscar o código-fonte), copie a configuração do resolvedor DNS:

cp --dereference /etc/resolv.conf etc

Etapa 4: Entrando no Chroot e Configurando o GPG

É hora de entrarmos em nosso ambiente recém-criado. Execute:

chroot . /bin/bash

Atualize seu prompt de shell para lembrar visualmente que você está agora dentro do chroot:

export PS1="(chroot) $PS1"

Dentro do chroot, importe a chave GPG privada:

gpg --import "binhost-private.asc"

O Portage depende do nível de confiança da chave GPG. Devemos definir a confiança como “ultimata” (ultimate) para que o Portage confie automaticamente nos pacotes assinados por esta chave, sem confirmação manual.

Execute o editor de chaves:

gpg --edit-key <keyid>

Quando o prompt do GPG aparecer, digite trust para alterar o nível de confiança. Um menu será apresentado. Selecione a opção mais alta (geralmente 5) para definir o nível de confiança como Ultimate (Máximo). Saia do prompt digitando quit.

Verifique se o banco de dados de confiança foi atualizado corretamente:

gpg --check-trustdb

Por fim, precisamos configurar o homedir (diretório home) específico do GPG do Portage com a chave pública para que o gerenciador de pacotes possa validar as assinaturas. Esta configuração será para o GPG do próprio portage (daí o argumento homedir); afinal, é o Portage que usará a chave pública para verificar a assinatura feita pela sua chave privada instalada no GPG do usuário root.

gpg --homedir=/etc/portage/gnupg --import "binhost-public.asc"
gpg --homedir=/etc/portage/gnupg --edit-key <keyid>

Repita o processo de alterar o nível de confiança para Ultimate e depois saia. Verifique o banco de dados de confiança do Portage:

gpg --homedir=/etc/portage/gnupg --check-trustdb

Etapa 5: Ajustando o make.conf do Portage para gerar binpkgs

Agora, é hora de alterar o make.conf para compilar seus pacotes binários à medida que compilar o restante. Abaixo está um exemplo de como deveria ficar. Alguns pontos importantes a observar:

  • BINPKG_GPG_SIGNING_KEY deve conter o ID da sua chave GPG.
  • O -march deve ser o denominador comum mínimo entre todos os servidores e o host. Lembre-se, o host precisa executar compiladores em um ambiente chroot que imite seu servidor, e seu servidor deve ser capaz de executar os binários. Uma estratégia segura é definir -march como core2 (o mínimo que tem todas as instruções da Intel e AMD dos últimos 15 anos) e -mtune definido para o CPU do seu servidor. Isso garante que seu host ainda conseguirá executar todos os compiladores necessários para criar binpkgs para seu servidor, e que seu servidor receberá binários com alguma otimização, mas não o suficiente para introduzir incompatibilidades com o -march definido.
  • Defina MAKEOPTS para corresponder ao número de núcleos e threads do CPU do seu host.
COMMON_FLAGS="-march=core2 -O2 -pipe -mtune=znver1"
RUSTFLAGS="${RUSTFLAGS} -C -C opt-level=2 --target-cpu=core2 --tune-cpu=znver1"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS}"
FCFLAGS="${COMMON_FLAGS}"
FFLAGS="${COMMON_FLAGS}"
MAKEOPTS="-j16 -l17"

# NOTA: Esta etapa foi construída com a flag USE bindist habilitada

# Isso define o idioma da saída de compilação para o inglês.
# Por favor, mantenha esta configuração intacta ao reportar bugs.
LC_MESSAGES=C.UTF-8

BINPKG_GPG_SIGNING_GPG_HOME="/root/.gnupg"
BINPKG_GPG_SIGNING_KEY="<keyid>"
FEATURES="${FEATURES} buildpkg binpkg-signing"

# besteira de licenças
ACCEPT_LICENSE="-* @FREE @BINARY-REDISTRIBUTABLE"

# kernels de distribuição a granel
USE="dist-kernel"

GENTOO_MIRRORS="rsync://gentoo.c3sl.ufpr.br/gentoo/"
GRUB_PLATFORMS="efi-64"

# aceleração de vídeo por hardware (GPU)
USE="vaapi"

Etapa 6: Compilando o Sistema Base

Antes de podermos compilar qualquer coisa, precisamos criar um diretório exigido pelo Portage moderno e utilitários do sistema:

mkdir /run/lock

Agora, o grande evento. Iremos executar emerge --emptytree:

emerge --emptytree

O que isso faz? A flag --emptytree diz ao Portage para assumir que o sistema não tem absolutamente nenhum pacote instalado e prosseguir para instalar tudo o que está listado no arquivo world que copiamos anteriormente. Como seu /etc/portage/make.conf dentro deste ambiente está configurado para atuar como um binhost, o Portage compilará cada único pacote e armazenará os arquivos binários .tbz2 resultantes no diretório do repositório do binhost (geralmente /usr/portage/packages/).

Este processo levará uma quantidade significativa de tempo, dependendo do número de pacotes no seu arquivo world. Você pode relaxar e deixar ele rodar. Quando terminar, você terá um repositório completo de binários pré-compilados, perfeitamente adaptados para sua máquina de destino!

A partir de agora, você pode simplesmente usar o comando de atualização mais comum ao criar pacotes binários para seus servidores, e será muito mais rápido:

emerge --ask --update --deep --newuse @world

Conclusão

Parabéns! Você configurou com sucesso um ambiente chroot de binhost Gentoo.

Para finalizar sua configuração, eventualmente você precisará configurar um servidor web leve (como Nginx ou Apache) para servir o conteúdo do diretório /usr/portage/packages/ via HTTP para que suas outras máquinas possam acessá-lo. Depois, em suas máquinas clientes (seus servidores ou hardware subdimensionado), você simplesmente configurará a variável PORTAGE_BINHOST no /etc/portage/make.conf delas e executará emerge --emptytree para baixar instantaneamente seus binários recém-compilados.