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提供了openrcsystemd两种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

这里分区的话我是打算分为两个zpool,但是系统安装的时候先搞一个后续的一块盘要怎么使用暂时没有想好。

用fdisk进行分区,分区格式为dos,分区表如下:

这里闹了一个乌龙,分区的时候没有看到用的是第二块盘第一块盘没有使用,不过不影响使用就是了。

分区大小文件系统挂载点
nvme1n1p1500Mext4/boot
nvme1n1p2剩余所有zpoolNONE

初始化引导分区的文件系统:

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

参数说明:

根据提示输入两次密码即可。

创建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查看分区大小以及挂载的位置是否正确。

这里由于上游的变动要去给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

这里设置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

拷贝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"
emaint sync --auto

第一步就是更新一下系统:

emerge -uDN @world

这里用sets安装常用的软件,我这里定义了这么几个sets:

  • bootloader
  • common-utils
  • dev-utils
  • filesystem
  • kernel

具体的软件表如下:

sets用途
sys-boot/grubbootloader引导器
app-portage/gentoolkitcommon-utils简化管理portage的工具
net-analyzer/mtrcommon-utils链路测试工具
sys-apps/lm-sensorscommon-utils系统传感器温度
net-misc/networkmanagercommon-utils网络管理
app-admin/sysklogdcommon-utils日志管理
sys-process/croniecommon-utils定时任务
sys-apps/mlocatecommon-utils索引
net-misc/chronycommon-utils时间同步
app-portage/pflcommon-utils通过文件来查找特定的包
dev-util/pkgdevcommon-utilsGentoo开发的工具集合
app-eselect/eselect-repositorycommon-utilsoverlay管理工具
app-admin/sudocommon-utilssudo工具
net-dns/avahicommon-utils网络发现
app-shells/bash-completioncommon-utilsbash 补全
app-misc/neofetchcommon-utils图一乐
sys-process/htopcommon-utils查看系统负载
sys-apps/usbutilscommon-utilsusb设备管理
sys-fs/e2fsprogscommon-utilsext文件系统的管理工具默认已经包含在@system
sys-process/btopcommon-utils查看系统负载
sys-apps/edac-utilscommon-utilsEDAC驱动的用户空间辅助工具 |
app-containers/dockerdev-utils容器
app-containers/docker-composedev-utils容器编排
app-editors/vimdev-utilsvim 编辑器
www-client/pybugzdev-utilsbugz 的py cli
app-emulation/virt-managerdev-utilsVMM管理
sys-apps/ripgrepdev-utils比grep更好用的过滤工具
dev-vcs/gitdev-utilsgit 工具
app-admin/ansibledev-utils节点管理
app-containers/lxddev-utilslxd 支持容器和虚拟机
app-misc/tmuxdev-utils回话管理
dev-libs/libisoburndev-utils如果使用virt-install iso的时候需要这个包
acct-group/libvirtdev-utils使用livritd的时候用这个包来管理对应的组
www-servers/nginxdev-utilsnginx web
app-crypt/certbotdev-utils申请ssl证书
www-apps/hugodev-utils静态站点生成器
sys-fs/zfsfilesystemzfs 工具
sys-kernel/gentoo-kernel-binkernel内核
sys-kernel/genkernelkernel内核

创建文件夹:

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:

emerge -av @filesystem

生成一个hostid:

zgenhostid

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

创建文件夹:

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支持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 启动的时候扫描可以启动的 zpool
  • dosshd 在initramfs中启动一个sshd守护进程
  • root=ZFS=rock/os/gentoo 引导的时候root在哪里,这里是选择了rock/os/gentoo这个dataset
  • 10.10.10.10/24 initramfs启动网络的时候的ip
  • gk.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

关掉密码登陆

编辑/etc/ssh/sshd_config 文件,修改内容如下:

PasswordAuthentication no
PermitEmptyPasswords no

开机启动sshd:

systemctl enable sshd 

在hz上测试发现,默认dhcp就可以拿到对应的ip不需要额外的配置:

systemctl enable NetworkManager

开机启动docker:

systemctl enable docker

将用户添加到docker组:

usermod -aG docker chris

编辑/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 整个文件夹

可以选择自己喜欢的方式进行备份。

  • 安全加固
  • 定期备份