关于如何配置无盘工作站的笔记
前言
- 利用
tftp
服务器提供grub
、内核以及initrd
- 利用
nfs
提供根文件系统
服务器操作系统
dhcp
服务器配置
nix
文件
services.dhcpd4={
enable = true;
interfaces=["eno1"];
configFile = "/etc/nixos/dhcpd/dhcpd.conf";
};
dhcpd.conf
文件
default-lease-time 600;
max-lease-time 7200;
authoritative;
ddns-update-style interim;
log-facility local1; # see dhcpd.nix
option subnet-mask 255.255.255.0;
option broadcast-address 192.168.1.255;
option routers 192.168.1.1;
option domain-name-servers 192.168.1.1,8.8.8.8;
option architecture-type code 93 = unsigned integer 16;
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.100 192.168.1.200;
next-server 192.168.1.251;
class "pxeclients" {
match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
if option architecture-type = 00:00 {
} elsif option architecture-type = 00:09 {
} elsif option architecture-type = 00:07 {
filename "/grub/x86_64-efi/core.efi"; #该文件路径与tftp服务器中文件的分布有关
} elsif option architecture-type = 00:06 {
}
}
}
host diskless{
hardware ethernet 98:FA:9B:0E:F6:89;
fixed-address 192.168.1.28;
option host-name "diskless";
}
tftp
服务配置
确定文件位置
mkdir -p /srv/tftproot
ln -s /srv/tftproot /srv/diskless
nix
文件
services.atftpd={
enable = true;
root = "/srv/tftproot";
extraOptions = [
"--verbose=7"
];
};
构建用于启动无盘工作站的根文件系统
由于服务器的操作系统是nixos
,which用来启动无盘有些麻烦,我们选用archlinux
作为无盘工作站的操作系统。
利用archlinux
的pacstrap
命令,可以在一个运行中的archlinux
中,构建出一个根文件系统,用于启动无盘工作站。
但是为了在nixos
中运行pacstrap
,这里采用singularity
先创建一个archlinux
的环境,这需要用到如下的定义文件archlinux.def
BootStrap: docker
From: archlinux
%post
yes |pacman -Syu
yes |pacman -S btrfs-progs arch-install-scripts
%files
%environment
export LC_ALL=C
export PATH=/usr/local/bin:$PATH
%labels
Author JhGU
%setup
然后执行如下的命令
sudo singularity build --sandbox archlinux archlinux.def
进入刚刚生成的archlinux
:
sudo singularity shell -B /home -B /srv:/srv ./archlinux
参考 https://wiki.archlinux.org/title/Diskless_system
执行如下命令
export root=/srv/tftproot/arch
mkdir -p "$root"
pacstrap -d "$root" base linux linux-firmware mkinitcpio-nfs-utils nfs-utils
然后打开$root/etc/mkinitcpio.conf
,进行如下编辑:
- 在
MODULES
中加入e1000e
和nfsv3
,如果必要,可加入无盘工作站的网卡驱动模块。 - 在
BINARIES
中加入/usr/bin/mount.nfs
- 在
HOOKS
中加入net
经过编辑得到的完整mkinitcpio.conf
内容如下(已删除注释)
MODULES=(e1000e nfsv3 )
BINARIES=(/usr/bin/mount.nfs)
FILES=()
HOOKS=(base udev autodetect modconf block filesystems keyboard fsck net )
接下来执行
arch-chroot "$root" mkinitcpio -p linux
pacman --root "$root" --dbpath "$root/var/lib/pacman" -S grub
arch-chroot "$root" grub-mknetdir --net-directory=/boot --subdir=grub
arch-chroot /srv/tftproot/arch/ grub-mkconfig -o /boot/grub.cfg
这里假定dhcp
、tftp
、nfs
服务器都设置在192.168.1.251
上
打开$root/boot/grub.cfg
进行如下编辑:
- 删除其中的
set root...
和search --no-floppy ...
行 - 将其中的
linux..
语句修改为linux /arch/boot/vmlinuz-linux add_efi_memmap ip=:::::eth0:dhcp nfsroot=192.168.1.251:/srv/diskless/arch rootdelay=10
- 将其中的
initrd..
语句修改为initrd /arch/boot/initramfs-linux.img
编辑得到的grub文件内容如下
### BEGIN /etc/grub.d/00_header ###
insmod part_gpt
insmod part_msdos
if [ -s $prefix/grubenv ]; then
load_env
fi
if [ "${next_entry}" ] ; then
set default="${next_entry}"
set next_entry=
save_env next_entry
set boot_once=true
else
set default="0"
fi
if [ x"${feature_menuentry_id}" = xy ]; then
menuentry_id_option="--id"
else
menuentry_id_option=""
fi
export menuentry_id_option
if [ "${prev_saved_entry}" ]; then
set saved_entry="${prev_saved_entry}"
save_env saved_entry
set prev_saved_entry=
save_env prev_saved_entry
set boot_once=true
fi
function savedefault {
if [ -z "${boot_once}" ]; then
saved_entry="${chosen}"
save_env saved_entry
fi
}
function load_video {
if [ x$feature_all_video_module = xy ]; then
insmod all_video
else
insmod efi_gop
insmod efi_uga
insmod ieee1275_fb
insmod vbe
insmod vga
insmod video_bochs
insmod video_cirrus
fi
}
if [ x$feature_default_font_path = xy ] ; then
font=unicode
else
insmod part_gpt
insmod ext2
#set root='hd0,gpt1'
font="/usr/share/grub/unicode.pf2"
fi
if loadfont $font ; then
set gfxmode=auto
load_video
insmod gfxterm
set locale_dir=$prefix/locale
set lang=C
insmod gettext
fi
terminal_input console
terminal_output gfxterm
if [ x$feature_timeout_style = xy ] ; then
set timeout_style=menu
set timeout=5
# Fallback normal timeout code in case the timeout_style feature is
# unavailable.
else
set timeout=5
fi
### END /etc/grub.d/00_header ###
### BEGIN /etc/grub.d/10_linux ###
menuentry 'Arch Linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-4a890386-d889-4847-bbfc-c4ab8d3d6c26' {
load_video
set gfxpayload=keep
insmod gzio
insmod part_gpt
insmod ext2
#set root='hd0,gpt1'
echo 'Loading Linux linux ...'
linux /arch/boot/vmlinuz-linux add_efi_memmap ip=:::::eth0:dhcp nfsroot=192.168.1.251:/srv/diskless/arch rootdelay=10
echo 'Loading initial ramdisk ...'
initrd /arch/boot/initramfs-linux.img
}
### BEGIN /etc/grub.d/41_custom ###
if [ -f ${config_directory}/custom.cfg ]; then
source ${config_directory}/custom.cfg
elif [ -z "${config_directory}" -a -f $prefix/custom.cfg ]; then
source $prefix/custom.cfg
fi
### END /etc/grub.d/41_custom ###
注意:archlinux
的mkinitcpio命令生成initramfs-linux.img
文件的默认权限是-rw------
,需要修改为-rw-r--r-
,否则tftp
将无法读取该文件。
接下来将/arch/boot/grub
复制到/srv/tftproot/
,如果不执行此操作,可能会启动失败,原因不明。
nfs
设置
在https://wiki.archlinux.org/title/Diskless_system,使用的是nfsv4
,但是在我的测试中,存在一些问题,所以这里采用nfsv3
。
相应的配置文件如下
services.nfs.server={
enable = true;
exports = ''
/srv/diskless 192.168.1.0/24(rw,no_root_squash,no_subtree_check)
/srv/diskless/arch 192.168.1.0/24(rw,no_root_squash,no_subtree_check)
'';
};
注意其中最重要的一个参数是no_root_squash
,该参数可以确保无盘工作站的root
用户能以特权权限操作挂载的nfs根分区。
最后,启动系统
在自检阶段,选择pxe over ipv4
启动方式,然后稍等一会儿,应该就能进入无盘工作站的系统了。