{"id":248,"date":"2022-01-16T17:12:05","date_gmt":"2022-01-16T17:12:05","guid":{"rendered":"http:\/\/10.171.10.16:10000\/?p=248"},"modified":"2022-02-13T20:19:19","modified_gmt":"2022-02-13T20:19:19","slug":"rebuilding-a-pxe-boot-server-with-almalinux","status":"publish","type":"post","link":"https:\/\/dannypayne.me\/?p=248","title":{"rendered":"Rebuilding a PXE boot server with AlmaLinux"},"content":{"rendered":"\n<p>With the impending doom of CentOS, I figured now would be a great time to update the series of blog posts created in 2020 regarding building a PXE boot server, but for AlmaLinux.<br><\/p>\n\n\n\n<p>This series of posts will be about rebuilding this server with AlmaLinux.<br>The main things I want to accomplish are:<br>&#8211; Rebuild the server with AlmaLinux<br>&#8211; Replicate the previous setup (booting memtest, gparted, clonezilla, etc)<br>&#8211; Replace the CentOS kickstart setup with something similar for AlmaLinux<br>&#8211; PXE boot Windows installations (MDT, unattend.xml, etc)<\/p>\n\n\n\n<p>In this post I&#8217;m going to cover initially setting the PXE server up, and booting the AlmaLinux setup.<\/p>\n\n\n\n<p>This post assumes that you&#8217;ve already downloaded and installed the latest AlmaLinux (8.5 at the time of writing) on a new VM within your environment. As before, here are the details of the VM within my environment: <br><br><strong>Server IP<\/strong>: 10.179.1.10<br><strong>Hostname<\/strong>: COLO-PXE<br><strong>OS<\/strong>: AlmaLinux 8.5 (Artic Sphynx)<br><strong>CPU<\/strong>: 4 cores<br><strong>RAM<\/strong>: 4GB<br><strong>Hard disk<\/strong>: 128GB (thin provisioned)<br><strong>Firewalld is disabled, and SELinux is set to Permissive<\/strong><br><br>The VM will be setup with a standard AlmaLinux Minimal install using the <strong><a rel=\"noreferrer noopener\" href=\"https:\/\/mirrors.almalinux.org\/isos\/x86_64\/8.5.html\" target=\"_blank\">AlmaLinux-8.5-x86_64-minimal<\/a><\/strong> ISO obtained from the AlmaLinux Mirror List; boot the ISO, run through the setup, select <strong>Minimal Install<\/strong>, login at the console once the install has completed and set an IP and hostname, and also install <strong>open-vm-tools<\/strong>. Reboot the VM once more and then we can SSH into it. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"install-required-packages\">Install required packages<\/h3>\n\n\n\n<p>Once the VM is back online and we&#8217;re SSH&#8217;d in, we&#8217;re going to install the following packages\/run the following command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[root@COLO-PXE ~]# yum -y install tftp-server vsftpd xinetd httpd syslinux wget<\/code><\/pre>\n\n\n\n<p>As before, we&#8217;re not installing <code>DNSMASQ<\/code> on our VM as our DHCP is handled on our router\/firewall in this example. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"populate-syslinux-bootloaders\">Populate SYSLINUX bootloaders <\/h3>\n\n\n\n<p>Now that we&#8217;ve installed our packages, we&#8217;re ready to start editing configs and copying files around. To start, we&#8217;re going to copy all of the SYSLINUX bootloader files to our tftproot folder with the following commands:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[root@COLO-PXE ~]# cp -v \/usr\/share\/syslinux\/{pxelinux.0,menu.c32,mboot.c32,chain.c32,memdisk,ldlinux.c32,libutil.c32,libcom32.c32} \/var\/lib\/tftpboot<\/code><\/pre>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"142\" src=\"http:\/\/10.171.10.16:10000\/wp-content\/uploads\/2022\/01\/248-1-1024x142.png\" alt=\"\" class=\"wp-image-265\" srcset=\"https:\/\/dannypayne.me\/wp-content\/uploads\/2022\/01\/248-1-1024x142.png 1024w, https:\/\/dannypayne.me\/wp-content\/uploads\/2022\/01\/248-1-300x42.png 300w, https:\/\/dannypayne.me\/wp-content\/uploads\/2022\/01\/248-1-768x106.png 768w, https:\/\/dannypayne.me\/wp-content\/uploads\/2022\/01\/248-1.png 1098w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"enable-and-start-services\">Enable and start services<\/h3>\n\n\n\n<p>Before we can continue, we need to enable and start the services we just installed:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[root@COLO-PXE ~]# systemctl enable xinetd vsftpd httpd\n[root@COLO-PXE ~]# systemctl start xinetd vsftpd httpd<\/code><\/pre>\n\n\n\n<p>We also need to create a TFTP server config file within <code>\/etc\/xinetd.d\/<\/code>.<br>Create and edit the following file: <code>\/etc\/xinetd.d\/tftp<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash line-numbers\">service tftp\n{\ndisable         = no\nsocket_type     = dgram\nprotocol        = udp\nwait            = yes\nuser            = root\nserver          = \/usr\/sbin\/in.tftpd\nserver_args     = -s \/var\/lib\/tftpboot\nper_source      = 11\ncps             = 100 2\nflags           = IPv4\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"copy-almalinux-files-to-server\">Copy AlmaLinux files to server<\/h3>\n\n\n\n<p>We&#8217;re now in a position whereby we can copy our AlmaLinux files and attempt to PXE boot our client. Mount the ISO file used to install the VM originally back to the VMs DVD drive if it&#8217;s been unmounted, and verify it&#8217;s seen by the OS:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[root@COLO-PXE ~]# blkid | grep AlmaLinux\n\/dev\/sr0: BLOCK_SIZE=\"2048\" UUID=\"2021-11-11-16-16-25-00\" LABEL=\"AlmaLinux-8-5-x86_64-dvd\" TYPE=\"iso9660\" PTUUID=\"5c6fc0a3\" PTTYPE=\"dos\"<\/code><\/pre>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"57\" src=\"http:\/\/10.171.10.16:10000\/wp-content\/uploads\/2022\/01\/248-2-1024x57.png\" alt=\"\" class=\"wp-image-266\" srcset=\"https:\/\/dannypayne.me\/wp-content\/uploads\/2022\/01\/248-2-1024x57.png 1024w, https:\/\/dannypayne.me\/wp-content\/uploads\/2022\/01\/248-2-300x17.png 300w, https:\/\/dannypayne.me\/wp-content\/uploads\/2022\/01\/248-2-768x43.png 768w, https:\/\/dannypayne.me\/wp-content\/uploads\/2022\/01\/248-2.png 1096w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n\n<p>Next, we&#8217;re going to mount the DVD drive within our OS and verify it&#8217;s mounted correctly:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[root@COLO-PXE ~]# mkdir \/media\/iso\n[root@COLO-PXE ~]# mount \/dev\/sr0 \/media\/iso\nmount: \/media\/iso: WARNING: device write-protected, mounted read-only.\n[root@COLO-PXE ~]# ls \/media\/iso\nBaseOS  EFI  images  isolinux  media.repo  Minimal  TRANS.TBL<\/code><\/pre>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"569\" height=\"103\" src=\"http:\/\/10.171.10.16:10000\/wp-content\/uploads\/2022\/01\/248-3.png\" alt=\"\" class=\"wp-image-267\" srcset=\"https:\/\/dannypayne.me\/wp-content\/uploads\/2022\/01\/248-3.png 569w, https:\/\/dannypayne.me\/wp-content\/uploads\/2022\/01\/248-3-300x54.png 300w\" sizes=\"auto, (max-width: 569px) 100vw, 569px\" \/><\/figure><\/div>\n\n\n\n<p>Next, we&#8217;re going to copy the files from the DVD to our VM. <br>I want these files to be accessible over both FTP and HTTP, so I&#8217;m going to go ahead and create a new directory at the <code>\/<\/code> location for these &#8211; <code>\/srv\/networkboot<\/code><br>Inside this folder, we&#8217;re going to create directories for our OS, <code>\/srv\/networkboot\/almalinux\/8.5<\/code> and copy the contents of the DVD to the above folder:<br>Finally, we&#8217;re going to create a symbolic link for <code>\/srv\/networkboot\/<\/code> to <code>\/var\/www\/html<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[root@COLO-PXE \/]# mkdir -p \/srv\/networkboot\/almalinux\/8.5\n[root@COLO-PXE \/]# cp -av \/media\/iso\/* \/srv\/networkboot\/almalinux\/8.5\/\n[root@COLO-PXE \/]# ln -s \/srv\/networkboot\/ \/var\/www\/html<\/code><\/pre>\n\n\n\n<p>We also need to copy the <code>vmlinuz<\/code> and <code>initrd.img<\/code> files from the DVD to the <code>\/var\/lib\/tftpboot<\/code> folder. <br>Within the above directory we&#8217;re going to create a new directory for the files, following the folder structure above, and then copy them:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[root@COLO-PXE \/]# mkdir -p \/var\/lib\/tftpboot\/almalinux\/8.5\n[root@COLO-PXE \/]# cp \/media\/iso\/images\/pxeboot\/{vmlinuz,initrd.img} \/var\/lib\/tftpboot\/almalinux\/8.5\/\n[root@COLO-PXE \/]# ls -l \/var\/lib\/tftpboot\/almalinux\/8.5\/\ntotal 87844\n-r--r--r-- 1 root root 79740504 Jan  8 20:22 initrd.img\n-r-xr-xr-x 1 root root 10211208 Jan  8 20:22 vmlinuz<\/code><\/pre>\n\n\n\n<p>Next, if we run an <code>ls<\/code> of the <code>\/var\/www\/html<\/code> directory we can see the symlink as expected. When browsing to the servers IP within a browser and navigating to <code>\/networkboot<\/code>, we should see our <code>almalinux\/8.5<\/code> folder containing the ISO content as expected. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[root@COLO-PXE \/]# ls -l \/var\/www\/html\ntotal 0\nlrwxrwxrwx 1 root root 17 Jan  3 17:16 networkboot -&gt; \/srv\/networkboot\/<\/code><\/pre>\n\n\n\n<p>For our FTP to work, we need to enable Anonymous Access<br>Edit the file <code>\/etc\/vsftpd\/vsftpd.conf<\/code> and change the following:<br><code>anonymous_enable=NO<\/code> to <code>anonymous_enable=YES<\/code><br><code>local_enable=YES<\/code> to <code>local_enable=NO<\/code><br><br>Finally we need to add the following line somewhere within the file:<br><code>anon_root=\/srv\/networkboot\/<\/code><br><br>After making these changes, restart <code>vsftpd<\/code> and verify all is working as expected. <\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"629\" height=\"161\" src=\"http:\/\/10.171.10.16:10000\/wp-content\/uploads\/2022\/01\/248-4.png\" alt=\"\/etc\/vsftpd\/vsftpd.conf\" class=\"wp-image-268\" srcset=\"https:\/\/dannypayne.me\/wp-content\/uploads\/2022\/01\/248-4.png 629w, https:\/\/dannypayne.me\/wp-content\/uploads\/2022\/01\/248-4-300x77.png 300w\" sizes=\"auto, (max-width: 629px) 100vw, 629px\" \/><\/figure><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"create-pxe-boot-menu-file\">Create PXE boot menu file<\/h3>\n\n\n\n<p>We now need to create our PXE boot menu. For this, we&#8217;re going to add a single option so we can verify our server is working as expected, and once we&#8217;ve confirmed this works, we can add more as needed. <br>To get started, we need to create the <code>pxelinux.cfg<\/code> directory, and within that, the <code>default<\/code> file:<\/p>\n\n\n\n<pre title=\"\" class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[root@COLO-PXE ~]# mkdir \/var\/lib\/tftpboot\/pxelinux.cfg \n[root@COLO-PXE ~]# touch \/var\/lib\/tftpboot\/pxelinux.cfg\/default<\/code><\/pre>\n\n\n\n<p>Next, we&#8217;re going to edit the <code>pxelinux.cfg\/default<\/code> file with a boot menu option so we can verify our server is working as expected.<\/p>\n\n\n\n<pre title=\"\/var\/lib\/tftpboot\/pxelinux.cfg\/default\" class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">default menu.c32\nprompt 0\ntimeout 300\nONTIMEOUT localboot\nMENU AUTOBOOT Booting from local drive in # seconds\n\nmenu title ########## PXE Boot Menu ##########\n\nLABEL Boot AlmaLinux 8.5 x64 with Network Repo\nMENU LABEL Boot AlmaLinux 8.5 x64 with Network Repo\nKERNEL almalinux\/8.5\/vmlinuz\nAPPEND initrd=almalinux\/8.5\/initrd.img method=ftp:\/\/10.179.1.10\/almalinux\/8.5 devfs=nomount\n\nLABEL localboot\nMENU LABEL Boot from local drive\nLOCALBOOT 1\nCOM32 chain.c32\nAPPEND hd0 0<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"configure-dhcp-firewall-for-pxe-booting\">Configure DHCP\/firewall for PXE booting<\/h3>\n\n\n\n<p>Finally, we need to configure our router for PXE booting. Within the DHCP settings of our router\/firewall we need to edit\/enable the following settings:<br>&#8211; TFTP Server<br>&#8211; Next Server<br>&#8211; Default file name<br>If we&#8217;re unable to configure them specific settings, we can also specify DHCP <strong>options 66<\/strong> and <strong>67<\/strong>.<\/p>\n\n\n\n<p>In this example, we&#8217;re using PFSense.<br>On PFSense, we&#8217;re going to want to navigate to <strong>Services <\/strong>&gt; <strong>DHCP Server<\/strong> &gt; <em><strong>&lt;Network name&gt;<\/strong><\/em>.<br>Scroll to the bottom of the page and find <strong>TFTP<\/strong>. Click <strong>Display Advanced<\/strong> and enter the IP of your PXE server &#8211; in this example, <strong>10.179.1.10<\/strong>.<br>Next, scroll down to <strong>Network Booting<\/strong> and click <strong>Display Advanced<\/strong>. Tick the checkbox for <strong>Enables network booting<\/strong> and enter the IP of your PXE server in the <strong>Next Server<\/strong> box.<br>In the <strong>Default BIOS file name<\/strong> box we&#8217;re going to enter<code>pxelinux.0<\/code> &#8211; This is one of the bootloader files we copied right at the beginning. <\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"782\" height=\"341\" src=\"http:\/\/10.171.10.16:10000\/wp-content\/uploads\/2022\/01\/248-5.png\" alt=\"\" class=\"wp-image-269\" srcset=\"https:\/\/dannypayne.me\/wp-content\/uploads\/2022\/01\/248-5.png 782w, https:\/\/dannypayne.me\/wp-content\/uploads\/2022\/01\/248-5-300x131.png 300w, https:\/\/dannypayne.me\/wp-content\/uploads\/2022\/01\/248-5-768x335.png 768w\" sizes=\"auto, (max-width: 782px) 100vw, 782px\" \/><\/figure><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"tidying-up\">Tidying up<\/h3>\n\n\n\n<p>At this point, we&#8217;ve completed our configuration and are ready to start testing.<br>Before doing anything, we need to tidy up our VM<\/p>\n\n\n\n<p>We&#8217;re going to do the following:<br>&#8211; Unmount <code>\/media\/iso<\/code><br>&#8211; Delete <code>\/media\/iso<\/code> <br>&#8211; Restart our services (<code>xinetd<\/code>, <code>vsftpd<\/code>, <code>httpd<\/code>)<br>&#8211; Eject AlmaLinux DVD from our VMs DVD drive<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[root@COLO-PXE ~]# umount \/media\/iso\n[root@COLO-PXE ~]# rm -rf \/media\/iso\n[root@COLO-PXE ~]# systemctl restart xinetd vsftpd httpd\n<\/code><\/pre>\n\n\n\n<p>I would also recommend giving the VM a quick restart for good measure. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"testing-the-boot\">Testing the boot<\/h3>\n\n\n\n<p>We&#8217;re now ready to test PXE booting a client device. <\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"600\" src=\"http:\/\/10.171.10.16:10000\/wp-content\/uploads\/2022\/01\/248-boot.gif\" alt=\"\" class=\"wp-image-270\"\/><\/figure><\/div>\n\n\n\n<p>If everything has worked successfully, we should be presented with our PXE boot menu, and then be able to select the <strong>first<\/strong> option on the menu. After a few moments, we&#8217;ll be prompted with the AlmaLinux setup screen.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"600\" src=\"http:\/\/10.171.10.16:10000\/wp-content\/uploads\/2022\/01\/248-7.png\" alt=\"\" class=\"wp-image-275\" srcset=\"https:\/\/dannypayne.me\/wp-content\/uploads\/2022\/01\/248-7.png 800w, https:\/\/dannypayne.me\/wp-content\/uploads\/2022\/01\/248-7-300x225.png 300w, https:\/\/dannypayne.me\/wp-content\/uploads\/2022\/01\/248-7-768x576.png 768w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/figure>\n\n\n\n<p>Once the VM reaches this point, we&#8217;ll be able to install AlmaLinux as normal, and it&#8217;ll just <em>work<\/em>. <\/p>\n\n\n\n<p>This concludes this post. <br>In another post, I&#8217;m going to cover adding other bootable media to our boot menu, and customising it a little more. Stay tuned! <\/p>\n","protected":false},"excerpt":{"rendered":"<p>With the impending doom of CentOS, I figured now would be a great time to update the series of blog&#8230;<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/dannypayne.me\/?p=248\">Read more<span class=\"screen-reader-text\">Rebuilding a PXE boot server with AlmaLinux<\/span><\/a><\/div>\n","protected":false},"author":1,"featured_media":273,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[6],"tags":[],"class_list":["post-248","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-homelab","excerpt","zoom","full-without-featured","even","excerpt-0"],"jetpack_featured_media_url":"https:\/\/dannypayne.me\/wp-content\/uploads\/2022\/01\/248-6.png","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/dannypayne.me\/index.php?rest_route=\/wp\/v2\/posts\/248","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dannypayne.me\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dannypayne.me\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dannypayne.me\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dannypayne.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=248"}],"version-history":[{"count":19,"href":"https:\/\/dannypayne.me\/index.php?rest_route=\/wp\/v2\/posts\/248\/revisions"}],"predecessor-version":[{"id":305,"href":"https:\/\/dannypayne.me\/index.php?rest_route=\/wp\/v2\/posts\/248\/revisions\/305"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/dannypayne.me\/index.php?rest_route=\/wp\/v2\/media\/273"}],"wp:attachment":[{"href":"https:\/\/dannypayne.me\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=248"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dannypayne.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=248"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dannypayne.me\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=248"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}