Preboot Execution Environment (PXE)

PXE is an open industry standard supported by a number of hardware and software vendors.
The PXE-enabled NIC of the client sends out a broadcast request to DHCP server, which returns with the IP address of the client along with the address of the TFTP server, and the location of boot files on the TFTP server.
  1. The Network Interface Card (NIC) of the machine triggers a DHCP request.
  2. DHCP server intercepts the request and responds with standard information (IP, subnet mask, gateway, DNS etc.). In addition, it provides information about the location of a TFTP server and boot image (pxelinux.0).
  3. When the client receives this information, it contacts the TFTP server for obtaining the boot image.
  4. TFTP server sends the boot image (pxelinux.0), and the client executes it.
  5. By default, the boot image searches the pxelinux.cfg directory on TFTP server for boot configuration files on the TFTP server
  6. For example, if the boot file name is /tftpboot/pxelinux.0, the Ethernet MAC address is 88:99:AA:BB:CC:DD, and the IP address 192.0.2.91, the boot image looks for file names in the following order:
    
    /tftpboot/pxelinux.cfg/01-88-99-aa-bb-cc-dd
    /tftpboot/pxelinux.cfg/C000025B
    /tftpboot/pxelinux.cfg/C000025
    /tftpboot/pxelinux.cfg/C00002
    /tftpboot/pxelinux.cfg/C0000
    /tftpboot/pxelinux.cfg/C000
    /tftpboot/pxelinux.cfg/C00
    /tftpboot/pxelinux.cfg/C0
    /tftpboot/pxelinux.cfg/C  
      

Ubuntu Netboot Images

Grub supports booting files over the network via both FTP/HTTP.
GRUB has builtin support for HTTP via http.mod.
It's also suggested to build grubnetx64.efi using GRUB modules to include lvm and RAID support.
This will allow grubnetx64.efi to local boot in all situations.

--- build-efi-images 2018-08-17 10:50:35.124311043 -0700
+++ build-efi-images.new 2018-08-17 10:50:59.270661126 -0700
@@ -148,8 +148,9 @@
  raid5rec
  raid6rec
  "
-NET_MODULES="$CD_MODULES
+NET_MODULES="$GRUB_MODULES
  tftp
+ http
  "

Automated Server Installs Introduction

Autoinstallation lets you answer all those configuration questions ahead of time with an autoinstall config and lets the installation process run without any interaction.

Differences from debian-installer preseeding

  • debian-installer
    • preseeding
    • debconf-set-selections format
  • autoinstalls
    • cloud-init yaml format
    • if there is any autoinstall config at all, the installer takes the default for any unanswered question
    • You can designate particular sections in the config as “interactive”,

Providing the autoinstall config in cloud-init

The autoinstall config is provided via cloud-init configuration.
The autoinstall config should be provided under the autoinstall key in the config.

#cloud-config
autoinstall:
  version: 1
  ...
Even if a fully noninteractive autoinstall config is found, the server installer will ask for confirmation before writing to the disks unless autoinstall is present on the kernel command line.

Many autoinstalls will be done via netboot, where the kernel command line is controlled by the netboot config.

Autoinstall Quick Start

This is to perform an autoinstall in a VM on your machine.

Providing the autoinstall config data (in cloud-init) over the network

  • Download the ISO image: ubuntu-20.04.2-live-server-amd64.iso
  • 
    wget http://releases.ubuntu.com/20.04/ubuntu-20.04.2-live-server-amd64.iso
      	
  • Mount the ISO
  • 
    sudo mount -r ~/Downloads/ubuntu-20.04.2-live-server-amd64.iso /mnt
    	
  • creating cloud-init config
  • 
    $ mkdir -p ~/www
    $ cat > ~/www/user-data << 'EOF'
    #cloud-config
    autoinstall:
      version: 1
      interactive-sections:
       - locale
       - refresh-installer
       - keyboard
       - network
       - proxy
       - apt
       - storage
       - identity
       - ssh
       - snaps  
      identity:
        hostname: ubuntu-server
        password: "$6$exDY1mhS4KUYCE/2$zmn9ToZwTKLhCw.b4/b.ZRTIZM30JZ4QrOQ2aOXJ8yk96xpcCof0kxKwuX1kqLG/ygbJ1f8wxED22bTL4F46P0"
        username: ubuntu
    EOF
    $ touch ~/www/meta-data
    	
    The crypted password is just “ubuntu”.
  • Serve the cloud-init config over HTTP
  • 
    $ cd ~/www
    $ python3 -m http.server 3003
    	
    http.server can also be invoked directly using the -m switch of the interpreter with a port number argument, this serves files relative to the current directory.
    By default, server binds itself to all interfaces. The option -b/--bind specifies a specific address to which it should bind.
  • Create a target disk
  • 
    $ truncate -s 10G image.img
    	
  • Using the server ISO image and Install the Ubuntu server on the targe
  • 
    $ kvm -no-reboot -m 1024 \
        -drive file=image.img,format=raw,cache=none,if=virtio \
        -cdrom ~/Downloads/ubuntu-20.04.2-live-server-amd64.iso \
        -kernel /mnt/casper/vmlinuz \
        -initrd /mnt/casper/initrd \
        -append 'autoinstall ds=nocloud-net\;s=http://localhost:3003/'
    	
    • the -no-reboot flag to kvm means that kvm will exit athe the end
    • ds=nocloud-net tells the kernel where to download the cloud-init data
    • In a GRUB bootloader, the semicolon character terminates a command.
      The cloud-init syntax uses exactly the same symbol to parameterize the installation source:
      
      		ds=nocloud-net[\;key=val;key=val]
              
      The permitted keys are:
      • h or local-hostname
      • i or instance-id
      • s or seedfrom
        • With ds=nocloud , the seedfrom value must start with / or file:// .
        • With ds=nocloud-net , the seedfrom value must start with http:// , https:// or ftp://
      You need to escape the semicolon by one of the following:
      • 
         linux /casper/vmlinuz autoinstall ds=nocloud-net\;s=http://192.168.10.10:3003/     
                    
      • 
         linux /casper/vmlinuz autoinstall ds='nocloud-net;s=http://192.168.10.10:3003/'        
                    
  • Boot the installed system
  • 
    $ kvm -no-reboot -m 1024 \
        -drive file=image.img,format=raw,cache=none,if=virtio    
    	
    This will boot into the freshly installed system and you should be able to log in as ubuntu/ubuntu.

Providing the autoinstall config data (in cloud-init) via a CD volume

  • Download the ISO image: ubuntu-20.04.2-live-server-amd64.iso
  • 
    wget http://releases.ubuntu.com/20.04/ubuntu-20.04.2-live-server-amd64.iso
      	
  • Mount the ISO
  • 
    sudo mount -r ~/Downloads/ubuntu-20.04.2-live-server-amd64.iso /mnt
    	
  • creating cloud-init config files: user-data , meta-data
  • 
    $ mkdir -p ~/cidata
    $ cat > ~/cidata/user-data << 'EOF'
    #cloud-config
    autoinstall:
      version: 1
      interactive-sections:
       - locale
       - refresh-installer
       - keyboard
       - network
       - proxy
       - apt
       - storage
       - identity
       - ssh
       - snaps  
      identity:
        hostname: ubuntu-server
        password: "$6$exDY1mhS4KUYCE/2$zmn9ToZwTKLhCw.b4/b.ZRTIZM30JZ4QrOQ2aOXJ8yk96xpcCof0kxKwuX1kqLG/ygbJ1f8wxED22bTL4F46P0"
        username: ubuntu
    EOF
    $ touch ~/cidata/meta-data
    	
    The crypted password is just “ubuntu”.
  • Create an ISO image to use as a cloud-init local data source
  • 
    $ sudo apt install cloud-image-utils
    $ cloud-localds ~/seed.iso ~/cidata/user-data ~/cidata/meta-data
    	
  • Create a target disk
  • 
    $ truncate -s 10G image.img
    	
  • Using the server ISO image and Install the Ubuntu server on the targe
  • 
    $ kvm -no-reboot -m 1024 \
        -drive file=image.img,format=raw,cache=none,if=virtio \
        -drive file=~/seed.iso,format=raw,cache=none,if=virtio \
        -cdrom ~/Downloads/ubuntu-20.04.2-live-server-amd64.iso \
    	
  • Boot the installed system
  • 
    $ kvm -no-reboot -m 1024 \
        -drive file=image.img,format=raw,cache=none,if=virtio    
    	
    This will boot into the freshly installed system and you should be able to log in as ubuntu/ubuntu.

Unpack the ISO and modify installer.squashfs


cat > squashfs-root/etc/cloud/cloud.cfg.d/90_autoinstall.cfg << 'EOF'
autoinstall:
  version: 1
  identity:
    hostname: ubuntu-server
    password: "$6$exDY1mhS4KUYCE/2$zmn9ToZwTKLhCw.b4/b.ZRTIZM30JZ4QrOQ2aOXJ8yk96xpcCof0kxKwuX1kqLG/ygbJ1f8wxED22bTL4F46P0"
    username: jerry
EOF
Then, all you need to do is add ‘autoinstall’ to grub.cfg and repack the ISO.

Understanding the Ubuntu 20.04 LTS Server Autoinstaller

Server Setup

TFTP Server

Installation


sudo apt install tftpd-hpa
sudo systemctl status tftpd-hpa
sudo mkdir /var/lib/tftpboot
sudo chown tftp:tftp /var/lib/tftpboot

Configuration

Modify this configuration file /etc/default/tftpd-hpa:

# vi /etc/default/tftpd-hpa

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/var/lib/tftpboot"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="--secure --create"
  • TFTP_USERNAME
  • is set to tftp.
    It means the TFTP server will run as the user tftp.
  • TFTP_DIRECTORY
  • is set to /var/lib/tftpboot.
    It means /var/lib/tftpboot is the directory on this server which you will be able to access via TFTP.
  • TFTP_ADDRESS
  • is set to :69.
    It means TFTP will run on port 69.
  • TFTP_OPTIONS
      • --secure
      • This variable sets the TFTP options.
      • --create
      • To create or upload new files to the TFTP server.
Restart the tftpd-hpa service afterwards.

$ sudo systemctl restart tftpd-hpa
$ sudo ufw allow tftp
$ sudo ufw allow bootpc

To test the TFTP server

  • Install the TFTP client
  • 
    $ sudo apt install tftp
    
  • Get the IP address of the TFTP server, connect to the TFTP s:
  • 
    $ tftp 10.101.46.143
    tftp> put 2021-01-06-01-02-05.076-VBoxSVC-37033.log
    Sent 248 bytes in 0.0 seconds
    tftp> quit
    

Debug


$ journalctl -fu tftpd-hpa

Prepare Image Files for Downloading

AMD64

  • Download the live server iso image
  • 
    sudo wget http://old-releases.ubuntu.com/releases/20.04/ubuntu-20.04.2-live-server-amd64.iso -O /var/lib/tftpboot/ubuntu-20.04.2-live-server-amd64.iso 
        
  • Extract the kernel and initramfs from the live server iso
  • 
    sudo mount /var/lib/tftpboot/ubuntu-20.04.2-live-server-amd64.iso /mnt/
    sudo cp /mnt/casper/vmlinuz /var/lib/tftpboot/
    sudo cp /mnt/casper/initrd /var/lib/tftpboot/
    sudo umount  /mnt    
        
  • Download the grub binary to load via PXE
  • 
    sudo wget http://archive.ubuntu.com/ubuntu/dists/focal/main/uefi/grub2-amd64/current/grubnetx64.efi.signed -O /var/lib/tftpboot/pxelinux.0  
        
  • Configure grub to provide a fully automated boot option as well as a manual boot option
  • 
    $ sudo -i
    # mkdir -p /var/lib/tftpboot/grub
    # cat > /var/lib/tftpboot/grub/grub.cfg <<'EOF'
    default=autoinstall
    timeout=30
    timeout_style=menu
    menuentry "Focal Live Installer - automated" --id=autoinstall {
        echo "Loading Kernel..."
        # make sure to escape the ';'
        linux /vmlinuz ip=dhcp url=http://$SERVER_IP/tftp/ubuntu-20.04.2-live-server-amd64.iso autoinstall ds=nocloud-net\;s=http://$SERVER_IP/tftp/
        echo "Loading Ram Disk..."
        initrd /initrd
    }
    menuentry "Focal Live Installer" --id=install {
        echo "Loading Kernel..."
        linux /vmlinuz ip=dhcp url=http://$SERVER_IP/tftp/ubuntu-20.04.2-live-server-amd64.iso
        echo "Loading Ram Disk..."
        initrd /initrd
    }
    EOF    
        
  • Configure cloud-init with the autoinstall configuration.
    • create meta-data
    • 
      # cat > /var/lib/tftpboot/meta-data <<EOF
      instance-id: focal-autoinstall
      EOF    
          	
    • create user-data
    • The autoinstall file is YAML.
      At top level it must be a mapping containing the keys described in this document.
      • version
      • A future-proofing config file version field. Currently this must be “1”.
      • interactive-sections
      • A list of config keys to still show in the UI.
        For ex., to stop on the network screen and allow the user to change the defaults.
        
        interactive-sections:
         - network
                    
        Not all config keys correspond to screens in the UI. Check the codument to know if a given section can be interactive or not.
      • locale
      • This can be interactive.
      • keyboard
      • This can be interactive.
      • network
      • This can be interactive.
        netplan formatted network configuration.
        This will be applied during installation as well as in the installed system.
      • apt
      • This can be interactive.
        APT configuration, used both during the install and once booted into the target system.
        This uses the same format as curtin(the curt installer) which is documented at https://curtin.readthedocs.io/en/latest/topics/apt_source.html, with one extension: the geoip key controls whether a geoip lookup is done.
      • storage
      • The installer supports “layouts” to express common storage configurations.
        Currently, there are two supported layouts:
        • lvm
        • direct
        The default is to use the lvm layout.
        By default these will install to the largest disk in a system, but you can supply a match spec to indicate which disk to use.
        For ex.,
        
        storage:
          layout:
            name: lvm
            match:
              serial: CT*
        storage:
          layout:
            name: disk
            match:
              ssd: yes            
                    
        The installer allows storage configuration to be done using a syntax which is a superset of that supported by curtin, described at https://curtin.readthedocs.io/en/latest/topics/storage.html.
        The extensions to the curtin syntax are around disk selection and partition/logical volume sizing.
        • disk selection
        • Disks can be identified by the match spec.
          A match spec supports the following keys:
          • model: model_vendor
          • matches a disk where ID_VENDOR=model_vendor in udev, supporting globbing
          • path: device_path
          • matches a disk where DEVPATH=device_path in udev
          • serial: seril_no
          • matches a disk where ID_SERIAL=seril_no in udev
          • ssd: yes|no
          • matches a disk that is or is not an SSD (vs a disk drive)
          • size: largest|smallest
          • take the largest or smallest disk rather than an arbitrary one if there are multiple matches (support for smallest added in version 20.06.1)
        • partition/logical volume sizing
      • identity
      
      # cat > /var/lib/tftpboot/user-data <<'EOF'
      #cloud-config
      autoinstall:
        version: 1
        # use interactive-sections to avoid an automatic reboot
        #interactive-sections:
        #  - locale
        keyboard: {layout: us, variant: ''}
        locale: en_US.UTF-8  
        # interface name will probably be different
        network:
          network:
            version: 2
            renderer: NetworkManager                  
        apt:
          # even set to no/false, geoip lookup still happens
          #geoip: no
          preserve_sources_list: false
          primary:
          - arches: [amd64, i386]
            uri: http://us.archive.ubuntu.com/ubuntu
          - arches: [default]
            uri: http://ports.ubuntu.com/ubuntu-ports
        # this creates an efi partition, /boot partition, and root(/) lvm volume
        storage:
          grub:
            reorder_uefi: False
          swap:
            size: 0
          config:
          - {ptable: gpt, path: /dev/nvme0n1, preserve: false, name: '', grub_device: false,
            type: disk, id: disk-nvme0n1}
          - {device: disk-nvme0n1, size: 536870912, wipe: superblock, flag: boot, number: 1,
            preserve: false, grub_device: true, type: partition, id: partition-nvme0n11}
          - {fstype: fat32, volume: partition-nvme0n11, preserve: false, type: format, id: format-2}
          - {device: disk-nvme0n1, size: 1073741824, wipe: superblock, flag: linux, number: 2,
            preserve: false, grub_device: false, type: partition, id: partition-nvme0n12}
          - {fstype: ext4, volume: partition-nvme0n12, preserve: false, type: format, id: format-0}
          - {device: disk-nvme0n1, size: -1, flag: linux, number: 3, preserve: false,
            grub_device: false, type: partition, id: partition-nvme0n13}
          - name: vg-0
            devices: [partition-nvme0n13]
            preserve: false
            type: lvm_volgroup
            id: lvm-volgroup-vg-0
          - {name: lv-root, volgroup: lvm-volgroup-vg-0, size: 100%, preserve: false,
            type: lvm_partition, id: lvm-partition-lv-root}
          - {fstype: ext4, volume: lvm-partition-lv-root, preserve: false, type: format,
            id: format-1}
          - {device: format-1, path: /, type: mount, id: mount-2}
          - {device: format-0, path: /boot, type: mount, id: mount-1}
          - {device: format-2, path: /boot/efi, type: mount, id: mount-3}      
        # r00tme
        identity: {hostname: focal-autoinstall, password: $6$.c38i4RIqZeF4RtR$hRu2RFep/.6DziHLnRqGOEImb15JT2i.K/F9ojBkK/79zqY30Ll2/xx6QClQfdelLe.ZjpeVYfE8xBBcyLspa/,
          username: ubuntu}
      
      
        ssh:
          allow-pw: true
          authorized-keys: []
          install-server: true
      
      write_files:
        # override the kernel package
        - path: /run/kernel-meta-package
          content: |
            linux-virtual
          owner: root:root
          permissions: "0644"
        # attempt to also use an answers file by providing a file at the default path.  It did not seem to have any effect
        #- path: /subiquity_config/answers.yaml
        #  content: |
        #    InstallProgress:
        #      reboot: no
        #  owner: root:root
        #  permissions: "0644"
      EOF
          	
This happened when autoinstall was selected:

finish: subiquity/InstallProgress/curtin_install: FAIL: Command '['systemd-cat', '--level-prefix=false', '--identifier=curtin_log.2441', '/snap/subiquity/1772/usr/bin/python3', '-m', 'curtin', '---showtrace', '-c', '/var/log/installer/subiquity-curtin-install.conf', 'install']' returned non-zero exit status 3.
It is due to the setting "ds=nocloud-net" in /var/lib/tftpboot/grub/grub.cfg was wrong.

ARM64

  • Download the Ubuntu 20.04.1 live server image ubuntu-20.04.1-live-server-arm64.iso
  • 
    sudo wget http://cdimage.ubuntu.com/ubuntu/releases/20.04.1/release/ubuntu-20.04.1-live-server-arm64.iso -O /var/lib/tftpboot/ubuntu-20.04.1-live-server-arm64.iso 
        
  • Extract the kernel and initramfs from the live server iso
  • 
    sudo mount /var/lib/tftpboot/ubuntu-20.04.1-live-server-arm64.iso /mnt/
    sudo cp /mnt/casper/vmlinuz /var/lib/tftpboot/
    sudo cp /mnt/casper/initrd /var/lib/tftpboot/
    sudo umount  /mnt    
        
  • Download the grub binary to load via PXE
  • 
    sudo wget  http://ports.ubuntu.com/ubuntu-ports/dists/focal/main/uefi/grub2-arm64/current/grubnetaa64.efi.signed -O /var/lib/tftpboot/pxelinux.0  
        
  • Configure grub to provide a fully automated boot option as well as a manual boot option
  • 
    $ sudo -i
    # mkdir -p /var/lib/tftpboot/grub
    # cat > /var/lib/tftpboot/grub/grub.cfg <<'EOF'
    default=autoinstall
    timeout=30
    timeout_style=menu
    menuentry "Focal Live Installer - automated" --id=autoinstall {
        echo "Loading Kernel..."
        # make sure to escape the ';'
        linux /vmlinuz ip=dhcp url=http://$SERVER_IP/tftp/ubuntu-20.04.1-live-server-arm64.iso autoinstall ds=nocloud-net\;s=http://$SERVER_IP/tftp/
        echo "Loading Ram Disk..."
        initrd /initrd
    }
    menuentry "Focal Live Installer" --id=install {
        echo "Loading Kernel..."
        linux /vmlinuz ip=dhcp url=http://$SERVER_IP/tftp/ubuntu-20.04.1-live-server-arm64.iso
        echo "Loading Ram Disk..."
        initrd /initrd
    }
    EOF    
        
  • Configure cloud-init with the autoinstall configuration.
    • create meta-data
    • 
      # cat > /var/lib/tftpboot/meta-data <<EOF
      instance-id: focal-autoinstall
      EOF    
          	
    • create user-data
    • The autoinstall file is YAML.
      At top level it must be a mapping containing the keys described in this document.
      
      # cat > /var/lib/tftpboot/user-data <<'EOF'
      #cloud-config
      autoinstall:
        version: 1
        # use interactive-sections to avoid an automatic reboot
        #interactive-sections:
        #  - locale
        keyboard: {layout: us, variant: ''}
        locale: en_US.UTF-8  
        # interface name will probably be different
        network:
          network:
            version: 2
            renderer: NetworkManager                  
        apt:
          # even set to no/false, geoip lookup still happens
          #geoip: no
          preserve_sources_list: false
          primary:
          - arches: [amd64, i386]
            uri: http://us.archive.ubuntu.com/ubuntu
          - arches: [default]
            uri: http://ports.ubuntu.com/ubuntu-ports
        # this creates an efi partition, /boot partition, and root(/) lvm volume
        storage:
          grub:
            reorder_uefi: False
          swap:
            size: 0
          config:
          - {ptable: gpt, path: /dev/nvme0n1, preserve: false, name: '', grub_device: false,
            type: disk, id: disk-nvme0n1}
          - {device: disk-nvme0n1, size: 536870912, wipe: superblock, flag: boot, number: 1,
            preserve: false, grub_device: true, type: partition, id: partition-nvme0n11}
          - {fstype: fat32, volume: partition-nvme0n11, preserve: false, type: format, id: format-2}
          - {device: disk-nvme0n1, size: 1073741824, wipe: superblock, flag: linux, number: 2,
            preserve: false, grub_device: false, type: partition, id: partition-nvme0n12}
          - {fstype: ext4, volume: partition-nvme0n12, preserve: false, type: format, id: format-0}
          - {device: disk-nvme0n1, size: -1, flag: linux, number: 3, preserve: false,
            grub_device: false, type: partition, id: partition-nvme0n13}
          - name: vg-0
            devices: [partition-nvme0n13]
            preserve: false
            type: lvm_volgroup
            id: lvm-volgroup-vg-0
          - {name: lv-root, volgroup: lvm-volgroup-vg-0, size: 100%, preserve: false,
            type: lvm_partition, id: lvm-partition-lv-root}
          - {fstype: ext4, volume: lvm-partition-lv-root, preserve: false, type: format,
            id: format-1}
          - {device: format-1, path: /, type: mount, id: mount-2}
          - {device: format-0, path: /boot, type: mount, id: mount-1}
          - {device: format-2, path: /boot/efi, type: mount, id: mount-3}      
        # r00tme
        identity: {hostname: focal-autoinstall, password: $6$.c38i4RIqZeF4RtR$hRu2RFep/.6DziHLnRqGOEImb15JT2i.K/F9ojBkK/79zqY30Ll2/xx6QClQfdelLe.ZjpeVYfE8xBBcyLspa/,
          username: ubuntu}
      
      
        ssh:
          allow-pw: true
          authorized-keys: []
          install-server: true
      
      write_files:
        # override the kernel package
        - path: /run/kernel-meta-package
          content: |
            linux-virtual
          owner: root:root
          permissions: "0644"
        # attempt to also use an answers file by providing a file at the default path.  It did not seem to have any effect
        #- path: /subiquity_config/answers.yaml
        #  content: |
        #    InstallProgress:
        #      reboot: no
        #  owner: root:root
        #  permissions: "0644"
      EOF
          	

BF NIC (ARM64)

  • Extract the OS image and copy the required PXE boot components:
  • 
    mount -t iso9660 -o loop CentOS-7-aarch64-Everything.iso /mnt
    mkdir -p /var/lib/tftpboot/centos/7.4
    cp /mnt/EFI/BOOT/BOOTAA64.EFI /var/lib/tftpboot/
    cp /mnt/EFI/BOOT/grubaa64.efi /var/lib/tftpboot/
    cp /mnt/images/pxeboot/vmlinuz /var/lib/tftpboot/centos/7.4
    cp /mnt/images/pxeboot/initrd.img /var/lib/tftpboot/centos/7.4/initrd-orig.img
    	
  • Patch the initrd with the eMMC driver and Tmfifo (Rshim network) driver
  •   
    mkdir -p /tmp/.bfcentos
    mkdir -p $/tmp/.bfinstdd
    cd /tmp/.bfcentos
    xzcat /var/lib/tftpboot/centos/7.4/initrd-orig.img | cpio -idm
    mount /root/BlueField-1.0.alpha3.10409/distro/rhel/bluefield_dd/bluefield_dd-4.11.0-22.el7a.aarch64.iso /tmp/.bfinstdd
    mkdir -p usr/lib/modules/4.11.0-22.el7a.aarch64/updates
    cp /tmp/.bfinstdd/lib/modules/4.11.0-22.el7a.aarch64/updates/dw_mmc*.ko usr/lib/modules/4.11.0-22.el7a.aarch64/updates/
    cp /tmp/.bfinstdd/lib/modules/4.11.0-22.el7a.aarch64/updates/tmfifo.ko usr/lib/modules/4.11.0-22.el7a.aarch64/updates/
    cp /root/BlueField-1.0.alpha3.10409/distro/rhel/bluefield_dd/bluefield_dd-4.11.0-22.el7a.aarch64.iso ./bluefield_dd.iso
    umount /tmp/.bfinstdd; rmdir /tmp/.bfinstdd
    chown root:root * -R
    depmod -b /tmp/.bfcentos 4.11.0-22.el7a.aarch64
    find . | cpio -oc | xz --check=crc32 --lzma2=dict=32MiB >
    /var/lib/tftpboot/centos/7.4/initrd.img
    	
If using a different version, use the corresponding bluefield_dd.iso.
If none is found, compile one yourself via:

source /path/to/SDK/environment-setup-aarch64-poky-linux; unset LDFLAGS; ./build-dd.sh /path/to/kernel-devel-4.11.0-44.el7a.aarch64.rpm

HTTP Server

Installation


sudo apt install apache2

Configuration

Configure apache to serve files from the tftp directory:

$ sudo -i
# cat > /etc/apache2/conf-available/tftp.conf <<EOF
<Directory /var/lib/tftpboot>
        Options +FollowSymLinks +Indexes
        Require all granted
</Directory>
Alias /tftp /var/lib/tftpboot
EOF
Enable tftp configuration file for apache2:

$ sudo a2enconf tftp
Enabling conf tftp.
To activate the new configuration, you need to run:
  systemctl reload apache2
Re-start the apache2 service:

$ sudo systemctl restart apache2

DHCP server

Installation


sudo apt install isc-dhcp-server
sudo systemctl status isc-dhcp-server

Configuration

  • /etc/default/isc-dhcp-server
  • 
    INTERFACESv4="eno1"
    	
  • /etc/dhcp/dhcpd.conf
  • 
    allow booting;
    allow bootp;
    
    subnet 192.168.2.0 netmask 255.255.255.0 {
      range dynamic-bootp 192.168.2.10 192.168.2.50;
      option broadcast-address 192.168.2.255;
      option routers 192.168.2.1;
      option domain-name-servers 8.8.8.8, 10.15.2.29, 10.15.2.16;
      option domain-search "internal.tilera.com", "mtbu.labs.mlnx";
      next-server 192.168.2.51;
    #  filename "grubnetaa64.efi.signed";
      filename "pxelinux.0"; # x86 , working for vbox
    #  filename "grubnetx64.efi.signed"; # not working for vbox
    }
    	
    In this ex.,
    • 192.168.2.1 is the IP of the gateway
    • 192.168.2.51 is the IP of the DHCP/TFTP/HTTP servers
    • Simply adding the allow bootp directive to enable the BOOTP server
    • The router option is the gateway address which access to the internet for instance
    • The domain-name-servers option indicate the dns you want to use
    • next-server
    • To specify the host address of the server from which the initial boot file (specified in the filename statement) is to be loaded.
    • The filename option should be the name of the file “boot loader” which will be retrieved via TFTP.

Restart DHCPD


$ sudo systemctl restart isc-dhcp-server

Check DHCPD status


$ journalctl -fu isc-dhcp-server
$ grep DHCP /var/log/syslog

Setup Notice

Configuration

The following 2 files are related to the LAN network setting(192.168.x.0):
  • /etc/dhcp/dhcpd.conf
  • /var/lib/tftpboot/grub/grub.cfg
If the subnet is changed, the above 2 files need to be changed accordingly.

Re-start servers

Re-start servers every time you changed the networking setting:
	
sudo systemctl restart tftpd-hpa
sudo systemctl restart apache2 
$ sudo systemctl restart isc-dhcp-server
  • DHCP log
  • 
    $ journalctl -fu isc-dhcp-server  
    Apr 14 12:52:20 jerry-Precision-3541 dhcpd[7305]: DHCPDISCOVER from 8c:8c:aa:54:8d:29 via eno1
    Apr 14 12:52:21 jerry-Precision-3541 dhcpd[7305]: DHCPOFFER on 192.168.2.10 to 8c:8c:aa:54:8d:29 (ubuntu-server) via eno1
    Apr 14 12:52:21 jerry-Precision-3541 dhcpd[7305]: DHCPREQUEST for 192.168.2.10 (192.168.2.51) from 8c:8c:aa:54:8d:29 (ubuntu-server) via eno1
    Apr 14 12:52:21 jerry-Precision-3541 dhcpd[7305]: DHCPACK on 192.168.2.10 to 8c:8c:aa:54:8d:29 (ubuntu-server) via eno1
    	

PXE booting in KVM

Installation


$ sudo apt install virt-manager

Create a VM to PXEBOOT the installer

Use virt-manager to create an instance:

$ sudo virt-manager
Create a new virtual machine
  • File -> "New Virtual Machine"
  • * Network Boot(PXE)
  • Choose the operating system you are installing
  • Choose Memory and CPU settings

PXE booting in Virtualbox

Add the PXE boot functionality in Virtualbox

After a fresh installation of VirtualBox, there are no extensions packages installed.
If you want to use pxe booting in virtualbox, be sure to install the Extension pack.

  • Starting the virtualbox
  • File -> Preferences
    • Go to the Extensions section
    • Click the Add a new package button (the icon with a green plus) to add the extension pack.
This will include the PXE boot functionality.


$ VBoxManage list extpacks
Extension Packs: 1
Pack no. 0:   Oracle VM VirtualBox Extension Pack
Version:      6.1.18
Revision:     142142
Edition:      
Description:  Oracle Cloud Infrastructure integration, USB 2.0 and USB 3.0 Host Controller, Host Webcam, VirtualBox RDP, PXE ROM, Disk Encryption, NVMe.
VRDE Module:  VBoxVRDP
Usable:       true 
Why unusable: 
Then reboot the computer:
Enter the BIOS setup to disable the “Secure Boot” so that the extension pack (kernel modules) can be loaded after starting the VirtualBox .

Creating a pxe-booting basebox in Virtualbox

  • On the Settings -> System -> Motherboard
  • Only enable the Network in the “Boot Order
  • On the Settings -> Network -> Adapter1
    • Enable Network Adapter
    • Bridge Adapter
    • Adapter Type
    • PCnet-FAST III
PXE booting with failure in office LAN:

"(initramfs) wget: bad address 'releases.ubuntu.com'"
Dump /etc/resolv.conf:

(initramfs) cat /etc/resolv.conf
nameserver 10.15.2.29
nameserver 10.15.2.16
search example.org internal.tilera.com mtbu.labs.mlnx example.org internal.tilera.com mtbu.labs.mlnx.
(initramfs) 
This needs to be fixed in /etc/dhcp/dhcpd.conf:

subnet 192.168.100.0 netmask 255.255.255.0 {
...
option domain-name-servers 192.168.100.1, 10.15.2.29, 10.15.2.16;
...
}

Netbooting the live server installer

PXE network booting goes like this:
  1. The to-be-installed machine boots, and is directed to network boot.
  2. The DHCP/bootp server tells the machine where to get pxelinux.0.
  3. The machine’s EFI firmware downloads pxelinux.0 over tftp and executes it.
  4. pxelinux.0 downloads configuration(via tftp) which tells where to download the kernel, initrd and kernel command line to use.
  5. The initrd looks at the kernel command line to see where to download the server ISO imagefrom, downloads it and mounts it as a loop device.
This document will briefly describe how to configure dnsmasq to perform both the DHCP/bootp and tftp protocols.

dnsmasq is a lightweight DNS, TFTP, PXE, router advertisement and DHCP server.

Configuring DHCP/bootp and tftp

  1. Install dnsmasq
  2. 
    sudo apt install dnsmasq    
        
  3. Configure dnsmasq
  4. At startup, dnsmasq reads /etc/dnsmasq.conf, if it exists.
    The format of this file consists of one option per line, exactly as the long options detailed in the OPTIONS section in man dnsmasq but without the leading "--".
    • --interface=interface name
    • Listen only on the specified interface(s). Dnsmasq automatically adds the loopback (local) interface to the list of interfaces to use when the --interface option is used.
    • --bind-interfaces
    • dnsmasq binds the wildcard address, even when it is listening on only some interfaces.
    • --dhcp-range=[tag:tag[,tag:tag],][set:tag,]start-addr[,end-addr|mode][,netmask[,broadcast]][,lease time]
    • Enable the DHCP server. Addresses will be given out from the range start-addr to end-addr
    • --dhcp-boot=[tag:tag,]filename,[servername[,server address|tftp_servername]]
    • Set BOOTP options to be returned by the DHCP server.
      Server name and address are optional: if not provided, the name is left empty, and the address set to the address of the machine running dnsmasq. If dnsmasq is providing a TFTP service (see --enable-tftp ) then only the filename is required here to enable network booting.
    • --enable-tftp[=interface[,interface]]
    • Enable the TFTP server function. Only reading is allowed
    • --tftp-root=directory[,interface]
    • Look for files to transfer using TFTP relative to the given directory.
    /etc/dnsmasq.conf:
    
    interface=your interface
    bind-interfaces
    dhcp-range=your interface,192.168.0.100,192.168.0.200
    dhcp-boot=pxelinux.0
    enable-tftp
    tftp-root=/var/ftpd
    	
  5. Plug off the Ethernet cable then configure IP for that interface
  6. 
    $ sudo ifconfig eno1 192.168.0.1 netmask 255.255.255.0 up    
        
  7. restart dnsmasq
  8.   
    sudo systemctl restart dnsmasq.service
      

Serving PXELINUX and its configuration

  1. Download the grub binary to load via PXE
  2. 
    $ sudo mkdir -p /srv/tftp    
    $ sudo wget http://archive.ubuntu.com/ubuntu/dists/focal/main/uefi/grub2-amd64/current/grubnetx64.efi.signed -O /var/ftpd/pxelinux.0  
    	
  3. Download the latest live server ISO image you want to install
  4. 
    $ sudo wget http://old-releases.ubuntu.com/releases/20.04/ubuntu-20.04.2-live-server-amd64.iso -O /var/ftpd/ubuntu-20.04.2-live-server-amd64.iso 
    	
  5. Copy the kernel and initrd from the ISO image to were the dnsmasq serves tftp from
  6. 
    $ sudo mount /var/tftpd/ubuntu-20.04.2-live-server-amd64.iso /mnt
    $ sudo cp /mnt/casper/{vmlinuz,initrd} /srv/tftp/
        
  7. Create /srv/tftp/pxelinux.cfg/default
  8. 
      DEFAULT install
    LABEL install
      KERNEL vmlinuz
      INITRD initrd
      APPEND root=/dev/ram0 ramdisk_size=1500000 ip=dhcp url=http://releases.ubuntu.com/focal/ubuntu-20.04.2-live-server-amd64.iso
    

Netbooting the Live Server Installer via UEFI PXE on Arm (aarch64, arm64) and x86_64 (amd64)

留言

熱門文章