Serveur iPXE ou comment booter sans USB/CD/whatever
Serveur iPXE ou comment booter sans USB/CD/whatever
Avant, quand je voulais (ré)installer une machine, je gravais un CD (bien personnalisé à coup de mkisofs). Ensuite, je suis passé aux clés USB.
Mais c’est toujours pénible :
- Il faut retrouver un média de libre
- Il faut construire une image
- Il faut graver/flasher l’image sur le média
- Booter sur le device
- Et quand ça ne fonctionne pas, repasser par la case construire l’image
Bref, ce n’est pas pratique.
On va donc passer à quelque chose de moderne comme (i)PXE.
Un peu de lecture pour comprendre ce que c’est :
Définition Wikipedia de Preboot Execution Environment.
TL;DR donc, pour résumer c’est :
- Le BIOS démarre
- Il passe par le firmware de la carte réseau (boot menu & NIC)
- Le firmware PXE fait une requête DHCP qui lui donne les informations
- IP
- Serveur BOOTP (TFTP pour simplifier)
- Le nom de l’image avec laquelle booter
- PXE télécharge l’image en TFTP
- PXE boot l’image
Ça, c’était bien quand j’avais un NAS avec tout ce qu’il fallait comme stockage. Mais je suis passé sur un APU2 avec OpenSense. Je suis donc passé de 6To de stockage à 13Go en SDD. Par contre, je suis aussi passé d’un ASDL faiblar à de la fibre qui met le datacenter d’OVH dans mon salon.
Il me fallait donc une solution pour booter à partir d’une machine sur Internet.
iPXE arrive à la rescousse. C’est une version open source (c’est un point positif) de firmware PXE. Mais surtout avec beaucoup plus de fonctionnalités (et c’est là que ça devient intéressant). Comme la possibilité de télécharger les images en HTTP à la place de TFTP.
Par contre, le firmware n’est pas forcément disponible dans les cartes réseau communes.
Ça tombe bien, on peut faire une image compatible PXE pour iPXE (Upsa powered).
Si on reprend la suite de tout à l’heure :
- PXE télécharge l’image iPXE en TFTP
- PXE boot l’image iPXE
- iPXE télécharge le reste de sa configuration en HTTP (ou autre protocole)
Il te faudra donc :
- Un serveur DHCP (sur ton routeur/firewall OpenSense)
- Un serveur TFTP (toujours ton serveur OpenSense)
- Une image iPXE (sur le serveur TFTP donc OpenSense)
- Un serveur HTTP (chez OVH ou ton serveur local)
Alors, je dis OpenSense, et le reste de l’article est basé dessus. Mais ça fonctionnera parfaitement avec PFSense, DD-WRT, un Linux installé à la “main”.
Pour générer l’image iPXE, 2 solutions :
J’ai passé pas mal de temps a essayer de faire fonctionner les images générées par rom-o-matic. Mais c’était pénible de remettre la configuration, attendre la génération sur le serveur. Et puis, c’est cool de leur libérer un peu de CPU.
Mais tu peux facilement reproduire la configuration ci-dessous dans les paramètres ROM-o-Matic. Mais c’est beaucoup moins marrant :)
Bon. On y va ? Ou bien ?
Installation du serveur iPXE
Tu fais comme tu veux. Mais moi, je mets Nginx comme serveur HTTP. Voici la configuration du virtualhost à mettre :
server{
listen 80;
listen [::]:80;
server_name ipxe.example.com pxe.example.com;
root /var/www/ipxe;
index index.html index.htm;
}
Tu vas maintenant installer tous les fichiers nécessaires à la partie iPXE :
cd /var/www
git clone https://github.com/nledez/ipxe-root ipxe
cd /var/www/ipxe
sed 's@%BOOT_URL%@http://ipxe.example.com/@;s@http://boot.smidsrod.lan/@http://ipxe.example.com/@;s@sysrcd-version 3.8.0@sysrcd-version 5.2.2@' boot.ipxe.cfg.example
mkdir boot
touch boot/.bootdir
./install.sh boot
Installation des sources pour l’installeur Ubuntu
cd /var/www/ipxe
./install-ubuntu.sh
Généreration du binaire iPXE
cd /var/www/ipxe
git clone git://git.ipxe.org/ipxe.git ipxe
cd ipxe/src
cat > myscript.ipxe <<EOF
#!ipxe
dhcp
chain http://ipxe.example.com/boot.ipxe
EOF
vi config/general.h
C’est là, ou ça prend du temps pour avoir tous les bons paramètres fonctionnels. Voilà un patch de git vs ma configuration :
diff --git a/src/config/general.h b/src/config/general.h
index 3c14a2cd..75f3a432 100644
--- a/src/config/general.h
+++ b/src/config/general.h
@@ -36,16 +36,16 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define NET_PROTO_IPV4 /* IPv4 protocol */
#undef NET_PROTO_IPV6 /* IPv6 protocol */
-#undef NET_PROTO_FCOE /* Fibre Channel over Ethernet protocol */
-#define NET_PROTO_STP /* Spanning Tree protocol */
-#define NET_PROTO_LACP /* Link Aggregation control protocol */
+//#undef NET_PROTO_FCOE /* Fibre Channel over Ethernet protocol */
+//#define NET_PROTO_STP /* Spanning Tree protocol */
+//#define NET_PROTO_LACP /* Link Aggregation control protocol */
/*
* PXE support
*
*/
//#undef PXE_STACK /* PXE stack in iPXE - you want this! */
-//#undef PXE_MENU /* PXE menu booting */
+#undef PXE_MENU /* PXE menu booting */
/*
* Download protocols
@@ -55,9 +55,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define DOWNLOAD_PROTO_TFTP /* Trivial File Transfer Protocol */
#define DOWNLOAD_PROTO_HTTP /* Hypertext Transfer Protocol */
#undef DOWNLOAD_PROTO_HTTPS /* Secure Hypertext Transfer Protocol */
-#undef DOWNLOAD_PROTO_FTP /* File Transfer Protocol */
-#undef DOWNLOAD_PROTO_SLAM /* Scalable Local Area Multicast */
-#undef DOWNLOAD_PROTO_NFS /* Network File System Protocol */
+//#undef DOWNLOAD_PROTO_FTP /* File Transfer Protocol */
+//#undef DOWNLOAD_PROTO_SLAM /* Scalable Local Area Multicast */
+//#undef DOWNLOAD_PROTO_NFS /* Network File System Protocol */
//#undef DOWNLOAD_PROTO_FILE /* Local filesystem access */
/*
@@ -85,9 +85,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* 802.11 cryptosystems and handshaking protocols
*
*/
-#define CRYPTO_80211_WEP /* WEP encryption (deprecated and insecure!) */
-#define CRYPTO_80211_WPA /* WPA Personal, authenticating with passphrase */
-#define CRYPTO_80211_WPA2 /* Add support for stronger WPA cryptography */
+//#define CRYPTO_80211_WEP /* WEP encryption (deprecated and insecure!) */
+//#define CRYPTO_80211_WPA /* WPA Personal, authenticating with passphrase */
+//#define CRYPTO_80211_WPA2 /* Add support for stronger WPA cryptography */
/*
* Name resolution modules
@@ -103,16 +103,16 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* you want to use.
*
*/
-//#define IMAGE_NBI /* NBI image support */
-//#define IMAGE_ELF /* ELF image support */
-//#define IMAGE_MULTIBOOT /* MultiBoot image support */
-//#define IMAGE_PXE /* PXE image support */
-//#define IMAGE_SCRIPT /* iPXE script image support */
-//#define IMAGE_BZIMAGE /* Linux bzImage image support */
-//#define IMAGE_COMBOOT /* SYSLINUX COMBOOT image support */
+#define IMAGE_NBI /* NBI image support */
+#define IMAGE_ELF /* ELF image support */
+#define IMAGE_MULTIBOOT /* MultiBoot image support */
+#define IMAGE_PXE /* PXE image support */
+#define IMAGE_SCRIPT /* iPXE script image support */
+#define IMAGE_BZIMAGE /* Linux bzImage image support */
+#define IMAGE_COMBOOT /* SYSLINUX COMBOOT image support */
//#define IMAGE_EFI /* EFI image support */
-//#define IMAGE_SDI /* SDI image support */
-//#define IMAGE_PNM /* PNM image support */
+#define IMAGE_SDI /* SDI image support */
+#define IMAGE_PNM /* PNM image support */
#define IMAGE_PNG /* PNG image support */
#define IMAGE_DER /* DER image support */
#define IMAGE_PEM /* PEM image support */
@@ -136,24 +136,24 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define LOGIN_CMD /* Login command */
#define SYNC_CMD /* Sync command */
#define SHELL_CMD /* Shell command */
-//#define NSLOOKUP_CMD /* DNS resolving command */
-//#define TIME_CMD /* Time commands */
-//#define DIGEST_CMD /* Image crypto digest commands */
-//#define LOTEST_CMD /* Loopback testing commands */
+#define NSLOOKUP_CMD /* DNS resolving command */
+#define TIME_CMD /* Time commands */
+#define DIGEST_CMD /* Image crypto digest commands */
+#define LOTEST_CMD /* Loopback testing commands */
//#define VLAN_CMD /* VLAN commands */
-//#define PXE_CMD /* PXE commands */
-//#define REBOOT_CMD /* Reboot command */
-//#define POWEROFF_CMD /* Power off command */
-//#define IMAGE_TRUST_CMD /* Image trust management commands */
-//#define PCI_CMD /* PCI commands */
-//#define PARAM_CMD /* Form parameter commands */
-//#define NEIGHBOUR_CMD /* Neighbour management commands */
-//#define PING_CMD /* Ping command */
-//#define CONSOLE_CMD /* Console command */
-//#define IPSTAT_CMD /* IP statistics commands */
-//#define PROFSTAT_CMD /* Profiling commands */
-//#define NTP_CMD /* NTP commands */
-//#define CERT_CMD /* Certificate management commands */
+#define PXE_CMD /* PXE commands */
+#define REBOOT_CMD /* Reboot command */
+#define POWEROFF_CMD /* Power off command */
+#define IMAGE_TRUST_CMD /* Image trust management commands */
+#define PCI_CMD /* PCI commands */
+#define PARAM_CMD /* Form parameter commands */
+#define NEIGHBOUR_CMD /* Neighbour management commands */
+#define PING_CMD /* Ping command */
+#define CONSOLE_CMD /* Console command */
+#define IPSTAT_CMD /* IP statistics commands */
+#define PROFSTAT_CMD /* Profiling commands */
+#define NTP_CMD /* NTP commands */
+#define CERT_CMD /* Certificate management commands */
/*
* ROM-specific options
@@ -166,14 +166,14 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* Virtual network devices
*
*/
-#define VNIC_IPOIB /* Infiniband IPoIB virtual NICs */
+//#define VNIC_IPOIB /* Infiniband IPoIB virtual NICs */
//#define VNIC_XSIGO /* Infiniband Xsigo virtual NICs */
/*
* Error message tables to include
*
*/
-#undef ERRMSG_80211 /* All 802.11 error descriptions (~3.3kb) */
+//#undef ERRMSG_80211 /* All 802.11 error descriptions (~3.3kb) */
/*
* Obscure configuration options
Maintenant, tu vas pouvoir compiler tout ça :
/var/www/ipxe/ipxe/src# make bin/undionly.kpxe
[VERSION] bin/version.undionly.kpxe.o
[LD] bin/undionly.kpxe.tmp
[BIN] bin/undionly.kpxe.bin
[ZINFO] bin/undionly.kpxe.zinfo
[ZBIN] bin/undionly.kpxe.zbin
[FINISH] bin/undionly.kpxe
rm bin/version.undionly.kpxe.o bin/undionly.kpxe.zinfo bin/undionly.kpxe.bin bin/undionly.kpxe.zbin
Et voilà, c’est terminé pour la partie iPXE.
Maintenant, tu dois configurer le DHCP / TFTP (sur l’OpenSense)
On va commencer par DNSMasq pour la partie TFTP :
Dans Service / Dnsmasq DNS / Settings :
- Cocher “Enable” si ce n’est pas fait
- “Listen port” -> “5353” ou autre chose, mais pas 53 qui rentrerait en conflit avec Unbound
- “Network interface” -> “LAN”, j’ai mis ça pour éviter de répondre aux requêtes sur la partie WAN
- “Advanced” voir ci-dessous
enable-tftp
tftp-root=/tftp
Clique sur “Save”. Et passes à Unbound :
Dans Service / DHCPv4 / LAN :
- Dans la partie “TFTP server”
- “Set TFTP hostname” -> “192.168.2.1”
- “Set Bootfile” -> “/tftp/undionly.kpxe”
Et pour finir, tu vas copier le firmware que tu as construit tout à l’heure. Ouvre un shell (en ssh par exemple):
mkdir /tftp
cd /tftp/
curl http://ipxe.example.com/ipxe/src/bin/undionly.kpxe > undionly.kpxe
Et voilà ce que ça donne :
Tu peux voir le boot PXE + iPXE avec Memtest86+ puis un début d’installation Ubuntu.