Установка и настройка PXE-сервера на Debian 13 (Trixie)

23 мин проверено на Debian 13 (Trixie)
Содержание
  1. Как это работает
  2. Что понадобится
  3. Шаг 1. Сеть на сервере
  4. Шаг 2. Интернет для клиентов (NAT)
  5. Шаг 3. Установка пакетов
  6. Шаг 4. DHCP-сервер
  7. Шаг 5. TFTP-сервер
  8. Шаг 6. HTTP-сервер
  9. Шаг 7. Файлы установщика Debian 13
  10. Шаг 8. Меню iPXE
  11. Шаг 9. Первая загрузка
  12. Шаг 10. Автоматическая установка (preseed)
  13. Шаг 11. Ubuntu 24.04 по сети
  14. Шаг 12. Windows 10 и 11 по сети (wimboot)
  15. 12.1. Файлы
  16. 12.2. Сетевая папка Samba
  17. 12.3. Сценарий запуска установки
  18. 12.4. Пункт в меню iPXE
  19. 12.5. Файл ответов autounattend.xml
  20. Проверка и диагностика
  21. Безопасность

PXE-сервер позволяет устанавливать операционные системы по сети: компьютер включается, получает адрес по DHCP, скачивает загрузчик и показывает меню — без флешек и дисков. В статье соберём такой сервер на Debian 13 (Trixie): он загружает компьютеры и с BIOS, и с UEFI, ставит Debian 13 вручную или полностью автоматически, а при желании — Ubuntu и Windows.

Все шаги проверены на стенде: Debian 13 в роли сервера и виртуальная машина в роли клиента. Скриншоты ниже — с этого стенда.

Как это работает

Загрузка идёт по цепочке, и на каждом шаге работает своя служба:

  1. DHCP (isc-dhcp-server) выдаёт клиенту IP-адрес и имя загрузочного файла — своё для BIOS и для UEFI.
  2. TFTP (tftpd-hpa) отдаёт этот файл — сетевой загрузчик iPXE.
  3. iPXE ещё раз спрашивает DHCP, получает адрес меню и скачивает его уже по HTTP (nginx) — это в десятки раз быстрее TFTP.
  4. Из меню по HTTP загружаются ядро и initrd установщика.
Клиент Что отдаёт DHCP
BIOS (Legacy) undionly.kpxe по TFTP
UEFI x64 snponly.efi по TFTP
Уже загрузившийся iPXE меню http://…/pxe/menu.ipxe

Третья строка важна: без неё iPXE после загрузки снова получит от DHCP имя undionly.kpxe, загрузит сам себя — и так по кругу.

Что понадобится

  • Сервер с Debian 13 и двумя сетевыми интерфейсами: один смотрит в обычную сеть с интернетом, второй — в отдельную сеть (или VLAN) для установки.
  • Клиентские компьютеры, подключённые к этой отдельной сети, с включённой загрузкой по сети (Network Boot / PXE) в BIOS/UEFI.

Впишите свои значения — они подставятся во все команды и конфиги ниже. «Подсеть» — первые три числа адресов PXE-сети: сервер получит адрес .1, клиенты — с .100 по .200.

192.168.2 — подсеть, enp2s0 — интерфейс в PXE-сети, enp1s0 — интерфейс с интернетом.

Шаг 1. Сеть на сервере

Посмотрите имена интерфейсов (в Debian 13 они вида enp1s0, а не eth0):

bash
ip -br link

Задайте статический адрес интерфейсу PXE-сети. В Debian 13 по умолчанию сетью управляет ifupdown:

/etc/network/interfaces.d/pxebash
auto enp2s0
iface enp2s0 inet static
    address 192.168.2.1/24
bash
sudo ifup enp2s0
ip -br addr show enp2s0

Шлюз на этом интерфейсе не указывайте: интернет у сервера идёт через enp1s0.

Шаг 2. Интернет для клиентов (NAT)

Установщику Debian нужен интернет — он скачивает пакеты с зеркала. Сервер будет раздавать интернет клиентам через свой внешний интерфейс.

Включите пересылку пакетов:

/etc/sysctl.d/90-pxe-forward.confbash
net.ipv4.ip_forward = 1
bash
sudo sysctl --system

Добавьте правило NAT в nftables (в Debian 13 nftables установлен по умолчанию):

/etc/nftables.confbash
#!/usr/sbin/nft -f
flush ruleset

table ip pxe_nat {
    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
        ip saddr 192.168.2.0/24 oifname "enp1s0" masquerade
    }
}
bash
sudo systemctl enable --now nftables
sudo nft list ruleset

Шаг 3. Установка пакетов

bash
sudo apt update
sudo apt install isc-dhcp-server tftpd-hpa tftp-hpa nginx ipxe whois wget
  • isc-dhcp-server — DHCP. Проект ISC DHCP больше не развивается (ему на смену пришёл Kea), но в Debian 13 он есть, стабилен и для PXE подходит отлично.
  • tftpd-hpa — TFTP-сервер, tftp-hpa — клиент для проверки.
  • ipxe — готовые загрузчики iPXE: /usr/lib/ipxe/undionly.kpxe для BIOS, /usr/lib/ipxe/snponly.efi и ipxe.efi для UEFI.
  • whois — в нём утилита mkpasswd, понадобится для автоматической установки.

Сразу после установки служба DHCP завершится с ошибкой — это нормально, она ещё не настроена.

Шаг 4. DHCP-сервер

Укажите, на каком интерфейсе работать:

/etc/default/isc-dhcp-serverbash
INTERFACESv4="enp2s0"
INTERFACESv6=""

Конфигурация:

/etc/dhcp/dhcpd.confbash
# Код опции 93 — архитектура клиента (RFC 4578): 0 = BIOS, 7 и 9 = UEFI x64
option arch code 93 = unsigned integer 16;

default-lease-time 600;
max-lease-time 7200;
authoritative;

subnet 192.168.2.0 netmask 255.255.255.0 {
    range 192.168.2.100 192.168.2.200;
    option routers 192.168.2.1;
    option domain-name-servers 77.88.8.8, 1.1.1.1;
    option broadcast-address 192.168.2.255;
    next-server 192.168.2.1;

    if exists user-class and option user-class = "iPXE" {
        # iPXE уже загружен — отдаём меню по HTTP (иначе загрузка пойдёт по кругу)
        filename "http://192.168.2.1/pxe/menu.ipxe";
    } elsif option arch = 00:07 or option arch = 00:09 {
        filename "snponly.efi";          # UEFI x64
    } else {
        filename "undionly.kpxe";        # BIOS (Legacy)
    }
}

next-server — адрес TFTP-сервера, filename — какой файл скачать. Проверьте конфиг и запустите службу:

bash
sudo dhcpd -t -cf /etc/dhcp/dhcpd.conf
sudo systemctl restart isc-dhcp-server
sudo systemctl status isc-dhcp-server --no-pager

dhcpd -t молчит, если ошибок нет, и показывает строку с ошибкой, если они есть.

Шаг 5. TFTP-сервер

/etc/default/tftpd-hpabash
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure"

--secure запрещает выходить за пределы /srv/tftp. Адрес 0.0.0.0 надёжнее конкретного IP: при загрузке сервера служба может стартовать раньше, чем поднимется интерфейс, и с конкретным адресом упадёт. Чтобы TFTP не был доступен из внешней сети, закройте порт 69/udp на enp1s0 в файрволе. Скопируйте загрузчики:

bash
sudo mkdir -p /srv/tftp
sudo cp /usr/lib/ipxe/undionly.kpxe /usr/lib/ipxe/snponly.efi /usr/lib/ipxe/ipxe.efi /srv/tftp/
sudo systemctl restart tftpd-hpa

Проверьте, что файл отдаётся:

консоль
$ tftp 192.168.2.1 -c get undionly.kpxe /tmp/test.kpxe
$ ls -l /tmp/test.kpxe

Шаг 6. HTTP-сервер

Отдельный сайт nginx для обращений по адресу PXE-сервера; к файлам пускает только клиентов PXE-сети:

/etc/nginx/sites-available/pxenginx
server {
    listen 80;
    server_name 192.168.2.1;
    root /var/www/html;

    location /pxe/ {
        allow 192.168.2.0/24;
        allow 127.0.0.1;
        deny all;
        autoindex on;
    }
}
bash
sudo mkdir -p /var/www/html/pxe
sudo ln -s /etc/nginx/sites-available/pxe /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Шаг 7. Файлы установщика Debian 13

Для загрузки по сети нужны файлы из netboot-архива, а не ядро и initrd с ISO-образа: initrd с netinst-ISO рассчитан на загрузку с CD и по сети остановится на ошибке «No CD-ROM detected».

bash
cd /tmp
wget https://deb.debian.org/debian/dists/trixie/main/installer-amd64/current/images/netboot/netboot.tar.gz
tar -xzf netboot.tar.gz ./debian-installer/amd64/linux ./debian-installer/amd64/initrd.gz
sudo mkdir -p /var/www/html/pxe/debian13
sudo cp debian-installer/amd64/linux debian-installer/amd64/initrd.gz /var/www/html/pxe/debian13/

Ядро весит около 12 МБ, initrd — около 40 МБ. После выхода новой точечной версии Debian (13.x) просто повторите эти команды — архив по ссылке current всегда свежий.

Шаг 8. Меню iPXE

/var/www/html/pxe/menu.ipxeipxe
#!ipxe
# Надписи на английском: консоль iPXE не показывает кириллицу
set server 192.168.2.1

:start
menu PXE boot menu - ${net0/mac} (${net0/ip})
item --gap -- ------------------------- Install -------------------------
item debian13      Install Debian 13 (Trixie)
item debian13auto  Install Debian 13 automatically (preseed)
item --gap -- -------------------------- Other --------------------------
item local         Boot from local disk
item shell         iPXE shell
item reboot        Reboot
choose --default local --timeout 15000 target && goto ${target}

:debian13
kernel http://${server}/pxe/debian13/linux initrd=initrd.gz vga=788 ---
initrd http://${server}/pxe/debian13/initrd.gz
boot || goto failed

:debian13auto
kernel http://${server}/pxe/debian13/linux initrd=initrd.gz auto=true priority=critical preseed/url=http://${server}/pxe/preseed.cfg locale=ru_RU.UTF-8 keymap=ru vga=788 ---
initrd http://${server}/pxe/debian13/initrd.gz
boot || goto failed

:local
# вернуть управление BIOS/UEFI — они загрузятся со следующего устройства (диска)
exit

:shell
echo Type "exit" to return to the menu
shell
goto start

:reboot
reboot

:failed
echo Boot failed, returning to the menu in 5 seconds
sleep 5
goto start

Что здесь важно:

  • initrd — отдельная команда после kernel, а initrd=initrd.gz в строке ядра нужен для UEFI: без него ядро в режиме UEFI не найдёт initrd.
  • По умолчанию через 15 секунд выбирается загрузка с диска. Так компьютер, у которого в BIOS первой стоит сеть, не переустановится сам по себе.
  • exit возвращает управление прошивке, и она грузится со следующего устройства. Это надёжнее, чем sanboot --drive 0x80, который на части машин заканчивается ошибкой ввода-вывода.
  • Синтаксис подстановок iPXE — только ${имя}: конструкции вроде ${hostname:-…} из shell он не понимает и выведет как есть.

Шаг 9. Первая загрузка

На клиенте включите в BIOS/UEFI загрузку по сети (обычно пункт Network Boot, PXE Boot или «Сетевой стек») и поставьте сеть первой в порядке загрузки — или выберите её разово в меню загрузки (F12, F11 или F8 в зависимости от производителя).

Клиент получит адрес, загрузит iPXE и покажет меню:

Меню iPXE на клиенте с BIOS
Меню загрузки: клиент получил адрес 192.168.2.100

После выбора первого пункта ядро и initrd скачаются по HTTP за пару секунд, и запустится обычный установщик Debian 13:

Установщик Debian 13, загруженный по сети
Установщик Debian 13 запущен по сети

Шаг 10. Автоматическая установка (preseed)

Preseed-файл отвечает на все вопросы установщика заранее: компьютер ставит систему сам и перезагружается.

Сначала получите хеш пароля для пользователя — открытый пароль в файле хранить не нужно:

консоль
$ mkpasswd -m sha-512
Password:

Скопируйте строку целиком и вставьте её вместо ВАШ_ХЕШ в файл ниже.

/var/www/html/pxe/preseed.cfgbash
# Автоматическая установка Debian 13 (Trixie)

### Язык, страна, клавиатура
d-i debian-installer/locale string ru_RU.UTF-8
d-i debian-installer/language string ru
d-i debian-installer/country string RU
d-i keyboard-configuration/xkb-keymap select ru
d-i keyboard-configuration/toggle select Alt+Shift

### Сеть
d-i netcfg/choose_interface select auto
d-i netcfg/get_hostname string debian
d-i netcfg/get_domain string local
d-i netcfg/hostname string debian-pxe

### Зеркало
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

### Пользователи: root без пароля (вход через sudo), пользователь sysadmin
d-i passwd/root-login boolean false
d-i passwd/user-fullname string System Administrator
d-i passwd/username string sysadmin
d-i passwd/user-password-crypted password ВАШ_ХЕШ

### Время
d-i clock-setup/utc boolean true
d-i time/zone string Europe/Moscow
d-i clock-setup/ntp boolean true

### Разметка: весь первый диск, один раздел + swap. Диск будет стёрт без вопросов
d-i partman-auto/method string regular
d-i partman-auto/choose_recipe select atomic
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

### Репозитории и пакеты
d-i apt-setup/non-free-firmware boolean true
tasksel tasksel/first multiselect standard, ssh-server
d-i pkgsel/include string sudo curl
d-i pkgsel/upgrade select full-upgrade
popularity-contest popularity-contest/participate boolean false

### Загрузчик
d-i grub-installer/only_debian boolean true
d-i grub-installer/bootdev string default

### Завершение: перезагрузиться без вопроса
d-i finish-install/reboot_in_progress note

Параметры в строке ядра (пункт debian13auto в меню) делают вот что:

Параметр Зачем
auto=true откладывает вопросы о языке и клавиатуре до загрузки preseed-файла
priority=critical не задавать вопросов, на которые есть ответ по умолчанию
preseed/url=… откуда скачать ответы
locale=ru_RU.UTF-8 keymap=ru язык и раскладка ещё до того, как скачается preseed

Выберите в меню пункт «Install Debian 13 automatically» — дальше установщик работает сам, на русском и без единого вопроса: скачивает компоненты с зеркала через NAT, размечает диск, ставит систему и перезагружается.

Автоматическая установка Debian 13 по сети
Установщик сам скачивает компоненты — вопросов не задаёт

Шаг 11. Ubuntu 24.04 по сети

Ubuntu Server загружается иначе, чем Debian: установщик (Subiquity) скачивает весь ISO-образ в оперативную память, поэтому клиенту нужно не меньше 4 ГБ ОЗУ. Preseed Ubuntu не понимает — у неё свой формат автоустановки (autoinstall).

bash
cd /var/www/html/pxe
sudo mkdir -p ubuntu2404
sudo wget -O ubuntu2404/ubuntu-24.04-live-server-amd64.iso \
  https://releases.ubuntu.com/24.04/ubuntu-24.04.5-live-server-amd64.iso
sudo mount -o loop,ro ubuntu2404/ubuntu-24.04-live-server-amd64.iso /mnt
sudo cp /mnt/casper/vmlinuz /mnt/casper/initrd ubuntu2404/
sudo umount /mnt

Номер точечной версии (24.04.5) проверьте на releases.ubuntu.com/24.04 — старые образы со временем удаляют.

Добавьте в меню пункт и его раздел:

фрагмент menu.ipxeipxe
item ubuntu2404    Install Ubuntu 24.04 Server

:ubuntu2404
kernel http://${server}/pxe/ubuntu2404/vmlinuz initrd=initrd ip=dhcp url=http://${server}/pxe/ubuntu2404/ubuntu-24.04-live-server-amd64.iso cloud-config-url=/dev/null ---
initrd http://${server}/pxe/ubuntu2404/initrd
boot || goto failed

Строку item поставьте в начало меню рядом с пунктами Debian, а раздел :ubuntu2404 — в любое место после choose.

  • ip=dhcp — initrd Ubuntu сам получает адрес, чтобы скачать образ.
  • url= — откуда скачать ISO целиком в память.
  • cloud-config-url=/dev/null — без него cloud-init тоже примет url= за адрес своих настроек и скачает 3-гигабайтный образ второй раз.

Шаг 12. Windows 10 и 11 по сети (wimboot)

Windows загружается через wimboot — загрузчик проекта iPXE, который запускает среду установки WinPE прямо из boot.wim. Сама программа установки берёт файлы системы с сетевой папки Samba, поэтому понадобятся ещё Samba и wimtools.

12.1. Файлы

bash
sudo apt install samba wimtools
sudo mkdir -p /var/www/html/pxe/windows /srv/windows/win11
sudo wget -O /var/www/html/pxe/windows/wimboot https://github.com/ipxe/wimboot/releases/latest/download/wimboot

Скопируйте содержимое ISO-образа Windows целиком — оно нужно программе установки:

bash
sudo mount -o loop,ro Win11_Russian_x64.iso /mnt
sudo cp -r /mnt/. /srv/windows/win11/
sudo umount /mnt

Загрузочные файлы WinPE nginx будет отдавать по HTTP, а Samba — остальное. Чтобы не хранить две копии, сделайте ссылку:

bash
sudo ln -s /srv/windows/win11 /var/www/html/pxe/windows/win11

Узнайте номер нужной редакции в образе — он понадобится в файле ответов:

консоль
$ wiminfo /srv/windows/win11/sources/install.wim | grep -E "^(Index|Name)"
Index:                  1
Name:                   Windows 11 Домашняя
…
Index:                  6

12.2. Сетевая папка Samba

Гостевой доступ без пароля современные версии Windows 11 блокируют, поэтому заведём отдельного пользователя только для установки:

bash
sudo useradd -M -s /usr/sbin/nologin pxe
sudo smbpasswd -a pxe

Папка только для чтения, доступ только из PXE-сети:

/etc/samba/smb.conf (добавить в конец)ini
[windows]
    path = /srv/windows
    read only = yes
    valid users = pxe
    hosts allow = 192.168.2. 127.
bash
sudo testparm -s >/dev/null && sudo systemctl restart smbd
smbclient //localhost/windows -U pxe -c ls

Последняя команда спросит пароль и покажет содержимое папки — значит, всё работает.

12.3. Сценарий запуска установки

wimboot умеет подкладывать файлы прямо в загружаемую среду WinPE. Подложим два файла: winpeshl.ini говорит WinPE, что запустить вместо оболочки, а install.bat подключает сетевую папку и запускает установку.

/var/www/html/pxe/windows/winpeshl.iniini
[LaunchApps]
"install.bat"
/var/www/html/pxe/windows/install.batcmd
wpeinit
net use \\192.168.2.1\windows /user:pxe ПАРОЛЬ_PXE
\\192.168.2.1\windows\win11\setup.exe /unattend:\\192.168.2.1\windows\autounattend.xml

wpeinit поднимает сеть в WinPE, без него net use не найдёт сервер. Пароль пользователя pxe здесь хранится открыто, поэтому этот пользователь ничего не умеет, кроме чтения папки с дистрибутивом.

12.4. Пункт в меню iPXE

фрагмент menu.ipxeipxe
item win11         Install Windows 11

:win11
set win http://${server}/pxe/windows
kernel ${win}/wimboot
initrd ${win}/winpeshl.ini winpeshl.ini
initrd ${win}/install.bat  install.bat
initrd ${win}/win11/boot/bcd        BCD
initrd ${win}/win11/boot/boot.sdi   boot.sdi
initrd ${win}/win11/sources/boot.wim boot.wim
boot || goto failed

Второе имя в каждой строке initrd — имя файла внутри WinPE. Пути boot/bcd и boot/boot.sdi берутся с образа как есть; wimboot работает и в BIOS, и в UEFI.

12.5. Файл ответов autounattend.xml

Файл можно собрать в Windows System Image Manager из комплекта Windows ADK, но проще взять готовый и поправить три места: номер редакции, имя пользователя и пароль. Пример ниже — для компьютеров с UEFI: диск 0 размечается в GPT (раздел EFI, служебный MSR и раздел Windows).

/srv/windows/autounattend.xmlxml
<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
  <settings pass="windowsPE">
    <component name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
      <SetupUILanguage><UILanguage>ru-RU</UILanguage></SetupUILanguage>
      <InputLocale>0409:00000409;0419:00000419</InputLocale>
      <SystemLocale>ru-RU</SystemLocale>
      <UILanguage>ru-RU</UILanguage>
      <UserLocale>ru-RU</UserLocale>
    </component>
    <component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
      <RunSynchronous>
        <!-- Обход проверок TPM, Secure Boot и ОЗУ для Windows 11 (удалите, если не нужно) -->
        <RunSynchronousCommand wcm:action="add"><Order>1</Order><Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassTPMCheck /t REG_DWORD /d 1 /f</Path></RunSynchronousCommand>
        <RunSynchronousCommand wcm:action="add"><Order>2</Order><Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassSecureBootCheck /t REG_DWORD /d 1 /f</Path></RunSynchronousCommand>
        <RunSynchronousCommand wcm:action="add"><Order>3</Order><Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassRAMCheck /t REG_DWORD /d 1 /f</Path></RunSynchronousCommand>
      </RunSynchronous>
      <DiskConfiguration>
        <Disk wcm:action="add">
          <DiskID>0</DiskID>
          <WillWipeDisk>true</WillWipeDisk>
          <CreatePartitions>
            <CreatePartition wcm:action="add"><Order>1</Order><Type>EFI</Type><Size>300</Size></CreatePartition>
            <CreatePartition wcm:action="add"><Order>2</Order><Type>MSR</Type><Size>16</Size></CreatePartition>
            <CreatePartition wcm:action="add"><Order>3</Order><Type>Primary</Type><Extend>true</Extend></CreatePartition>
          </CreatePartitions>
          <ModifyPartitions>
            <ModifyPartition wcm:action="add"><Order>1</Order><PartitionID>1</PartitionID><Format>FAT32</Format><Label>EFI</Label></ModifyPartition>
            <ModifyPartition wcm:action="add"><Order>2</Order><PartitionID>3</PartitionID><Format>NTFS</Format><Label>Windows</Label><Letter>C</Letter></ModifyPartition>
          </ModifyPartitions>
        </Disk>
      </DiskConfiguration>
      <ImageInstall>
        <OSImage>
          <InstallFrom>
            <MetaData wcm:action="add"><Key>/IMAGE/INDEX</Key><Value>6</Value></MetaData>
          </InstallFrom>
          <InstallTo><DiskID>0</DiskID><PartitionID>3</PartitionID></InstallTo>
        </OSImage>
      </ImageInstall>
      <UserData>
        <AcceptEula>true</AcceptEula>
        <ProductKey><WillShowUI>OnError</WillShowUI></ProductKey>
      </UserData>
    </component>
  </settings>
  <settings pass="oobeSystem">
    <component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
      <InputLocale>0409:00000409;0419:00000419</InputLocale>
      <SystemLocale>ru-RU</SystemLocale>
      <UILanguage>ru-RU</UILanguage>
      <UserLocale>ru-RU</UserLocale>
    </component>
    <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
      <TimeZone>Russian Standard Time</TimeZone>
      <OOBE>
        <HideEULAPage>true</HideEULAPage>
        <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
        <HideOnlineAccountScreens>true</HideOnlineAccountScreens>
        <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
        <ProtectYourPC>3</ProtectYourPC>
      </OOBE>
      <UserAccounts>
        <LocalAccounts>
          <LocalAccount wcm:action="add">
            <Name>admin</Name>
            <Group>Administrators</Group>
            <Password><Value>Смените-Этот-Пароль1</Value><PlainText>true</PlainText></Password>
          </LocalAccount>
        </LocalAccounts>
      </UserAccounts>
    </component>
  </settings>
</unattend>

Что поменять под себя:

  • /IMAGE/INDEX — номер редакции из вывода wiminfo (в примере 6 — Windows 11 Pro).
  • Name и Password локального администратора. Пароль в файле хранится открыто, поэтому папка доступна только из PXE-сети; после установки смените его.
  • Ключ продукта не указан: Windows установится и попросит активацию позже. Если программа установки всё же остановится на вводе ключа, впишите в <ProductKey><Key>…</Key></ProductKey> свой ключ или общедоступный ключ установки для вашей редакции — он есть в документации Microsoft («Generic product keys» / ключи для установки) и только выбирает редакцию, а не активирует Windows.
  • Часовой пояс Russian Standard Time — это Москва (UTC+3).

Проверка и диагностика

Состояние служб:

bash
systemctl status isc-dhcp-server tftpd-hpa nginx --no-pager
sudo ss -ulpn | grep -E ':67|:69'

Лучший инструмент диагностики — смотреть сеть во время загрузки клиента:

bash
sudo tcpdump -ni enp2s0 port 67 or port 68 or port 69

В журнале DHCP видно, кому и какой адрес выдан:

bash
sudo journalctl -u isc-dhcp-server -f
текст
DHCPDISCOVER from 52:54:00:12:34:01 via enp2s0
DHCPOFFER on 192.168.2.100 to 52:54:00:12:34:01 via enp2s0
DHCPREQUEST for 192.168.2.100 (192.168.2.1) from 52:54:00:12:34:01 via enp2s0
DHCPACK on 192.168.2.100 to 52:54:00:12:34:01 via enp2s0

Частые ошибки:

Что видно на клиенте Причина и решение
PXE-E53: No boot filename received DHCP не отдал filename: проверьте dhcpd.conf и что запрос пришёл именно на ваш сервер (tcpdump)
PXE-E32: TFTP open timeout TFTP не отвечает: служба tftpd-hpa, адрес в TFTP_ADDRESS, файл лежит в /srv/tftp
Меню мелькает и загрузка начинается заново нет условия user-class = "iPXE" — iPXE получает сам себя по кругу
Secure Boot Violation Secure Boot включён, а загрузчик не подписан — отключите Secure Boot
Установщик Debian пишет No CD-ROM detected взяты ядро и initrd с ISO вместо netboot-архива (шаг 7)
Установщик не может скачать пакеты у клиентов нет интернета — проверьте NAT (шаг 2): sudo nft list ruleset, sysctl net.ipv4.ip_forward
Клиент получает адрес из другой сети в сети есть второй DHCP-сервер (роутер) — нужна отдельная сеть для PXE
Автоустановка остановилась на «зарезервированное имя пользователя» в preseed указано системное имя (admin, root, daemon и т. п.) — выберите другое

Безопасность

  • PXE-сеть — отдельная: в ней работает свой DHCP и отдаётся preseed с хешем пароля.
  • nginx пускает к /pxe/ только PXE-сеть, Samba-папка — только чтение, отдельный пользователь и тоже только для PXE-сети.
  • Порты DHCP (67/udp), TFTP (69/udp) и Samba закройте на внешнем интерфейсе enp1s0.
  • По умолчанию меню загружает компьютер с диска: случайная переустановка исключена.
  • Пароли в preseed храните хешем (mkpasswd), а в autounattend.xml — меняйте после установки.
Статья помогла?

Нашли ошибку или устаревшую команду? Выделите текст и нажмите Ctrl+Enter.

Комментарии

Комментариев пока нет.

Код можно выделять `обратными кавычками`. Комментарии проверяются перед публикацией.