Post

Criação de Imagem Debian com Packer e Preseed

Criação de Imagem Debian com Packer e Preseed

Nota: Este tutorial é o terceiro de uma série de 6 tutoriais sobre criação de imagens QEMU/KVM com Packer. Se você ainda não leu os tutoriais anteriores sobre os fundamentos do Packer e a criação de imagens Oracle Linux, recomendamos que o faça antes de prosseguir. Criação de Imagem Oracle Linux com Packer e Kickstart.

Introdução

Nos tutoriais anteriores, exploramos os fundamentos do Packer e QEMU/KVM e aprendemos a criar uma imagem automatizada do Oracle Linux usando Kickstart. Agora, vamos avançar para a criação de uma imagem do Debian 12 (Bookworm) utilizando o método Preseed para automação da instalação.

O Debian é uma das distribuições Linux mais estáveis e amplamente utilizadas, servindo como base para muitas outras distribuições, incluindo o Ubuntu. Sua filosofia de software livre e estabilidade o torna uma excelente escolha para servidores e ambientes de produção.

Neste tutorial, vamos:

  1. Entender o que é o Preseed e como ele funciona
  2. Criar um arquivo Preseed personalizado para Debian 12
  3. Configurar o Packer para utilizar o Preseed
  4. Adicionar scripts de provisionamento para personalização
  5. Construir e validar a imagem final

O que é Preseed?

Preseed é o sistema de automação de instalação do Debian, similar ao Kickstart usado no Red Hat/Oracle Linux. Ele permite automatizar completamente o processo de instalação, fornecendo respostas pré-definidas para todas as perguntas que normalmente seriam feitas durante uma instalação manual.

Um arquivo Preseed contém configurações para:

  • Localização e idioma
  • Configuração de rede
  • Configuração de usuários e senhas
  • Particionamento de disco
  • Seleção de pacotes
  • Configurações de boot
  • Scripts de pós-instalação

Vantagens do Preseed

  • Automação completa: Elimina a necessidade de intervenção manual
  • Flexibilidade: Permite personalização detalhada da instalação
  • Reprodutibilidade: Garante instalações idênticas a cada vez
  • Integração: Funciona perfeitamente com ferramentas como o Packer
  • Documentação extensa: Bem documentado na wiki do Debian

Preparando o Ambiente

Vamos preparar nosso ambiente de trabalho para este tutorial:

1
2
3
4
5
6
# Criar diretório para o terceiro tutorial
mkdir -p ~/packer-kvm-tutorial/tutorial3
cd ~/packer-kvm-tutorial/tutorial3

# Criar subdiretórios necessários
mkdir -p http scripts build/os-base

Criando o Arquivo Preseed

O arquivo Preseed é o coração da nossa automação. Vamos criar um arquivo preseed.cfg no diretório http que será servido via HTTP durante a instalação:

1
nano http/preseed.cfg

Adicione o seguinte conteúdo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# Definindo o idioma como português do Brasil
d-i debian-installer/locale string pt_BR.UTF-8

# Teclado para layout brasileiro
d-i keyboard-configuration/xkb-keymap select br

# Locales adicionais
d-i localechooser/supported-locales multiselect pt_BR.UTF-8, en_US.UTF-8

### Network configuration
d-i netcfg/choose_interface select auto
d-i netcfg/get_hostname string packer
d-i netcfg/get_domain string local

### Mirror settings
d-i mirror/country string BR
d-i mirror/http/hostname string deb.debian.org
d-i mirror/http/directory string /debian
d-i mirror/http/proxy string

### Account setup
# Senha root e usuário padrão
d-i passwd/root-password password packer
d-i passwd/root-password-again password packer
d-i passwd/user-fullname string Packer
d-i passwd/username string packer
d-i passwd/user-password password packer
d-i passwd/user-password-again password packer

# Fuso horário do Brasil
d-i time/zone string America/Sao_Paulo
d-i clock-setup/utc boolean true

# Particionamento Automático - LVM
d-i partman-auto/disk string /dev/vda
d-i partman-auto/method string lvm
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-md/device_remove_md boolean true
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true

# Forçar o particionamento e gravação no disco sem confirmação
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true

### Base system installation
d-i base-installer/install-recommends boolean false

# Definindo para usar atualização completa após a instalação
d-i pkgsel/upgrade select full-upgrade

# Escolha de pacotes
tasksel tasksel/first multiselect SSH server
d-i pkgsel/include string openssh-server sudo

### Boot loader installation
d-i grub-installer/only_debian boolean true
d-i grub-installer/with_other_os boolean true
d-i grub-installer/bootdev string default

### Finishing up the installation
d-i finish-install/reboot_in_progress note

# Comando de finalização
d-i preseed/late_command string echo 'packer ALL = (root) NOPASSWD: ALL' > /target/etc/sudoers.d/packer; chmod 440 /target/etc/sudoers.d/packer

Vamos analisar as principais seções deste arquivo Preseed:

Configurações Básicas

  • debian-installer/locale string pt_BR.UTF-8: Define o idioma como português do Brasil
  • keyboard-configuration/xkb-keymap select br: Define o layout de teclado como brasileiro
  • time/zone string America/Sao_Paulo: Define o fuso horário para São Paulo

Configuração de Rede

  • netcfg/choose_interface select auto: Seleciona automaticamente a interface de rede
  • netcfg/get_hostname string packer: Define o hostname como “packer”

Configuração de Espelho (Mirror)

  • mirror/country string BR: Seleciona espelhos do Brasil
  • mirror/http/hostname string deb.debian.org: Define o servidor espelho principal

Configuração de Usuários

  • passwd/root-password password packer: Define a senha do root
  • passwd/username string packer: Cria um usuário chamado “packer”
  • passwd/user-password password packer: Define a senha do usuário

Particionamento

  • partman-auto/method string lvm: Usa LVM para particionamento
  • partman-auto/disk string /dev/vda: Usa o disco vda (padrão para QEMU/KVM)

Seleção de Pacotes

  • tasksel/first multiselect SSH server: Instala o servidor SSH
  • pkgsel/include string openssh-server sudo: Instala pacotes adicionais

Comando de Finalização

  • preseed/late_command: Executa comandos após a instalação, neste caso configurando o sudo para o usuário packer

Criando o Script de Limpeza

Agora, vamos criar um script de limpeza que será executado após a instalação para otimizar a imagem:

1
nano scripts/cleanup.sh

Adicione o seguinte conteúdo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/bin/bash -eux

# Atualizar o sistema
apt-get update
apt-get -y upgrade

# Instalar pacotes essenciais
apt-get -y install cloud-init qemu-guest-agent

# Configurar cloud-init para NoCloud
cat > /etc/cloud/cloud.cfg.d/99-nocloud.cfg << EOF
datasource_list: [ NoCloud, None ]
EOF

# Limpar pacotes não necessários
apt-get -y autoremove
apt-get -y clean

# Limpar logs e arquivos temporários
find /var/log -type f -exec truncate --size=0 {} \;
rm -rf /tmp/*
rm -rf /var/tmp/*

# Remover informações específicas da máquina
truncate -s 0 /etc/machine-id
rm -f /etc/ssh/*key*
rm -f ~/.bash_history

# Limpar histórico de apt
rm -f /var/lib/apt/lists/*

# Zerar espaço livre
fstrim -av

Este script realiza várias tarefas importantes:

  1. Atualiza o sistema e instala pacotes essenciais (cloud-init, qemu-guest-agent)
  2. Configura o cloud-init para usar o datasource NoCloud
  3. Remove pacotes desnecessários e limpa caches
  4. Remove logs e arquivos temporários
  5. Remove identificadores únicos da máquina (machine-id, chaves SSH)
  6. Executa fstrim para otimizar o espaço em disco

Torne o script executável:

1
chmod +x scripts/cleanup.sh

Criando o Arquivo Packer

Agora, vamos criar o arquivo Packer que utilizará o Preseed e o script de limpeza:

1
nano debian12-kvm.pkr.hcl

Adicione o seguinte conteúdo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
packer {
  required_version = ">= 1.10.0" 
  required_plugins {
    qemu = {
      version = "= 1.1.0"
      source  = "github.com/hashicorp/qemu"
    }
  }
}

variable "vm_name" {
  default = "debian-12-amd64.raw"
}

variable "disk_size" {
  default = "16384"
}

variable "iso_url" {
  default = "https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-12.5.0-amd64-netinst.iso"
}

variable "iso_checksum" {
  default = "013f5b44670d81280b5b1bc02455842b247951bf8ba45f6.."
}

source "qemu" "iso" {
  vm_name          = var.vm_name 
  iso_url          = var.iso_url
  iso_checksum     = var.iso_checksum
  disk_size        = var.disk_size
  memory           = 2048
  disk_image       = false
  output_directory = "build/os-base"
  accelerator      = "kvm"
  disk_interface   = "virtio"
  format           = "raw"
  net_device       = "virtio-net"
  boot_wait        = "5s"
  boot_command = [
    "<esc><wait>",
    "install <wait>",
    "preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg <wait>",
    "debian-installer=pt_BR.UTF-8 <wait>",
    "auto <wait>",
    "locale=pt_BR.UTF-8 <wait>",
    "kbd-chooser/method=br <wait>",
    "keyboard-configuration/xkb-keymap=br <wait>",
    "netcfg/get_hostname=packer <wait>",
    "netcfg/get_domain=local <wait>",
    "fb=false <wait>",
    "debconf/frontend=noninteractive <wait>",
    "console-setup/ask_detect=false <wait>",
    "console-keymaps-at/keymap=br <wait>",
    "<enter><wait>"
  ]
  http_directory   = "http"
  cpu_model        = "host"
  shutdown_command = "echo 'packer' | sudo -S shutdown -P now"
  ssh_username     = "packer"
  ssh_password     = "packer"
  ssh_timeout      = "60m"
}

build {
  sources = ["source.qemu.iso"]

  # Envia o script de limpeza para a VM
  provisioner "file" {
    source      = "scripts/cleanup.sh"          
    destination = "/tmp/cleanup.sh"      
  }

  # Executa o script de limpeza na VM
  provisioner "shell" {
    inline = [
      "chmod +x /tmp/cleanup.sh",
      "echo 'packer' | sudo -S /tmp/cleanup.sh" 
    ]
  }
}

Vamos analisar as partes importantes deste arquivo:

Variáveis

  • vm_name: Nome do arquivo de imagem resultante
  • disk_size: Tamanho do disco em MB (16GB neste caso)
  • iso_url: URL da ISO do Debian 12
  • iso_checksum: Checksum da ISO para verificação

Configuração QEMU

  • memory: 2GB de RAM para a VM
  • accelerator: Usa KVM para melhor desempenho
  • disk_interface e net_device: Usa dispositivos virtio para melhor desempenho
  • format: Formato raw para a imagem resultante

Boot Command

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
boot_command = [
  "<esc><wait>",
  "install <wait>",
  "preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg <wait>",
  "debian-installer=pt_BR.UTF-8 <wait>",
  "auto <wait>",
  "locale=pt_BR.UTF-8 <wait>",
  "kbd-chooser/method=br <wait>",
  "keyboard-configuration/xkb-keymap=br <wait>",
  "netcfg/get_hostname=packer <wait>",
  "netcfg/get_domain=local <wait>",
  "fb=false <wait>",
  "debconf/frontend=noninteractive <wait>",
  "console-setup/ask_detect=false <wait>",
  "console-keymaps-at/keymap=br <wait>",
  "<enter><wait>"
]

Esta sequência de comandos:

  1. Pressiona ESC para acessar o menu de boot
  2. Inicia a instalação com vários parâmetros:
    • preseed/url: Aponta para nosso arquivo Preseed
    • debian-installer=pt_BR.UTF-8: Define o idioma do instalador
    • auto: Ativa o modo automático
    • Várias outras configurações de localização e teclado
  3. Pressiona Enter para iniciar a instalação

Provisionadores

1
2
3
4
5
6
7
8
9
10
11
12
13
# Envia o script de limpeza para a VM
provisioner "file" {
  source      = "scripts/cleanup.sh"          
  destination = "/tmp/cleanup.sh"      
}

# Executa o script de limpeza na VM
provisioner "shell" {
  inline = [
    "chmod +x /tmp/cleanup.sh",
    "echo 'packer' | sudo -S /tmp/cleanup.sh" 
  ]
}

Estes provisionadores:

  1. Copiam o script de limpeza para a VM
  2. Tornam o script executável
  3. Executam o script com privilégios sudo

Construindo a Imagem

Agora que temos todos os arquivos necessários, vamos construir nossa imagem:

1
2
3
4
5
6
7
8
# Inicializar o Packer (baixa os plugins necessários)
packer init .

# Validar a configuração
packer validate debian12-kvm.pkr.hcl

# Construir a imagem (com logs detalhados)
PACKER_LOG=1 packer build debian12-kvm.pkr.hcl

Este processo pode levar algum tempo, pois o Packer irá:

  1. Baixar a ISO do Debian (se ainda não estiver em cache)
  2. Iniciar uma VM QEMU/KVM
  3. Inicializar a instalação com o Preseed
  4. Aguardar a conclusão da instalação
  5. Conectar-se via SSH
  6. Executar os provisionadores
  7. Desligar a VM
  8. Empacotar a imagem resultante

Verificando a Imagem Gerada

Após a conclusão do build, você terá uma imagem raw no diretório build/os-base:

1
ls -lh build/os-base/

Você deve ver um arquivo como debian-12-amd64.raw.

Convertendo para QCOW2 (Opcional)

O formato raw é ótimo para desempenho, mas o formato QCOW2 oferece recursos adicionais como compressão e snapshots. Para converter a imagem:

1
qemu-img convert -O qcow2 -c build/os-base/debian-12-amd64.raw debian-12-amd64.qcow2

Testando a Imagem

Para testar a imagem, você pode iniciar uma VM usando o QEMU diretamente:

1
2
3
4
5
6
7
8
9
10
qemu-system-x86_64 \
  -name "Test-Debian12" \
  -machine type=q35,accel=kvm \
  -cpu host \
  -m 2048 \
  -drive file=build/os-base/debian-12-amd64.raw,format=raw,if=virtio \
  -net nic,model=virtio \
  -net user,hostfwd=tcp::2222-:22 \
  -display none \
  -daemonize

Conecte-se à VM via SSH:

1
ssh -p 2222 packer@localhost

Diferenças entre Preseed e Kickstart

Agora que já trabalhamos com Kickstart (Oracle Linux) e Preseed (Debian), vamos destacar algumas diferenças importantes:

Sintaxe

  • Kickstart: Usa uma sintaxe baseada em comandos com seções específicas (como %packages, %post)
  • Preseed: Usa uma sintaxe de pares chave-valor com prefixos de domínio (como d-i, tasksel)

Flexibilidade

  • Kickstart: Oferece scripts pré e pós-instalação mais flexíveis
  • Preseed: Mais detalhado nas opções de configuração do instalador

Integração

  • Kickstart: Integrado diretamente ao instalador Anaconda
  • Preseed: Integrado ao debian-installer

Complexidade

  • Kickstart: Geralmente mais simples e direto
  • Preseed: Pode ser mais complexo devido ao grande número de opções disponíveis

Personalizações Adicionais

Vamos explorar algumas personalizações adicionais que você pode fazer no arquivo Preseed:

Particionamento Avançado

Para um particionamento mais detalhado com LVM:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Particionamento avançado com LVM
d-i partman-auto/expert_recipe string                         \
      boot-root ::                                            \
              500 10000 1000 ext4                             \
                      $primary{ } $bootable{ }                \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ ext4 }    \
                      mountpoint{ /boot }                     \
              .                                               \
              6000 10000 10000 ext4                           \
                      $lvmok{ }                               \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ ext4 }    \
                      mountpoint{ / }                         \
              .                                               \
              2000 10000 3000 ext4                            \
                      $lvmok{ }                               \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ ext4 }    \
                      mountpoint{ /var }                      \
              .                                               \
              2000 10000 2000 linux-swap                      \
                      $lvmok{ }                               \
                      method{ swap } format{ }                \
              .

Configuração de Rede Avançada

Para configuração de rede estática:

1
2
3
4
5
6
7
# Configuração de rede estática
d-i netcfg/disable_autoconfig boolean true
d-i netcfg/get_ipaddress string 192.168.1.42
d-i netcfg/get_netmask string 255.255.255.0
d-i netcfg/get_gateway string 192.168.1.1
d-i netcfg/get_nameservers string 8.8.8.8
d-i netcfg/confirm_static boolean true

Instalação de Pacotes Adicionais

Para instalar mais pacotes:

1
2
# Pacotes adicionais
d-i pkgsel/include string openssh-server sudo vim git curl wget htop net-tools

Configurações Avançadas de APT

Para configurar repositórios adicionais:

1
2
3
# Configurar repositórios adicionais
d-i apt-setup/local0/repository string http://deb.debian.org/debian bookworm-backports main
d-i apt-setup/local0/comment string Debian Backports

Comandos de Finalização Avançados

Para executar comandos mais complexos após a instalação:

1
2
3
4
5
6
7
8
# Comandos de finalização avançados
d-i preseed/late_command string \
    in-target apt-get update; \
    in-target apt-get -y install cloud-init; \
    echo 'packer ALL = (root) NOPASSWD: ALL' > /target/etc/sudoers.d/packer; \
    chmod 440 /target/etc/sudoers.d/packer; \
    in-target systemctl enable qemu-guest-agent; \
    in-target sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config;

Exercícios Práticos

Para fixar o conhecimento adquirido neste tutorial, tente os seguintes exercícios:

  1. Modifique o arquivo Preseed para instalar um ambiente de desktop mínimo (como XFCE)
  2. Altere o particionamento para criar partições separadas para /, /var, /home e swap
  3. Adicione configurações para instalar e configurar o firewall (ufw)
  4. Crie uma variável adicional no arquivo Packer para permitir a escolha entre Debian 11 e 12

Solução de Problemas Comuns

A instalação não inicia com o Preseed

Verifique:

  • Se o boot_command está correto e completo
  • Se o arquivo Preseed está no diretório http
  • Se há erros de sintaxe no arquivo Preseed

Timeout de SSH

Se o Packer não conseguir se conectar via SSH:

  • Aumente o valor de ssh_timeout
  • Verifique se o usuário e senha no Preseed correspondem aos definidos no Packer
  • Verifique se o SSH está instalado e habilitado no Preseed

Erros no script de limpeza

Se o script de limpeza falhar:

  • Verifique permissões do script
  • Verifique se todos os comandos são compatíveis com Debian 12
  • Tente executar os comandos manualmente para identificar o problema

Conclusão

Neste tutorial, aprendemos a criar uma imagem automatizada do Debian 12 usando Packer e Preseed. Exploramos:

  1. Como criar um arquivo Preseed para automação da instalação
  2. Como configurar o Packer para usar o Preseed
  3. Como adicionar scripts de provisionamento para personalização
  4. Como construir e validar a imagem final
  5. As diferenças entre Preseed e Kickstart

Esta abordagem permite criar imagens padronizadas e reproduzíveis do Debian, ideais para ambientes de produção, desenvolvimento ou testes.

No próximo tutorial, vamos explorar a criação de imagens para Ubuntu usando o método Cloud-init, que oferece uma abordagem mais moderna para automação de instalações.

Referências

This post is licensed under CC BY 4.0 by the author.