Gentoo on ZoL 全盘加密
需求
电脑还有书之类一个包要将近30多斤了(2个16寸大板砖),实在是背不动了。最近看了kasm workspace 这个基于容器化的web应用的一个平台感觉很适合拿个iPad打开浏览器就可以使用目前的工作流应该会很方便。
目前使用到的场景和软件比较多,内存大概在32-64G之间可以满足基本的需求(客户端),如果还有其他的需求就直接连到服务器去使用了。
看来看去还是决定用 Hetzener家的dedicated-rootserver,配置还可以满足当作一个客户端的使用。
我这里选择的是AX41-NVME这个版本,配置是AMD Ryzen 5 3600,64G内存和两个nvme的ssd,默认带一个ipv4的地址出口是上下1G。
操作系统的话是选择自己更习惯点的Gentoo,虽然Hetzener家不提供Gentoo,但是可以很方便的去使用Resucue System去安装Gentoo。
Gentoo的话提供了多种init支持,在stage3提供了openrc和systemd两种init,在我的实际使用场景中systemd还是比较简单易用的,openrc服务测试的场景就使用虚拟机就好了。
存储这里选择了OpenZFS,ZFS的好处都有啥,说对了都给他;并且开启全盘加密(不包含 boot,暂时还没有研究连同boot分区一起加密的方案)。
在云上的环境不能确保说一定安全,这里最好还是做一些加密防止数据泄漏造成不必要的风险;在加密之后还会遇到一个问题就是:我应该怎样解锁我的zpool 或者是分区?
如果是采用 key的方式,这个key放在哪里都不是很合适,这里我采用的是密码的方式,通过genkernel里面的脚本制作一个带有 zfs utils、ssh、network相关组件的一个initramfs在启动阶段会先准备网络和启动ssh等待链接进来并且解锁zpool。解锁了zpool之后再去恢复到正常的引导过程。
环境准备
Hetzener的Resucue System默认是没有zfs utils的,但是提供了很方便的安装脚本,只需要输入zpool根据提示就可以安装
我这里暂时没有当时保留的现场了,这个截图没有找到,输入
zpool
之后会提示你让你同意许可 输入y
继续等待安装完成即可。
zpool
还要创建一个文件夹,用于后面存放zfs的cache file,这个cache file 就是ZFS所谓的0管理,有个zfs-import-cache.service的服务会导入存储池,这也就是为什么ZoL(ZFS on Linux)不需要 fstab
mkdir -pv /etc/zfs
安装Gentoo
分区
这里分区的话我是打算分为两个zpool,但是系统安装的时候先搞一个后续的一块盘要怎么使用暂时没有想好。
用fdisk进行分区,分区格式为dos,分区表如下:
这里闹了一个乌龙,分区的时候没有看到用的是第二块盘第一块盘没有使用,不过不影响使用就是了。
分区 | 大小 | 文件系统 | 挂载点 |
---|---|---|---|
nvme1n1p1 | 500M | ext4 | /boot |
nvme1n1p2 | 剩余所有 | zpool | NONE |
初始化引导分区的文件系统:
mkfs.ext4 /dev/nvme1n1p1
查看磁盘的id:
ls -l /dev/disk/by-id/
创建zpool:
zpool create -f -o ashift=12 -o cachefile=/etc/zfs/zpool.cache \
-O compression=zstd \
-O xattr=sa \
-O relatime=on \
-O acltype=posixacl \
-O dedup=off \
-O encryption=on \
-O keyformat=passphrase \
-m none \
-R /mnt/gentoo rock /dev/disk/by-id/nvme-SAMSUNG_MZVL2512HCJQ-00B00_S675NX0T618385-part2
参数说明:
ashift=12
ashift会根据磁盘报告的sector大小自动设置,但是底层的设备报告不一定是正确的大小,这里是比较简单粗暴设置了一个12类似于4k对齐 具体更详细的可以看 https://www.high-availability.com/docs/ZFS-Tuning-Guide/ 和 https://openzfs.github.io/openzfs-docs/man/7/zpoolprops.7.htmlcompression=zstd
压缩算法,这个性能比较好 性能比较可以看 https://www.reddit.com/r/zfs/comments/svnycx/a_simple_real_world_zfs_compression_speed_an/xattr=sa
出于性能考虑要开启,不开的话在Linux下要频繁的找xattrs并且没cache 具体可以看 https://github.com/openzfs/zfs/issues/443relatime=on
类似于 ext4/XFS atimeacltype=posixacl
ACLdedup=off
dedup 属性控制是否从文件系统中删除重复数据。如果文件系统启用了 dedup 属性,则会以同步方式删除重复的数据块。结果是仅存储唯一的数据,在文件之间共享通用组件。(这个选项生产不推荐开)encryption=on
zpool的加密keyformat=passphrase
加密的key选择使用密码rock
是zpool的名称
根据提示输入两次密码即可。
创建dataset:
zfs create -o mountpoint=none -o canmount=off rock/os
zfs create -o mountpoint=/ rock/os/gentoo
创建/boot
的挂载点:
mkdir -pv /mnt/gentoo/boot
挂载boot设备:
mount nvme1n1p1 /mnt/gentoo/boot
到这里就分区就完成了,可以使用lsblk
查看分区大小以及挂载的位置是否正确。
安装stage3
这里由于上游的变动要去给Merge-usr一下,这里下载的stage3的profile 也是Merge-usr的,为了简单我这里用了几个命令直接下载这个stage3了:
MIRRORS='https://bouncer.gentoo.org/fetch/root/all/releases/amd64/autobuilds'
ZIPFILENAME=`curl -L $MIRRORS/latest-stage3.txt |grep amd64-systemd-mergedusr|grep ^[0-9] |awk -F '[/ ]' '{if (NR==1) {print $2}}'`
FILENAME=`curl -L $MIRRORS/latest-stage3.txt 2>/dev/null|grep amd64-systemd-mergedusr |grep ^[0-9]|awk '{if (NR==1) {print $1}}'`
FILEURL="$MIRRORS/$FILENAME"
wget -T 3 -c -O /mnt/gentoo/$ZIPFILENAME $FILEURL
解压stage3:
tar xpvf stage3-*.tar.xz --xattrs-include='*.*' --numeric-owner
配置portage
这里设置EMERGE_DEFAULT_OPTS
(Portage作业数控制)和MAKEOPTS
,因为portage不支持shell的高级操作就在root用户下设置了,默认情况下是root调起的portage,root用户登陆的时候会依次读取,如果你设置了其他用户来跑portage那么就需要在相应的用户去配置这几个变量。
拷贝一个bash_profile 到root用户下:
这个地方的skel 首次创建用户的时候会把
/etc/skel/
下面的文件都拷贝一份到新用户的家目录下。
cp -v /mnt/gentoo/etc/skel/.bash_profile /mnt/gentoo/root/
创建并编辑文件:
nano -w /mnt/gentoo/root/.bashrc
内容如下:
export NUMCPUS=$(nproc)
export NUMCPUSPLUSONE=$(( NUMCPUS + 1 ))
export MAKEOPTS="-j${NUMCPUSPLUSONE} -l${NUMCPUS}"
export EMERGE_DEFAULT_OPTS="--jobs=${NUMCPUSPLUSONE} --load-average=${NUMCPUS}"
接下来是make.conf
我这里在原有的基础上添加了如下内容:
# The following licence is required.
ACCEPT_LICENSE="*"
# Additional USE flags supplementary to those specified by the current profile.
USE=""
# Use the 'stable' branch - 'testing' no longer required for Gnome 3.
# NB, amd64 is correct for both Intel and AMD 64-bit CPUs
ACCEPT_KEYWORDS="amd64"
允许所有许可证,用stable的分支(不需要频繁更新,我需要的是一个稳定的环境),全局设置里面是不开启USE的。
创建portage tree的相关目录和拷贝配置:
mkdir -p -v /mnt/gentoo/etc/portage/repos.conf
cp -v /mnt/gentoo/usr/share/portage/config/repos.conf /mnt/gentoo/etc/portage/repos.conf/gentoo.conf
修改一个地方:
nano -w /mnt/gentoo/etc/portage/repos.conf/gentoo.conf
将里面的sync-type
的值改为webrsync
:
[DEFAULT]
main-repo = gentoo
[gentoo]
location = /var/db/repos/gentoo
sync-type = webrsync
sync-uri = rsync://rsync.gentoo.org/gentoo-portage
auto-sync = yes
sync-rsync-verify-jobs = 1
sync-rsync-verify-metamanifest = yes
sync-rsync-verify-max-age = 24
sync-openpgp-key-path = /usr/share/openpgp-keys/gentoo-release.asc
sync-openpgp-keyserver = hkps://keys.gentoo.org
sync-openpgp-key-refresh-retry-count = 40
sync-openpgp-key-refresh-retry-overall-timeout = 1200
sync-openpgp-key-refresh-retry-delay-exp-base = 2
sync-openpgp-key-refresh-retry-delay-max = 60
sync-openpgp-key-refresh-retry-delay-mult = 4
sync-webrsync-verify-signature = yes
chroot
拷贝DNS文件和挂载必要的文件系统:
cp -v -L /etc/resolv.conf /mnt/gentoo/etc/
mount -v -t proc none /mnt/gentoo/proc
mount -v --rbind /sys /mnt/gentoo/sys
mount -v --rbind /dev /mnt/gentoo/dev
mount -v --make-rslave /mnt/gentoo/sys
mount -v --make-rslave /mnt/gentoo/dev
在非Gentoo Livecd下面还需要执行:
test -L /dev/shm && rm /dev/shm && mkdir /dev/shm
mount --types tmpfs --options nosuid,nodev,noexec shm /dev/shm
chmod 1777 /dev/shm
进入chroot:
chroot /mnt/gentoo /bin/bash
如果任何命令都执行不了可以输入:
source /etc/profile
给一个PS1的提示方便区分环境:
export PS1="(chroot) $PS1"
同步portage tree
emaint sync --auto
更新系统
第一步就是更新一下系统:
emerge -uDN @world
安装软件
这里用sets安装常用的软件,我这里定义了这么几个sets:
- bootloader
- common-utils
- dev-utils
- filesystem
- kernel
具体的软件表如下:
包 | sets | 用途 |
---|---|---|
sys-boot/grub | bootloader | 引导器 |
app-portage/gentoolkit | common-utils | 简化管理portage的工具 |
net-analyzer/mtr | common-utils | 链路测试工具 |
sys-apps/lm-sensors | common-utils | 系统传感器温度 |
net-misc/networkmanager | common-utils | 网络管理 |
app-admin/sysklogd | common-utils | 日志管理 |
sys-process/cronie | common-utils | 定时任务 |
sys-apps/mlocate | common-utils | 索引 |
net-misc/chrony | common-utils | 时间同步 |
app-portage/pfl | common-utils | 通过文件来查找特定的包 |
dev-util/pkgdev | common-utils | Gentoo开发的工具集合 |
app-eselect/eselect-repository | common-utils | overlay管理工具 |
app-admin/sudo | common-utils | sudo工具 |
net-dns/avahi | common-utils | 网络发现 |
app-shells/bash-completion | common-utils | bash 补全 |
app-misc/neofetch | common-utils | 图一乐 |
sys-process/htop | common-utils | 查看系统负载 |
sys-apps/usbutils | common-utils | usb设备管理 |
sys-fs/e2fsprogs | common-utils | ext文件系统的管理工具默认已经包含在@system了 |
sys-process/btop | common-utils | 查看系统负载 |
sys-apps/edac-utils | common-utils | EDAC驱动的用户空间辅助工具 | |
app-containers/docker | dev-utils | 容器 |
app-containers/docker-compose | dev-utils | 容器编排 |
app-editors/vim | dev-utils | vim 编辑器 |
www-client/pybugz | dev-utils | bugz 的py cli |
app-emulation/virt-manager | dev-utils | VMM管理 |
sys-apps/ripgrep | dev-utils | 比grep更好用的过滤工具 |
dev-vcs/git | dev-utils | git 工具 |
app-admin/ansible | dev-utils | 节点管理 |
app-containers/lxd | dev-utils | lxd 支持容器和虚拟机 |
app-misc/tmux | dev-utils | 回话管理 |
dev-libs/libisoburn | dev-utils | 如果使用virt-install iso的时候需要这个包 |
acct-group/libvirt | dev-utils | 使用livritd的时候用这个包来管理对应的组 |
www-servers/nginx | dev-utils | nginx web |
app-crypt/certbot | dev-utils | 申请ssl证书 |
www-apps/hugo | dev-utils | 静态站点生成器 |
sys-fs/zfs | filesystem | zfs 工具 |
sys-kernel/gentoo-kernel-bin | kernel | 内核 |
sys-kernel/genkernel | kernel | 内核 |
创建文件夹:
mkdir -pv /etc/portage/sets
创建并编辑/etc/portage/sets/common-utils
文件,内容如下:
app-portage/gentoolkit
net-analyzer/mtr
sys-apps/lm-sensors
net-misc/networkmanager
app-admin/sysklogd
sys-process/cronie
sys-apps/mlocate
net-misc/chrony
app-portage/pfl
dev-util/pkgdev
app-eselect/eselect-repository
app-admin/sudo
net-dns/avahi
app-shells/bash-completion
app-misc/neofetch
sys-process/htop
sys-apps/usbutils
sys-fs/e2fsprogs
sys-process/btop
sys-apps/edac-utils
创建并编辑/etc/portage/sets/dev-utils
文件,内容如下:
app-containers/docker
app-containers/docker-compose
app-editors/vim
www-client/pybugz
app-emulation/virt-manager
sys-apps/ripgrep
dev-vcs/git
app-admin/ansible
app-containers/lxd
app-misc/tmux
dev-libs/libisoburn
acct-group/libvirt
www-servers/nginx
app-crypt/certbot
www-apps/hugo
创建并编辑/etc/portage/sets/filesystem
文件,内容如下:
sys-fs/zfs
创建并编辑/etc/portage/sets/kernel
文件,内容如下:
sys-kernel/gentoo-kernel-bin
sys-kernel/genkernel
创建并编辑/etc/portage/sets/bootloader
文件,内容如下:
sys-boot/grub
安装common-utils:
emerge -av @common-utils
安装dev-utils:
emerge --autounmask-write=y --autounmask -av @dev-utils
这里会提示有文件需要更新使用etc-update更新掉即可(选择-5)。
安装内核
这里没有选择自己编译内核直接选择二进制的内核,二进制内核USE会帮我们创建initramfs;我这里不要它帮我创建的,因此要关掉一个USE:
echo sys-kernel/gentoo-kernel-bin -initramfs > /etc/portage/package.use/gentoo-kernel-bin
安装内核:
emerge -av @kernel
安装zfs
在安装好了内核之后再来安装zfs:
emerge -av @filesystem
生成一个hostid:
zgenhostid
systemd
systemd要额外去做一些初始化的工作:
ln -sf /proc/self/mounts /etc/mtab
systemctl daemon-reexec
# 这一步会帮忙开机启动zfs相关的服务不用手动启动了
systemctl preset-all
systemd-machine-id-setup
第一次初始化和设置主机名:
systemd-firstboot --prompt --setup-machine-id
genkernel
创建文件夹:
mkdir -pv /etc/dropbear/
创建并编辑/etc/dropbear/authorized_keys
文件,里面就存放自己的公钥:
vi /etc/dropbear/authorized_keys
生成initramfs:
genkernel --zfs --ssh initramfs
用户配置
创建常用的管理用户:
这里chris是我的用户,你可以切换到你的用户
useradd -m -G users,wheel,portage,usb,video,tty chris
切换到chris
这个用户
su - chris
创建文件夹:
mkdir -pv .ssh
创建并编辑.ssh/authorized_keys
文件,内容填写自己的公钥
vi .ssh/authorized_keys
写好之后保存并退出。
退出 chris用户
exit
grub
为了让grub支持zfs还需要启动一个USE:
echo sys-boot/grub libzfs > /etc/portage/package.use/grub
安装grub:
emerge -av @bootloader
配置grub
编辑/etc/default/grub
文件,修改GRUB_CMDLINE_LINUX
这行的内容如下:
GRUB_CMDLINE_LINUX="dozfs root=ZFS=rock/os/gentoo ip=10.10.10.10/24 gk.net.gw=10.10.10.1 dosshd gk.sshd.port=2222 init=/lib/systemd/systemd net.ifnames=0"
dozfs
启动的时候扫描可以启动的 zpooldosshd
在initramfs中启动一个sshd守护进程root=ZFS=rock/os/gentoo
引导的时候root在哪里,这里是选择了rock/os/gentoo
这个dataset10.10.10.10/24
initramfs启动网络的时候的ipgk.net.gw=10.10.10.1
initramfs启动网络时候的网关gk.sshd.port=2222
sshd守护进程的端口init=/lib/systemd/systemd
systemd init的配置net.ifnames=0
网卡都遵循类似etch0, eth1
这样的格式
安装grub:
grub-install /dev/nvme1n1
生成grub的配置文件:
grub-mkconfig -o /boot/grub/grub.cfg
服务配置
ssh
关掉密码登陆
编辑/etc/ssh/sshd_config
文件,修改内容如下:
PasswordAuthentication no
PermitEmptyPasswords no
开机启动sshd:
systemctl enable sshd
NetworkManager
在hz上测试发现,默认dhcp就可以拿到对应的ip不需要额外的配置:
systemctl enable NetworkManager
Docker
开机启动docker:
systemctl enable docker
将用户添加到docker组:
usermod -aG docker chris
sudoer配置
编辑/etc/sudoers
文件修改内容如下:
%wheel ALL=(ALL:ALL) NOPASSWD: ALL
收尾
退出chroot:
exit
卸除挂载:
umount -R /mnt/gentoo
重启:
reboot
验证
可以长ping 机器的ip,发现可以ping通了 用ssh链接:
ssh [email protected] -p2222
解锁:
根据提示解锁zpool即可。
unlock-zfs
继续启动:
resume-boot
然后再用ssh链接:
配置备份
需要备份的有:
- /etc/sudoers
- /etc/default/grub
- /etc/portage 整个文件夹
可以选择自己喜欢的方式进行备份。
TODO
- 安全加固
- 定期备份
参考文档
- https://www.yafa.moe/post/gentoo-on-zfs/
- https://wiki.gentoo.org/wiki/Pfl
- https://wiki.gentoo.org/wiki/Pkgdev
- https://wiki.gentoo.org/wiki/System_set_(Portage)
- https://wiki.gentoo.org/wiki/Handbook:X86/Portage/Tools
- https://wiki.gentoo.org/wiki/Genkernel
- https://wiki.gentoo.org/wiki/Systemd
- https://wiki.gentoo.org/wiki//etc/portage/sets
- https://wiki.gentoo.org/wiki/Gentoolkit