terça-feira, 3 de junho de 2025

Debian Autoinstall com iPXE e Preseed no Initrd – Rápido, Leve e 100% Automático

Introdução

Automatizar instalações do Debian via rede (iPXE) pode poupar horas de trabalho, especialmente em ambientes com dezenas ou centenas de máquinas. Apesar do Preseed ser um recurso poderoso do instalador Debian, ele sofre com problemas de compatibilidade e formatação, especialmente ao lidar com particionamentos manuais e hardware legado.

Este artigo apresenta uma solução estável e compatível com máquinas novas e antigas, utilizando:


⚠️ Problemas Comuns com Preseed

Alguns dos obstáculos que encontrei ao tentar uma instalação sem intervenção via Preseed incluem:

  • Falhas silenciosas causadas por tabulações ou espaços extras no particionamento (expert_recipe);

  • A partição swap sendo ignorada se colocada fora de ordem;

  • Problemas com compatibilidade em hardware mais antigo, principalmente com discos IDE ou BIOS legados;

  • preseed.cfg sendo ignorado mesmo que especificado via kernel boot line.


✅ Solução: Preseed Embutido no Initrd

A maneira mais confiável que encontrei foi embutir o preseed.cfg diretamente no initrd.gz, garantindo que o instalador sempre o carregue — independentemente da forma como o sistema boota.


📁 Estrutura do preseed.cfg

O preseed.cfg utilizado cobre:

  • Localização, teclado, fuso horário

  • Configuração de rede e hostname fixo

  • Usuário root e padrão com senha

  • Particionamento totalmente automatizado com expert_recipe detalhado

  • Instalação de pacotes

  • Comandos pós-instalação

A parte completa do particionamento está abaixo, ao final tem o preseed.cfg completo e também o arquivo embed-preseed.sh que embute o preseed no initrd.gz para instalação via iPXE:

### Pré-carrega os módulos necessários
d-i anna-install string btrfs-modules xfs-modules

### Garante que o módulo btrfs está disponível antes do particionamento
d-i preseed/early_command string \
  modprobe btrfs || true; \
  modprobe xfs || true

### Configura o particionamento automático
d-i partman-auto/method string regular
d-i partman-auto/choose_recipe select boot-root
d-i partman-auto/expert_recipe string \
  boot-root :: \
    40 50 512 ext4 \
      $primary{ } $bootable{ } \
      method{ format } format{ } \
      use_filesystem{ } filesystem{ ext4 } \
      mountpoint{ /boot } . \
    4096 4096 4096 linux-swap \
      $primary{ } \
      method{ swap } format{ } . \
    51200 51200 51200 btrfs \
      $primary{ } \
     method{ format } format{ } \
      use_filesystem{ } filesystem{ btrfs } \
      mountpoint{ / } . \
    512 512 -1 xfs \
      $primary{ } \
      method{ format } format{ } \
      use_filesystem{ } filesystem{ xfs } \
      mountpoint{ /orangefs } .

### Confirma as ações do particionador
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true


🔧 Particionamento: pontos críticos

O expert_recipe é extremamente sensível à formatação.

Algumas observações práticas:

  • Não use tabulações, apenas espaços simples;

  • Jamais deixe espaços em branco no final das linhas;

  • A ordem das partições importa — por exemplo, a swap deve vir após /boot e antes de / (raiz);

  • No esquema de particionamento não pode ter comentários entre as linhas da string expert_recipe, aliás, não pode ter nada além do esquema de particionamento;

  • Um erro mínimo de formatação e/ou sintaxe pode resultar em falha silenciosa do instalador.


🛠️ Script: embed-preseed.sh

Esse script extrai, modifica e reempacota o initrd.gz, embutindo o preseed.cfg de forma confiável:

#!/bin/bash

set -e

# === CONFIGURAÇÕES ===

BOOT_DIR="/var/www/html/boot/debian-installer/amd64"

WORK_DIR="/tmp/initrd-work"

PRESEED_SOURCE="/var/www/html/boot/preseed.cfg"

OUTPUT_INITRD="$BOOT_DIR/initrd-custom.gz"


# === CHECAGENS INICIAIS ===

INITRD_ORIGINAL="$BOOT_DIR/initrd.gz"


if [ ! -f "$INITRD_ORIGINAL" ]; then

  echo "❌ Arquivo initrd.gz não encontrado em: $INITRD_ORIGINAL"

  exit 1

fi


if [ ! -f "$PRESEED_SOURCE" ]; then

  echo "❌ Arquivo preseed.cfg não encontrado em: $PRESEED_SOURCE"

  exit 1

fi


echo "📦 Preparando diretório de trabalho..."

rm -rf "$WORK_DIR"

mkdir -p "$WORK_DIR"

cd "$WORK_DIR"


echo "🧩 Fazendo backup do initrd original..."

cp "$INITRD_ORIGINAL" "${INITRD_ORIGINAL}.bak"


echo "🔓 Extraindo initrd.gz..."

gzip -dc "$INITRD_ORIGINAL" | cpio -id --quiet


echo "📄 Copiando preseed.cfg para raiz do initrd..."

cp "$PRESEED_SOURCE" ./preseed.cfg


echo "🗜️ Reempacotando initrd com preseed embutido..."

##find . | cpio --quiet -o -H newc | gzip -9 > "$OUTPUT_INITRD"

find . | cpio --quiet -o -H newc --owner=0:0 | gzip -9 > "$OUTPUT_INITRD"


echo "✅ Novo initrd com preseed embutido foi criado com sucesso!"

echo "📍 Local: $OUTPUT_INITRD"

echo

echo "💡 Use esta linha no seu script iPXE:"

echo "    initrd http://<IP_DO_SERVIDOR>/boot/debian-installer/amd64/initrd-custom.gz"


Como usar


$ sudo chmod +x embed-preseed.sh $ sudo ./embed-preseed.sh


🌐 Exemplo de Boot via iPXE com label iPXE embutido dentro de menu PXE


LABEL debian-ipxe
MENU LABEL Instale o Debian via iPXE (netboot e preseed) KERNEL ipxe.lkrn APPEND dhcp && chain http://192.168.1.3/boot/debian.ipxe


Conteúdo do arquivo debian.ipxe:

#!ipxe echo "Configuracao feita..." echo kernel http://192.168.1.3/boot/debian-installer/amd64/linux auto=true priority=critical initrd http://192.168.1.3/boot/debian-installer/amd64/initrd-custom.gz boot


🧩 Considerações Finais

  • Esse método provou-se confiável em servidores novos com UEFI e máquinas antigas com BIOS tradicional.

  • Testado com sucesso inclusive em hardware antigo com DDR2 e BIOS legado.

  • Evita depender de parâmetros instáveis em linha de kernel.

  • Pode ser adaptado para qualquer distribuição baseada no debian-installer.

  • O esquema total utilizado foi com label iPXE dentro de menu PXE com apache2, tftpd-hpa e isc-dhcp-server, mas pode ser utilizado com somente iPXE.


Exemplo de arquivo /var/lib/tftpboot/pxelinux.cfg/default (menu PXE): DEFAULT debian UI menu.c32 PROMPT 1 TIMEOUT 100 MENU TITLE PXE Boot Menu LABEL debian MENU LABEL Instale o Debian (PXE) KERNEL vmlinuz APPEND initrd=initrd.gz auto=true priority=critical preseed/url=http://192.168.1.3/debianiso/preseed.cfg --- LABEL memtest MENU LABEL Teste de RAM (Memtest86+ 7.20) KERNEL memtest86+ LABEL clonezilla MENU LABEL Clonezilla Live (Backup/Restore) KERNEL clonezilla/vmlinuz APPEND initrd=clonezilla/initrd.img boot=live union=overlay username=user config components noswap edd=on nomodeset ocs_live_run="ocs-live-general" ocs_live_keymap="none" ocs_live_batch="no" vga=788 fetch=tftp://192.168.1.3/clonezilla/filesystem.squashfs LABEL debian-ipxe MENU LABEL Instale o Debian via iPXE (netboot e preseed) KERNEL ipxe.lkrn APPEND dhcp && chain http://192.168.1.3/boot/debian.ipxe


preseed.cfg completo

#_preseed_V1 ###Preseed para boot PXE sem Interface Grafica### ##Preseed ideal para cluster, podendo ser adaptado## ### Locale e linguagem ### d-i debian-installer/locale string pt_BR.UTF-8 d-i console-setup/ask_detect boolean false ## Configuracoes de teclado br-abnt2 d-i console-keymaps-at/keymap select br-abnt2 d-i keyboard-configuration/xkb-keymap select br d-i keyboard-configuration/layout select br d-i keyboard-configuration/model select abnt2 d-i keyboard-configuration/variant select abnt2 d-i keyboard-configuration/options string lv3:alt_switch,compose:rctrl d-i keyboard-configuration/store_defaults_in_debconf_db boolean true d-i time/zone string America/Sao_Paulo ### Hostname e rede ### d-i netcfg/use_autoconfig boolean true d-i netcfg/disable_dhcp_hostname boolean true d-i netcfg/get_nameservers string 1.1.1.1 9.9.9.9 d-i netcfg/get_hostname string no01 d-i netcfg/get_hostname seen true d-i netcfg/get_domain string localdomain d-i netcfg/get_domain seen true d-i netcfg/choose_interface select auto ### Repositorio Debian ### d-i mirror/country string manual d-i mirror/http/hostname string deb.debian.org d-i mirror/http/directory string /debian d-i mirror/http/proxy string ### Usuario ### d-i passwd/root-password password cluster d-i passwd/root-password-again password cluster d-i passwd/user-fullname string Kluster User d-i passwd/username string kluster d-i passwd/user-password password cluster d-i passwd/user-password-again password cluster d-i passwd/user-default-groups string sudo ### Popularidade ### popularity-contest popularity-contest/participate boolean false ### Pre-carrega os modulos necessarios d-i anna-install string btrfs-modules xfs-modules ### Garante que o módulo btrfs está disponivel antes do particionamento d-i preseed/early_command string \ modprobe btrfs || true; \ modprobe xfs || true ### Configura o particionamento automatico d-i partman-auto/method string regular d-i partman-auto/choose_recipe select boot-root d-i partman-auto/expert_recipe string \ boot-root :: \ 40 50 512 ext4 \ $primary{ } $bootable{ } \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ /boot } . \ 4096 4096 4096 linux-swap \ $primary{ } \ method{ swap } format{ } . \ 51200 51200 51200 btrfs \ $primary{ } \ method{ format } format{ } \ use_filesystem{ } filesystem{ btrfs } \ mountpoint{ / } . \ 512 512 -1 xfs \ $primary{ } \ method{ format } format{ } \ use_filesystem{ } filesystem{ xfs } \ mountpoint{ /orangefs } . ### Confirma as acoes do particionador d-i partman-partitioning/confirm_write_new_label boolean true d-i partman/choose_partition select finish d-i partman/confirm boolean true d-i partman/confirm_nooverwrite boolean true ### Pacotes ### tasksel tasksel/first multiselect standard, ssh-server d-i pkgsel/include string sudo vim curl wget net-tools aptitude libu2f-udev console-setup keyboard-configuration console-data ### GRUB ### d-i grub-installer/bootdev string default ### Finalizacao ### d-i finish-install/reboot_in_progress note ### Comandos pos-instalacao ### d-i preseed/late_command string \ in-target bash -c 'echo "XKBMODEL=\"abnt2\"" > /etc/default/keyboard; \ echo "XKBLAYOUT=\"br\"" >> /etc/default/keyboard; \ echo "XKBVARIANT=\"abnt2\"" >> /etc/default/keyboard; \ echo "XKBOPTIONS=\"lv3:alt_switch,compose:rctrl\"" >> /etc/default/keyboard; \ echo "BACKSPACE=\"guess\"" >> /etc/default/keyboard'; \ in-target dpkg-reconfigure -f noninteractive keyboard-configuration; \ in-target setupcon --force; \ in-target update-initramfs -u; \ in-target bash -c 'set -e; \ apt-get clean || true; \ apt-get update || true; \ sed -i "s/^allow-hotplug/auto/" /etc/network/interfaces; \ update-grub || true; update-initramfs -u || true; \ mkdir -p /etc/sudoers.d; \ echo "kluster ALL=(ALL:ALL) ALL" > /etc/sudoers.d/kluster; \ chmod 0440 /etc/sudoers.d/kluster'

Nenhum comentário:

Postar um comentário