# PXE Server setup
預啟動執行環境(Preboot eXecution Environment,PXE,也被稱為預執行環境)提供了一種使用網路介面(Network Interface)啟動電腦的機制。這種機制讓電腦的啟動可以不依賴本地資料儲存裝置(如硬碟)或本地已安裝的作業系統。
PXE 伺服器必須要提供至少含有 DHCP 以及 TFTP :
DHCP 服務必須要能夠提供用戶端的網路參數之外,還得要告知用戶端 TFTP 所在的位置為何才行
TFTP 則是提供用戶端 boot loader 及 kernel file 下載點的重要服務

**本次教學使用的方案為上圖中的DHCP+TFTP+NFS**
---
安裝套件
---
- sudo apt-get install -y tftpd-hpa isc-dhcp-server lftp openbsd-inetd nfs-kernel-server grub-efi-amd64 grub-efi-amd64-bin grub-efi-amd64-signed grub-imageboot grub-pc-bin grub2-splashimages shim shim-signed
---
DHCP 設定
---
首先編輯 /etc/dhcp/dhcpd.conf檔案,在下面配置 DHCP:
**for ipv4**
```typescript
ddns-update-style none;
default-lease-time 600;
max-lease-time 7200;
log-facility local7;
subnet 10.21.10.0 netmask 255.255.255.0 {
range 10.21.10.200 10.21.10.250;
option subnet-mask 255.255.255.0;
option routers 10.21.10.254;
option broadcast-address 10.21.10.255;
filename "pxelinux.0";
#UEFI
#filename "uefi/syslinux.efi";
}
```
**For ipv6**
```typescript
$ cd /etc/dhcp/
$ sudo cp dhcpd.conf dhcpd6.conf
$ touch /var/lib/dhcp/dhcpd6.leases
$ sudo chmod 666 /var/lib/dhcp/dhcpd6.leases
$ chown dhcpd:dhcpd /var/lib/dhcp/dhcpd6.leases
$ sudo nano dhcpd6.conf
```
內容如下
```typescript
default-lease-time 600;
max-lease-time 7200;
log-facility local7;
subnet6 2001:db8:0:1::/64 {
# Range for clients
range6 2001:db8:0:1::129 2001:db8:0:1::254;
# Additional options
option dhcp6.name-servers fec0:0:0:1::1;
option dhcp6.domain-search "domain.example";
filename "pxelinux.0";
#UEFI
option dhcp6.bootfile-url "tftp://[2001:db8:f00f:cafe::1]/uefi/syslinux.efi";
# Prefix range for delegation to sub-routers
prefix6 2001:db8:0:100:: 2001:db8:0:f00:: /56;
# Example for a fixed host address (可加,可不加)
#host specialclient {
#host-identifier option dhcp6.client-id 00:01:00:01:4a:1f:ba:e3:60:b9:1f:01:23:45;
#fixed-address6 2001:db8:0:1::127;
#}
}
```
**指定DHCP作用之網路卡**
```typescript=
sudo vim /etc/default/isc-dhcp-server
```
```typescript
INTERFACES="eth0"
```
<font color=#0000FF>_"eth0"依照使用者網路卡名稱的不同會有不同的命名方式,請自行修改_</font>
<br><br/>
**建立ipv6 init file**
```typescript
$ sudo cp /etc/init.d/isc-dhcp-server /etc/init.d/isc-dhcp-server6
$ sudo sed -i s/isc-dhcp-server/isc-dhcp-server6/ /etc/init.d/isc-dhcp-server6
$ sudo sed -i s/dhcpd.conf/dhcpd6.conf/ /etc/init.d/isc-dhcp-server6
$ sudo sed -i s/dhcpd.pid/dhcpd6.pid/ /etc/init.d/isc-dhcp-server6
```
**完成後,重新啟動 DHCP 服務:**
```typescript
$ sudo service isc-dhcp-server restart
$ sudo service isc-dhcp-server6 restart
* Stopping ISC DHCP server dhcpd [fail]
* Starting ISC DHCP server dhcpd [ OK ]
```
**透過/var/lib/dhcp/dhcpd.leases驗證DHCP server是否正常運作
如有正常運作,將會看到DHCP server分派IP之列表**
```typescript
cat /var/lib/dhcp/dhcpd.leases
```
```typescript
lease 192.168.123.71 {
starts 4 2021/06/10 02:13:39;
ends 0 2021/06/20 02:13:39;
cltt 4 2021/06/10 12:30:35;
binding state active;
next binding state free;
rewind binding state free;
hardware ethernet a4:ae:12:71:aa:6f;
uid "\001\244\256\022q\252o";
set vendor-class-identifier = "udhcp 1.21.1";
}
lease 192.168.123.69 {
starts 4 2021/06/10 06:26:05;
ends 0 2021/06/20 06:26:05;
cltt 4 2021/06/10 12:01:23;
binding state active;
next binding state free;
rewind binding state free;
hardware ethernet 00:e0:4c:68:00:50;
uid "\001\000\340Lh\000P";
set vendor-class-identifier = "MSFT 5.0";
}
lease 192.168.123.63 {
starts 4 2021/06/10 07:06:58;
ends 0 2021/06/20 07:06:58;
cltt 4 2021/06/10 10:06:26;
binding state active;
next binding state free;
rewind binding state free;
hardware ethernet e6:26:29:3f:52:0b;
uid "\001\346&)?R\013";
set vendor-class-identifier = "MSFT 5.0";
}
lease 192.168.123.66 {
starts 4 2021/06/10 13:55:42;
ends 0 2021/06/20 13:55:42;
cltt 4 2021/06/10 15:13:38;
binding state active;
next binding state free;
rewind binding state free;
hardware ethernet a4:ae:12:71:aa:34;
uid "\001\244\256\022q\2524";
set vendor-class-identifier = "udhcp 1.21.1";
}
lease 192.168.123.73 {
starts 4 2021/06/10 20:21:17;
ends 0 2021/06/20 20:21:17;
cltt 4 2021/06/10 20:21:17;
binding state active;
next binding state free;
rewind binding state free;
hardware ethernet a4:ae:12:6f:7b:b0;
uid "\001\244\256\022o{\260";
set vendor-class-identifier = "udhcp 1.21.1";
}
```
---
TFTP Server 設定
---
**編輯/etc/default/tftpd-hpa檔案:**
```typescript
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/var/lib/tftpboot"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="--secure"
RUN_DAEMON="yes"
OPTIONS="-l -s /var/lib/tftpboot"
```
**接著設定 Boot 時啟動服務,以及重新啟動相關服務:**
```typescript
$ sudo update-rc.d tftpd-hpa defaults
$ sudo service tftpd-hpa start
```
---
建立開機選單
---
>syslinux是一個功能強大的引導載入程式,而且兼容各種介質。它的目的是簡化首次安裝Linux的時間,並建立修護或其它特殊用途的啟動盤。它的安裝很簡單,一旦安裝syslinux好之後,sysLinux啟動盤就可以引導各種基於DOS的工具,以及MS-DOS/Windows或者任何其它作業系統。不僅支援採用BIOS結構的主機板,而且從6.0版也開始支援採用EFI結構的新型主機板。
>次教學選用syslinux作為PXE選單與引導載入程式
作為載入Linux與Windows的第一步
**完成後安裝 syslinux:**
```typescript
sudo apt-get -y install syslinux
```
**複製 syslinux 設定檔至/var/lib/tftpboot目錄中:**
for BIOS
```typescript
sudo cp /usr/lib/syslinux/menu.c32 /var/lib/tftpboot
sudo cp /usr/lib/syslinux/vesamenu.c32 /var/lib/tftpboot
sudo cp /usr/lib/syslinux/pxelinux.0 /var/lib/tftpboot
sudo cp /usr/lib/syslinux/memdisk /var/lib/tftpboot
sudo cp /usr/lib/syslinux/mboot.c32 /var/lib/tftpboot
sudo cp /usr/lib/syslinux/chain.c32 /var/lib/tftpboot
```
for UEFI
```typescript=
mkdir /var/lib/tftpboot/uefi
cp /var/lib/tftpboot/pxelinux.cfg var/lib/tftpboot/uefi/ -rf
sudo cp /usr/lib/SYSLINUX.EFI/efi64/syslinux.efi /var/lib/tftpboot/uefi
sudo cp /usr/lib/syslinux/modules/efi64/ldlinux.e64 /var/lib/tftpboot/uefi
sudo cp /usr/lib/syslinux/modules/efi64/libcom32.c32 /var/lib/tftpboot/uefi
sudo cp /usr/lib/syslinux/modules/efi64/libutil.c32 /var/lib/tftpboot/uefi
sudo cp /usr/lib/syslinux/modules/efi64/vesamenu.c32 /var/lib/tftpboot/uefi
```
**建立/var/lib/tftpboot/pxelinux.cfg目錄:**
```typescript
$ sudo mkdir /var/lib/tftpboot/pxelinux.cfg
```
**接著編輯/var/lib/tftpboot/pxelinux.cfg/default檔案,設定開機選單,以下為簡單設定範例:**
```typescript
EFAULT vesamenu.c32
TIMEOUT 100
PROMPT 0
MENU INCLUDE pxelinux.cfg/pxe.conf
NOESCAPE 1
LABEL localboot
MENU LABEL Boot from local disk
LOCALBOOT 0
LABEL Ubuntu 20.04 Desktop
MENU LABEL Install Ubuntu 20.04 Desktop
kernel ubuntu/20.04/casper/vmlinuz
append nfsroot=192.168.123.1:/var/lib/tftpboot/ubuntu/20.04 netboot=nfs ip=dhcp boot=casper initrd=ubuntu/20.04/casper/initrd systemd.mask=tmp.mount --
LABEL Ubuntu 20.10 Desktop
MENU LABEL Install Ubuntu 20.10 Desktop
kernel ubuntu/20.10/casper/vmlinuz
append nfsroot=192.168.123.1:/var/lib/tftpboot/ubuntu/20.10 netboot=nfs ip=dhcp boot=casper initrd=ubuntu/20.10/casper/initrd systemd.mask=tmp.mount --
LABEL winpe
MENU LABEL Boot Windows PE from network
KERNEL memdisk
INITRD winpe.iso
APPEND iso raw
ENDTEXT
```
**美化PXE開機選單,並存多個作業系統並且可以使用光棒選擇**
```typescript
sudo /var/lib/tftpboot/pxelinux.cfg/pxe.conf
```
```typescript
MENU TITLE PXE Server
NOESCAPE 1
ALLOWOPTIONS 1
PROMPT 0
MENU WIDTH 80
MENU ROWS 14
MENU TABMSGROW 24
MENU MARGIN 10
MENU COLOR border 30;44 #ffffffff #00000000 std
```

---
NFS Server 設定
---
```typescript
sudo nano /etc/exports
```
```typescript
/var/lib/tftpboot/ *(ro,async,no_root_squash,no_subtree_check)
```
>參數
* rw:read-write,可讀寫的權限;
* ro:read-only,唯讀的權限;
* sync:資料同步寫入到記憶體與硬碟當中;
* async:資料會先暫存於記憶體當中,而非直接寫入硬碟。
* no_root_squash:
登入 NFS 主機使用分享目錄的使用者如果是 root,對於分享的目錄具有 root 的權限。
極不安全,不建議使用。
* root_squash:
登入 NFS 主機使用分享目錄的使用者如果是 root,權限將被壓縮成匿名使用者,
通常他的 UID 與 GID 都會變成 nobody(nfsnobody) 那個系統帳號的身份;
* all_squash:
不論登入 NFS 的使用者身份為何,都會被壓縮成為匿名使用者,通常是 nobody(nfsnobody) 。
* anonuid:
anon 意指 anonymous (匿名者),自訂匿名使用者的 UID。
* anongid:自訂匿名使用者的是變成 GID。
重啟nfs服務
```typescript
sudo /etc/init.d/nfs-kernel-server restart
```
---
新增啟動印象檔(Linux)
---
**以Ubuntu 20.10為範例**
```typescript
$ wget http://ubuntu.cs.nctu.edu.tw/ubuntu-release/20.10/ubuntu-20.10-desktop-amd64.iso
$ sudo mount ubuntu-20.10-desktop-amd64.iso /mnt
$ sudo mkdir /var/lib/tftpboot/ubuntu/
$ sudo mkdir /var/lib/tftpboot/ubuntu/20.10
$ sudo cp -r /mnt/.disk /var/lib/tftpboot/ubuntu/20.10
$ sudo cp -r /mnt/* /var/lib/tftpboot/ubuntu/20.10
```
---
新增啟動印象檔(Windows)
---
**透過PXE server安裝Windows的思路如下:**
1. 製作WinPE開機iso
2. 透過PXE載入WinPE
3. 從WinPE連線到網路磁碟
4. 進入網路磁碟內安裝Windows 7 or 10或是server...等
**製作WinPE開機iso**
```typescript
$ sudo apt-get install -y samba genisoimage wimtools cabextract
$ wget https://download.microsoft.com/download/8/E/9/8E9BBC64-E6F8-457C-9B8D-F6C9A16E6D6A/KB3AIK_EN.iso
$ sudo mount KB3AIK_EN.iso /mnt
$ sudo mkwinpeimg --iso --arch=amd64 --waik-dir=/mnt/ /var/lib/tftpboot/winpe.iso
$ sudo umount /mnt
```
**從PXE開機到WinPE後連線到網路磁碟**
```typescript
net use z: \\192.168.10.1\windows10
```
**進入網路磁碟內安裝Windows 7 or 10或是server...等**
```typescript
z:\setup.exe
```



