近期有几个服务器到期,又对国内低流量、大带宽的服务器有一定需求(主要是用于内网穿透),于是入手了阿里云的 2C0.5G T6 突发性能实例。综合下来五年仅需不到 200 元,性价比极高。
然而云服务的一大特点是「块存储」,也就是硬盘收费很贵,算下来硬盘价格比服务器本身还高。因此选用一个体积较小的操作系统就显得尤为重要。早在之前 LMS 就已介绍了如何自定义 Alpine Linux 镜像以超低价格购买该配置的实例。然而对我来说,还有几个需要考虑的地方:
- 希望使用 LUKS 加密,以防止阿里云的「自动化扫描硬盘」
- 出于个人便好,想要使用 btrfs 文件系统
- 由于内存较小,因此使用 x86-32 而非 x86-64 架构以节省内存占用
同时,不同于该文章使用 Hyper-V 创建虚拟机的方式,本文使用了笔者更加熟悉的 Proxmox VE。
本文所涉 Alpine Linux 版本为 3.21,未来更新版本的配置方式可能有所区别,敬请读者在操作时注意。
分区
使用 Proxmox VE 获取镜像及创建虚拟机的过程在此不再赘述,由于 32 位系统默认不支持 UEFI,因此请选择 BIOS 引导类型。
笔者建议,在开始安装 Alpine Linux 之前,使用其他发行版的镜像(例如「Arch Linux 安装介质」或 SystemRescue)先行完成分区工作。
注意
这里需要注意的是,和其他发行版不同,Alpine Linux 默认的 syslinux 引导程序只支持从 512B 处读取
/boot
分区。因此,无法使用 cfdisk、fdisk 工具进行分区(因为其默认会进行 2048B 对齐)。为了指定准确的分区开始位置,建议使用parted
工具进行分区。
为了获得更好的性能,笔者依然在划分主分区时进行了对齐,即在 /dev/vda1
和 /dev/vda2
之间留下部分间隙,/dev/vda1
使用 parted
分区设置的起始位置为 512B、不对齐到 2048B;/dev/vda2
使用 cfdisk
分区工具对齐到 2048B。
然而,由于未知的 bug,cfdisk
写入分区表不会被 Alpine Linux 安装介质的内核重新加载,因此建议在其他操作系统完成分区后,再使用 Alpine Linux 安装介质进行格式化和安装。
1 | parted -sa optimal /dev/vda mklabel msdos |
注意
GRUB 可能并不需要为第一个分区设置 bootable flag,但是 Alpine Linux 在使用 syslinux 引导程序的情况下,为
/boot
分区设置 bootable flag 是必要的。否则,Alpine Linux 将无法引导。
提示
尽管 50MB 已足够 Alpine Linux 的
/boot
分区使用,但在默认情况下,btrfs 需要大于 128MB 的空间才能格式化。因此,笔者将/boot
分区设置为 128MB。
安装和格式化
在分区完成后,使用 Alpine Linux 安装介质引导系统。进入安装界面后,使用 setup-alpine
命令进行安装。
1 | setup-alpine |
安装过程在此不再赘述。在完成镜像设置之后、选择安装磁盘前,使用 Ctrl+C
退出安装程序。
首先安装需要的软件包:
1 | apk add --no-cache cfdisk parted e2fsprogs btrfs-progs cryptsetup lsblk |
然后对之前的分区进行格式化:
1 | mkfs.btrfs -L alpine-boot /dev/vda1 |
请在提示时输入 YES
(必须为大写字母) 以确认格式化。接下来,使用 cryptsetup luksOpen
命令打开加密分区,并完成后续操作:
1 | cryptsetup luksOpen /dev/vda2 root |
由于 Alpine Linux 作为最小化操作系统,并不总是加载所有内核模块,因此如果直接进行分区挂载,会显示 Invalid argument
错误。因此,我们需要手动加载内核模块:
1 | modprobe btrfs |
然后挂载分区:
1 | mount /dev/mapper/root /mnt |
完成后,使用 lsblk
命令检查分区是否正确挂载。
如果一切正常,继续安装 Alpine Linux:
1 | setup-disk -m sys /mnt |
如果一切正常,重启后将进入引导界面,输入 LUKS 密码后可以正常进入系统。
镜像导出 Proxmox VE
在 Proxmox VE 关机的情况下,使用 qemu-img
命令将虚拟机的磁盘导出为 qcow2 格式:
1 | qemu-img convert /data/images/<vmid>/vm-<vmid>-disk-0/disk.raw ~/alpine.qcow2 -O qcow2 -f raw |
其中:
/data/images
为 Proxmox VE 中设置的 VM 磁盘存储路径<vmid>
为虚拟机 ID- 假设磁盘 ID 为 0
完成后,通过 scp
或其他终端软件集成的文件管理器将 alpine.qcow2
文件下载到本地。
镜像导入阿里云
在计划创建服务器的同一地域(即,如果打算在杭州创建服务器,那么就需要在杭州地域创建一个 OSS)创建一个 OSS,名称随意,访问权限可以为私有。
将本地的 alpine.qcow2
文件上传到 OSS 中。在阿里云的镜像导入界面,选择 「导入镜像」。
- 镜像文件 URL:填写 OSS 中的文件 URL,有无签名均可
- 镜像名称:根据自己需要填写
- 操作系统类型:Linux
- 操作系统版本:Customized Linux
- 系统架构:32 位
- 启动模式:BIOS
- 镜像格式:qcow2
此处需要 勾选「配置云盘属性」,并设置云盘大小为 1GB 或 2GB(根据实际需要)。
注意
阿里云默认导入的镜像大小为 20GB,因此如果不勾选「配置云盘属性」,会导致创建服务器时无法将系统盘设置得更小。
完成导入后,创建服务器的过程不再赘述。
创建完成后,可以使用阿里云自带的 Web VNC 连接到服务器,以输入 LUKS 密码并登录。
SSH 安全配置
注意
由于 SSH 尚未配置,本节内容在 VNC 界面中完成。
由于安装 Alpine 时选择了 OpenSSH,因此其他发行版的 OpenSSH 配置可以通用。
1 | sudo sed -i "/^#HostKey/s/^#//g" /etc/ssh/sshd_config |
然后,重启 SSH 服务:
1 | sudo rc-service sshd restart |
配置 SSH 安全密钥:
1 | mkdir -p ~/.ssh |
如果使用阿里云,可以使用 VNC 控制台的「黏贴命令」来黏贴你的 SSH 公钥。
如果配置正常,至此,即可使用 SSH 连接服务器公网 IP。
如果无法连接,请检查云服务是否分配公网 IP 及安全组、防火墙等设置。
更换镜像源
注意
此节及之后的内容在 SSH 界面中完成,您需要以 root 身份登录 SSH。
修改 /etc/apk/repositories
文件,将 dl-cdn.alpinelinux.org
替换为想要的源地址,视情况可取消 Community 源的注释。
1 | https://mirrors.tuna.tsinghua.edu.cn/alpine/v3.21/main |
如果使用阿里云,可以使用内网源:
1 | http://mirrors.cloud.aliyuncs.com/alpine/v3.21/main |
vi = vim,以及不得不装的工具
安装 vim:
1 | apk add vim sudo curl |
修改默认 shell 为 bash
安装 bash:
1 | apk update |
修改默认 shell:
1 | chsh -s /bin/bash |
有强迫症可以清除 ash 的历史记录:
1 | rm -v ~/.ash_history |
配置 LUKS 自动解锁
会降低安全性,但是对于服务器来说,重启可以自动化,无需人工干预输入密码。是否进行这一步骤,请慎重考虑。
1 | dd if=/dev/urandom of=/crypto_keyfile.bin bs=1024 count=4 |
其中,<luks-device>
是加密分区的设备名,例如 /dev/sda2
。
如果服务器内存很小(小于 1GB),可以使用 --pbkdf pbkdf2 --pbkdf-memory 25600
来换用内存更少的 PBKDF2 算,并限制内存使用量为 25600 KiB。
如果服务器内存较大,可以去掉 --pbkdf
和 --pbkdf-memory
参数,使用更加安全的 Argon2 算法。
使用下面的命令确认是否成功,如果成功,则可以看见新增的 Key Slot(一般为 Slot 1):
1 | cryptsetup luksDump <luks-device> |
然后,修改 /etc/mkinitfs/mkinitfs.conf
文件,在 features
中添加 cryptkey
和 btrfs
(由于我的 /boot
分区使用了 btrfs,因此需要添加这个选项)。
1 | # /etc/mkinitfs/mkinitfs.conf |
更新 initramfs:
1 | mkinitfs |
此外,还需要修改 /etc/update-extlinux.conf
文件:
- 在
modules
中添加btrfs
(如果你的/boot
分区使用了 btrfs,如果没有使用 btrfs,则不需要添加这个选项) - 在
default_kernel_opts
中添加cryptkey
1 | # /etc/update-extlinux.conf |
根据我的个人习惯,另外的,我还会修改以下选项:
verbose
选项设置为1
,这样执行update-extlinux
时会显示详细的执行过程- 去掉
default_kernel_opts
中的quiet
选项,这样可以在启动时看到详细的启动过程
然后,更新 extlinux:
1 | update-extlinux |
重启服务器,如果没有配置错误,此时可以看到服务器自动解锁 LUKS 分区,进入系统。
最后,如果重启成功,可以删除原有的 LUKS 密码,以增加安全性:
1 | cryptsetup luksKillSlot \ |
用户默认的 dotfiles
使用 /etc/skel
目录中的文件作为新用户的默认配置文件。
1 | mkdir -p /etc/skel |
配置开机后及 TTY 登出时清屏
在 Debian 上,计算机开机之后及在 TTY 登出时,都会自动清屏。要在 Alpine 上实现这个行为,需要修改 /etc/issue
文件。
1 | clear > issue |
可以通过 vim 打开 /etc/issue
文件,查看是否有控制字符,来确定是否成功。
修改 MOTD
1 | . /etc/os-release |
调整内核参数
1 | echo 'net.core.default_qdisc = fq' | tee -a /etc/sysctl.d/10-tcp-bbr.conf |
另外可以尝试 https://omnitt.com/ 的 TCP 调参算法,但是我没有尝试过。
添加 swap 和 zram
安装 zram-init:
1 | apk add zram-init |
编辑 /etc/conf.d/zram-init
文件,设置 zram 的大小:
1 | num_devices=1 # zram 设备数量 |
然后启动 zram-init:
1 | rc-service zram-init start |
然后配置 swap:
1 | dd if=/dev/zero of=/swapfile bs=1M count=512 |
然后,编辑 /etc/fstab
文件,添加 swap:
1 | echo -e "/swapfile\tswap\tswap\tdefaults\t0 0" | tee -a /etc/fstab |
如果有需要,也可以删除 fstab 内无用的 USB 和 CD-ROM 的挂载项。
配置 NTP
创建 /etc/periodic/hourly/10-timesync-ntpd
文件:
1 |
|
该 NTP 服务器为阿里云内网 NTP 服务器,如果你在其他云服务商上,请自行寻找合适的 NTP 服务器。
然后,给文件添加可执行权限:
1 | chmod +x /etc/periodic/hourly/10-timesync-ntpd |