PXE无U盘网络安装OracleLinux系统
2024-01-03 07:56:53

PXE无U盘网络安装OracleLinux系统

前置操作:

1698910942393

路由器一个(192.168.6.1)

将IP设置为192.168.6.1,因为我将要使用192.168.6.3这台服务器去替代路由器功能,因此需要进入路由器,关闭DHCP服务。

注意:有些路由器可能不能修改局域网的IP网段,比如下图这个小米路由器是192.168.31.0网段的。大家需要按照实际情况去进行操作。可以相应的将上图的6换成31。

1698913012969

笔记本一台(192.168.6.3)

需要预安装Linux环境,此处我选用Oraclelinux9.2,这是一个对标Centos9.2的系统,并且将IP配置为192.168.6.3,可以在终端输入nmtliEdit a connectionEdit,改成如下图信息:

1698912886439

把开机启动网络也开启起来,然后点击最后的OK即可。

1698913206327

待安装的服务器若干台

在开机过程中,疯狂按Del键,进入bios配置开机启动顺序,如下图,去到boot界面后,按shift + 加号上升顺序,按F10,保存并且退出。

1698912631590

镜像准备

第一步:下载镜像

以下命令是将镜像下载到/home目录,当然你可以使用其他下载工具下载你想要想系统镜像。

1
wget -P /home -c https://yum.oracle.com/ISOS/OracleLinux/OL9/u2/x86_64/OracleLinux-R9-U2-x86_64-dvd.iso

第二步:挂载镜像

创建目录/home/linuxiso,以只读的方式,挂载iso到/home/linuxiso

1
2
mkdir /home/linuxiso/
mount -t iso9660 /home/OracleLinux-R9-U2-x86_64-dvd.iso /home/linuxiso -o loop,ro

第三步:将挂载的ISO内容复制到文件夹

因为既要将镜像文件作为TFTP服务使用,又要作为WEB使用,于是就直接复制到/var/lib/tftpboot/system_iso/oraclelinux/

1
2
mkdir -p /var/lib/tftpboot/system_iso/oraclelinux/
cp -rf /home/linuxiso/* /var/lib/tftpboot/system_iso/oraclelinux/

第四步:卸载目录

卸载ISO磁盘

1
2
umount /home/linuxiso/
rm -rf /home/linuxiso/

服务安装

192.168.6.3这台服务器安装DHCP、TFTP、Nginx。

WEB服务Nginx

Nginx是一个受欢迎的Web 服务器,它也可以用作反向代理、负载均衡器、邮件代理和HTTP缓存。该软件由Igor Sysoev创建并于 2004 年公开发布,截至 2022 年 6 月,W3Tech 所有网站的 Web 服务器数量中 Nginx 以 33.6% 排名第一。

第一步:设置下载源

1
2
3
4
5
echo "[nginx]
name=nginx repo
baseurl=https://nginx.org/packages/centos/9/x86_64/
gpgcheck=0
enabled=1" > /etc/yum.repos.d/nginx.repo

第二步:安装Nginx

1
yum install nginx -y

第三步:开启防火墙

1
2
firewall-cmd --permanent --add-port={80/tcp,443/tcp}
firewall-cmd --reload

第四步:配置Selinux权限

三种方式都可以,看具体情况而定,此处建议使用方式1:

方式1:赋予/home/oraclelinux目录为web目录,让nginx可以访问

1
2
3
4
5
6
setsebool -P httpd_can_network_connect 1
setsebool -P tftp_anon_write 1
semanage fcontext -a -t public_content_t "/var/lib/tftpboot(/.*)?"
# 临时更改selinux权限
# chcon -Rv --type=public_content_t /var/lib/tftpboot/
restorecon -F -R -v /var/lib/tftpboot

方式2:通过审计日志生成允许策略

会在当前目录生成后缀为*.pp*.te的文件

1
2
ausearch -c 'nginx' --raw | audit2allow -M my-nginx
ausearch -c 'tftp' --raw | audit2allow -M my-tftp

应用审计内容

1
2
semodule -i my-nginx.pp
semodule -i my-tftp.pp

semodule的参数:

选项 含义
-l 显示安装的模块
-R 重装策略模块
-B 建立和重装策略模块
-i <策略模块> 安装一个新的模块
-u <策略模块> 升级策略模块
-e <策略模块> 激活策略模块
-d <策略模块> 禁用策略模块
-b <策略模块> 安装新的基础模块
-r <策略模块> 删除策略模块

方式3:直接关闭selinux

1
setenforce 0

第五步:设置Nginx配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
echo "server {
listen 80;
server_name 0.0.0.0;
autoindex on;
root /var/lib/tftpboot/system_iso/;

# 这是oraclelinux
location /oraclelinux {
alias /var/lib/tftpboot/system_iso/oraclelinux;
index index.html index.htm;
}

# 其他系统一样
# location /centoslinux {
# alias /var/lib/tftpboot/system_iso/centoslinux;
# index index.html index.htm;
# }
}" > /etc/nginx/conf.d/default.conf

第六步:设置开机启动

1
2
systemctl enable --now nginx
systemctl restart nginx

TFTP服务

TFTP代表”Trivial File Transfer Protocol”,是一种用于在计算机和设备之间传输文件的简单网络协议。TFTP的设计目标是提供一种轻量级的文件传输方法,通常用于引导启动、配置文件传输和固件升级等用途。它是FTP(File Transfer Protocol)的精简版本,因此称为”trivial”(简单)。

第一步:安装TFTP服务

1
yum install tftp-server -y

第二步:防火墙放行TFTP服务

1
2
firewall-cmd --add-service=tftp --permanent
firewall-cmd --reload

第三步:从镜像复制一些文件出来

因为提取一些启动必须要的文件,需要在镜像中寻找syslinux-tftpboot-6.04-0.20.el9.noarch.rpm文件并复制到/tmp/linuxiso_rpm_temp临时文件夹,待处理。为了方便,我直接使用文件查找命令。

1
2
mkdir /tmp/linuxiso_rpm_temp
find /var/lib/tftpboot/system_iso/oraclelinux -name "syslinux-tftpboot*" | xargs -I {} cp {} /tmp/linuxiso_rpm_temp/

第四步:rpm文件解压并复制

通常,EFI 系统分区 (ESP) 上的 EFI/redhat/grubx64.efi是 GRUB 二进制文件,而 EFI/redhat/shimx64.efi是 shim 的二进制文件。

安全启动(Secure Boot)开启的状态下,未签名的 GRUB 版本(grubx64.efi)将无法启动,因此 shim 弥补了缺陷并添加了自己的安全工具,与 安全启动(Secure Boot) 类似。

shimx64.efi 它提供了一种在安全启动(Secure Boot)开启的状态下使用的方法。实际上,shim 会在固件中注册自己,然后在它的目录中启动一个名为 grubx64.efi的程序,在没有启用 安全启动(Secure Boot) 的计算机中,启动 shimx64.efi 和启动 grubx64.efi是一样的

/var/lib/tftpboot/pxelinux文件夹是引导相关的镜像

1
2
3
4
5
mkdir /var/lib/tftpboot/pxelinux
find /tmp/linuxiso_rpm_temp/ -type f -name "syslinux-tftpboot*.rpm" -exec sh -c 'mkdir "/tmp/linuxiso_rpm_temp/$(basename {} .rpm)"' \;
find /tmp/linuxiso_rpm_temp/ -type f -name "syslinux-tftpboot*.rpm" -exec sh -c 'rpm2cpio {} | cpio -dimv -D "/tmp/linuxiso_rpm_temp/$(basename {} .rpm)"' \;

find /tmp/linuxiso_rpm_temp/ -wholename "*tftpboot/*" -exec cp -rf {} /var/lib/tftpboot/pxelinux \;

第五步:复制启动文件到TFTP镜像目录

在镜像中复制vmlinuzinitrd.img启动镜像文件到/var/lib/tftpboot/pxelinux/images/oraclelinux待使用。

1
2
3
mkdir -p /var/lib/tftpboot/pxelinux/images/oraclelinux
find /var/lib/tftpboot/system_iso/oraclelinux/ -wholename "*pxeboot/vmlinuz" -exec cp {} /var/lib/tftpboot/pxelinux/images/oraclelinux \;
find /var/lib/tftpboot/system_iso/oraclelinux/ -wholename "*pxeboot/initrd.img" -exec cp {} /var/lib/tftpboot/pxelinux/images/oraclelinux \;

第五步:配置Pxelinux

1
mkdir /var/lib/tftpboot/pxelinux/pxelinux.cfg

重定向内容到/var/lib/tftpboot/pxelinux/pxelinux.cfg/default文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
echo "default vesamenu.c32
prompt 1
timeout 600

display boot.msg

label linux
menu label ^Install system
menu default
kernel images/oraclelinux/vmlinuz
append initrd=images/oraclelinux/initrd.img ip=dhcp inst.repo=http://192.168.6.3/oraclelinux/
label vesa
menu label Install system with ^basic video driver
kernel images/oraclelinux/vmlinuz
append initrd=images/oraclelinux/initrd.img ip=dhcp inst.xdriver=vesa nomodeset inst.repo=http://192.168.6.3/oraclelinux/
label rescue
menu label ^Rescue installed system
kernel images/oraclelinux/vmlinuz
append initrd=images/oraclelinux/initrd.img rescue
label local
menu label Boot from ^local drive
localboot 0xffff" > /var/lib/tftpboot/pxelinux/pxelinux.cfg/default

第六步:UEFI支持

因为需要提取grubx64.efishimx64.efi文件,需要在镜像中寻找grub2-efi-x64-2.06-61.0.1.el9.x86_64.rpmshim-x64-15.7-1.0.3.el9.x86_64.rpm并复制到
/tmp/linuxiso_rpm_temp/目录下。

使用rpm2cpio命令解压后,将grubx64.efishimx64.efi两文件复制到/var/lib/tftpboot/uefi

/var/lib/tftpboot/uefi文件夹是”统一可扩展固件接口”相关文件,为了能引导系统启动还需要写一份配置文件,如下方的:/var/lib/tftpboot/uefi/grub.cfg,inst.repo是网络镜像路径,按实际的操作系统进行修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mkdir /var/lib/tftpboot/uefi
mkdir /tmp/linuxiso_rpm_temp

find /var/lib/tftpboot/system_iso/oraclelinux -name "grub2-efi-x64-2*x86_64.rpm" | xargs -I {} cp {} /tmp/linuxiso_rpm_temp/
find /tmp/linuxiso_rpm_temp/ -type f -name "grub2-efi-x64-2*x86_64.rpm" -exec sh -c 'rpm2cpio {} | cpio -dimv -D "/tmp/linuxiso_rpm_temp/$(basename {} .rpm)"' \;

find /var/lib/tftpboot/system_iso/oraclelinux -name "shim-x64*.x86_64.rpm" | xargs -I {} cp {} /tmp/linuxiso_rpm_temp/
find /tmp/linuxiso_rpm_temp/ -type f -name "shim-x64*.x86_64.rpm" -exec sh -c 'rpm2cpio {} | cpio -dimv -D "/tmp/linuxiso_rpm_temp/$(basename {} .rpm)"' \;

find /tmp/linuxiso_rpm_temp/ -wholename "*grubx64.efi" -exec cp {} /var/lib/tftpboot/uefi \;
find /tmp/linuxiso_rpm_temp/ -wholename "*shimx64.efi" -exec cp {} /var/lib/tftpboot/uefi \;

echo 'set timeout=60
menuentry 'oraclelinux' {
linuxefi /pxelinux/images/oraclelinux/vmlinuz ip=dhcp inst.repo=http://192.168.6.3/oraclelinux
initrdefi /pxelinux/images/oraclelinux/initrd.img
}' > /var/lib/tftpboot/uefi/grub.cfg

chmod -R 777 /var/lib/tftpboot/uefi

在编写本文档过程中,出现了一个bug,困扰了我很久,无论怎样,pxe就是启动不起来,出现error ../../grub-core/net/tftp.c这种错误,后来排查后,原来是权限问题。加上chmod -R 777 /var/lib/tftpboot/uefi就好了

完成以上步骤后可以删除/tmp/linuxiso_rpm_temp/临时目录。

1
rm -rf /tmp/linuxiso_rpm_temp/

第七步:启动TFTP

1
2
systemctl enable --now tftp.socket
systemctl restart tftp.socket

DHCP服务

DHCP(Dynamic Host Configuration Protocol)是一种网络协议,用于自动分配IP地址和其他网络配置信息给计算机和设备。

第一步:安装DHCP服务

1
yum install dhcp-server -y

第二步:修改DHCP配置文件

编辑/etc/dhcp/dhcpd.conf文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
echo 'option space pxelinux;
option pxelinux.magic code 208 = string;
option pxelinux.configfile code 209 = text;
option pxelinux.pathprefix code 210 = text;
option pxelinux.reboottime code 211 = unsigned integer 32;
option architecture-type code 93 = unsigned integer 16;

subnet 192.168.6.0 netmask 255.255.255.0 {
option routers 192.168.6.1;
option domain-name-servers 192.168.6.1;
range 192.168.6.100 192.168.6.200;

class "pxeclients" {
match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
next-server 192.168.6.3;
if option architecture-type = 00:07 {
filename "uefi/shimx64.efi";
}
else {
filename "pxelinux/pxelinux.0";
}
}

class "httpclients" {
match if substring (option vendor-class-identifier, 0, 10) = "HTTPClient";
option vendor-class-identifier "HTTPClient";
filename "http://192.168.6.3/oraclelinux/EFI/BOOT/BOOTX64.EFI";
}
}' > /etc/dhcp/dhcpd.conf && systemctl restart dhcpd

注解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// 这一行定义了一个名为"architecture-type"的自定义DHCP选项,其编码为93,数据类型为16位无符号整数。
option architecture-type code 93 = unsigned integer 16;

// 这一行指定了一个子网,范围从192.168.6.0到192.168.6.255,子网掩码255.255.255.0。
subnet 192.168.6.0 netmask 255.255.255.0 {
// 默认网关的IP地址
option routers 192.168.6.1;

// DNS服务器的IP地址
option domain-name-servers 192.168.6.1;

// DNS服务器的IP地址
range 192.168.6.100 192.168.6.200;

// 定义一个名为"pxeclients"的DHCP客户端类,用于匹配特定类型的客户端。
class "pxeclients" {
// 匹配字符串
match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";

// 跳转到192.168.6.3这台机器让其提供服务
next-server 192.168.6.3;
// 检查客户端的architecture-type选项的值。
// 如果该值等于00:07,则为客户端分配引导文件名"uefi/shimx64.efi"。
// 如果不等于00:07,则分配引导文件名"pxelinux/pxelinux.0"。
// 可根据https://www.rfc-editor.org/rfc/rfc4578#page-2查询对应的architecture-type选项的值
// Type Architecture Name
// ---- -----------------
// 0 Intel x86PC
// 1 NEC/PC98
// 2 EFI Itanium
// 3 DEC Alpha
// 4 Arc x86
// 5 Intel Lean Client
// 6 EFI IA32
// 7 EFI BC
// 8 EFI Xscale
// 9 EFI x86-64
if option architecture-type = 00:07 {
filename "uefi/shimx64.efi";
}
else {
filename "pxelinux/pxelinux.0";
}
}

// 定义一个名为"httpclients"的DHCP客户端类,用于匹配特定类型的客户端。
class "httpclients" {
// 匹配字符串
match if substring (option vendor-class-identifier, 0, 10) = "HTTPClient";

// 用于设置客户端的 vendor-class-identifier 值为 "HTTPClient"。
option vendor-class-identifier "HTTPClient";

// 引导的http文件名
filename "http://192.168.6.3/oraclelinux/EFI/BOOT/BOOTX64.EFI";
}
}

第三步:防火墙放行DHCP服务

1
2
firewall-cmd --add-service=dhcp --permanent
firewall-cmd --reload

第四步:启动DHCP

1
2
systemctl enable --now dhcpd
systemctl restart dhcpd

内网服务器网络安装系统过程

服务器只需要插上网线,且网络保持同一局域网。设置BISO的开机顺序为PXE启动。按开机键即可进入系统安装界面。

一键PXE服务脚本

可以以下方脚本为依据,改造成属于自己的PXE网络安装系统脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# /bin/bash

# 下载系统镜像并且挂载
wget -P /home -c https://yum.oracle.com/ISOS/OracleLinux/OL9/u2/x86_64/OracleLinux-R9-U2-x86_64-dvd.iso
mkdir /home/linuxiso/
mount -t iso9660 /home/OracleLinux-R9-U2-x86_64-dvd.iso /home/linuxiso -o loop,ro

# 复制镜像文件让其变成web内容
mkdir -p /var/lib/tftpboot/system_iso/oraclelinux/
cp -rf /home/linuxiso/* /var/lib/tftpboot/system_iso/oraclelinux/

# 卸载镜像ISO
umount /home/linuxiso/
rm -rf /home/linuxiso/

# 关闭selinux
setenforce 0

# nginx安装
echo "[nginx]
name=nginx repo
baseurl=https://nginx.org/packages/centos/9/x86_64/
gpgcheck=0
enabled=1" > /etc/yum.repos.d/nginx.repo
yum install nginx -y
firewall-cmd --permanent --add-port={80/tcp,443/tcp}
echo "server {
listen 80;
server_name 0.0.0.0;
autoindex on;
root /var/lib/tftpboot/system_iso/;

location /oraclelinux {
alias /var/lib/tftpboot/system_iso/oraclelinux;
index index.html index.htm;
}
}" > /etc/nginx/conf.d/default.conf
systemctl enable --now nginx
systemctl restart nginx

# TFTP服务安装
yum install tftp-server -y
firewall-cmd --add-service=tftp --permanent
mkdir /tmp/linuxiso_rpm_temp
find /var/lib/tftpboot/system_iso/oraclelinux -name "syslinux-tftpboot*" | xargs -I {} cp {} /tmp/linuxiso_rpm_temp/
mkdir /var/lib/tftpboot/pxelinux
find /tmp/linuxiso_rpm_temp/ -type f -name "syslinux-tftpboot*.rpm" -exec sh -c 'mkdir "/tmp/linuxiso_rpm_temp/$(basename {} .rpm)"' \;
find /tmp/linuxiso_rpm_temp/ -type f -name "syslinux-tftpboot*.rpm" -exec sh -c 'rpm2cpio {} | cpio -dimv -D "/tmp/linuxiso_rpm_temp/$(basename {} .rpm)"' \;
find /tmp/linuxiso_rpm_temp/ -wholename "*tftpboot/*" -exec cp -rf {} /var/lib/tftpboot/pxelinux \;
mkdir -p /var/lib/tftpboot/pxelinux/images/oraclelinux
find /var/lib/tftpboot/system_iso/oraclelinux/ -wholename "*pxeboot/vmlinuz" -exec cp {} /var/lib/tftpboot/pxelinux/images/oraclelinux \;
find /var/lib/tftpboot/system_iso/oraclelinux/ -wholename "*pxeboot/initrd.img" -exec cp {} /var/lib/tftpboot/pxelinux/images/oraclelinux \;
mkdir /var/lib/tftpboot/pxelinux/pxelinux.cfg
echo "default vesamenu.c32
prompt 1
timeout 600

display boot.msg

label linux
menu label ^Install system
menu default
kernel images/oraclelinux/vmlinuz
append initrd=images/oraclelinux/initrd.img ip=dhcp inst.repo=http://192.168.6.3/oraclelinux/
label vesa
menu label Install system with ^basic video driver
kernel images/oraclelinux/vmlinuz
append initrd=images/oraclelinux/initrd.img ip=dhcp inst.xdriver=vesa nomodeset inst.repo=http://192.168.6.3/oraclelinux/
label rescue
menu label ^Rescue installed system
kernel images/oraclelinux/vmlinuz
append initrd=images/oraclelinux/initrd.img rescue
label local
menu label Boot from ^local drive
localboot 0xffff" > /var/lib/tftpboot/pxelinux/pxelinux.cfg/default

# 添加UEFI支持
mkdir /var/lib/tftpboot/uefi
mkdir /tmp/linuxiso_rpm_temp

find /var/lib/tftpboot/system_iso/oraclelinux -name "grub2-efi-x64-2*x86_64.rpm" | xargs -I {} cp {} /tmp/linuxiso_rpm_temp/
find /tmp/linuxiso_rpm_temp/ -type f -name "grub2-efi-x64-2*x86_64.rpm" -exec sh -c 'rpm2cpio {} | cpio -dimv -D "/tmp/linuxiso_rpm_temp/$(basename {} .rpm)"' \;

find /var/lib/tftpboot/system_iso/oraclelinux -name "shim-x64*.x86_64.rpm" | xargs -I {} cp {} /tmp/linuxiso_rpm_temp/
find /tmp/linuxiso_rpm_temp/ -type f -name "shim-x64*.x86_64.rpm" -exec sh -c 'rpm2cpio {} | cpio -dimv -D "/tmp/linuxiso_rpm_temp/$(basename {} .rpm)"' \;

find /tmp/linuxiso_rpm_temp/ -wholename "*grubx64.efi" -exec cp {} /var/lib/tftpboot/uefi \;
find /tmp/linuxiso_rpm_temp/ -wholename "*shimx64.efi" -exec cp {} /var/lib/tftpboot/uefi \;

echo 'set timeout=60
menuentry 'oraclelinux' {
linuxefi /pxelinux/images/oraclelinux/vmlinuz ip=dhcp inst.repo=http://192.168.6.3/oraclelinux
initrdefi /pxelinux/images/oraclelinux/initrd.img
}' > /var/lib/tftpboot/uefi/grub.cfg

chmod -R 777 /var/lib/tftpboot/uefi

rm -rf /tmp/linuxiso_rpm_temp/

systemctl enable --now tftp.socket
systemctl restart tftp.socket


# dhcp服务安装
yum install dhcp-server -y
echo 'option space pxelinux;
option pxelinux.magic code 208 = string;
option pxelinux.configfile code 209 = text;
option pxelinux.pathprefix code 210 = text;
option pxelinux.reboottime code 211 = unsigned integer 32;
option architecture-type code 93 = unsigned integer 16;

subnet 192.168.6.0 netmask 255.255.255.0 {
option routers 192.168.6.1;
option domain-name-servers 192.168.6.1;
range 192.168.6.100 192.168.6.200;

class "pxeclients" {
match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
next-server 192.168.6.3;
if option architecture-type = 00:07 {
filename "uefi/shimx64.efi";
}
else {
filename "pxelinux/pxelinux.0";
}
}

class "httpclients" {
match if substring (option vendor-class-identifier, 0, 10) = "HTTPClient";
option vendor-class-identifier "HTTPClient";
filename "http://192.168.6.3/oraclelinux/EFI/BOOT/BOOTX64.EFI";
}
}' > /etc/dhcp/dhcpd.conf

firewall-cmd --add-service=dhcp --permanent
firewall-cmd --reload

systemctl enable --now dhcpd
systemctl restart dhcpd