−25%

Windows 按年付费,截至 10 月 31 日。 查看套餐

EQVPS
开始使用

如何配置 Alpine Linux VPS:apk、doas、OpenRC 和防火墙

全新 Alpine Linux 3.21 VPS 的第一步:更新并重启,创建一个真正能登录的 doas 用户,关闭 root 和密码 SSH 登录,装上 ufw,开启 cron 和每日更新。另附 ufw 挡不住的 Docker 端口。

Alpine Linux 是我们提供的最小的镜像。在我们的服务器上,全新的 Alpine 3.21 空闲时占用 55 MB 内存和 153 MB 磁盘,而 Ubuntu 24.04 是 313 MB 和 2.7 GB。代价是放弃熟悉的工具。Alpine 用 apk 代替 apt,用 doas 代替 sudo,用 OpenRC 代替 systemd,用 musl 代替 glibc。

下面的步骤和在 Debian 或 Ubuntu 上的前十分钟相同,只是换成了 Alpine 的做法。发布前,我们在自己的 Alpine 3.21 镜像上运行了每一条命令,其中两条第一次就让我们栽了跟头。用控制面板里的密码以 root 登录。

1. 更新,然后重启一次

apk update && apk upgrade
uname -r
ls /lib/modules

服务器在第一次启动时已经安装了可用的更新,所以 apk upgrade 通常没剩多少事可做。重点看最后两行。如果那次首启更新带来了新内核,正在运行的内核(uname -r)在磁盘上就已经没有对应的模块了。任何需要加载模块的操作都会失败,直到重启为止。在我们的测试服务器上,安装防火墙时输出了 ERROR: Couldn't determine iptables version。如果两个版本不一致,现在就重启:

reboot

我们的测试服务器不到一分钟就恢复了。

2. 创建一个能登录的用户

adduser -D deploy
passwd deploy
adduser deploy wheel

不要跳过 passwd。adduser -D 创建的账户没有密码,Alpine 会把它标记为锁定,而 sshd 会拒绝锁定的账户,即使密钥正确。在我们的测试里,唯一的线索是 /var/log/messages 中的这一行:

User deploy not allowed because account is locked

密码之后也有用:doas 要的就是它。

如果下单时添加了 SSH 密钥,它就在 root 的 authorized_keys 里。把它复制给新用户:

install -d -m 700 -o deploy -g deploy /home/deploy/.ssh
install -m 600 -o deploy -g deploy /root/.ssh/authorized_keys /home/deploy/.ssh/authorized_keys

还没有密钥?在自己的电脑上生成一个,把公钥部分粘贴到 /home/deploy/.ssh/authorized_keys。

3. 让 doas 要求输入密码

Alpine 用 doas 代替 sudo,我们的镜像已经允许 wheel 组使用它。/etc/doas.d/wheel.conf 里的规则是 permit nopass :wheel,也就是说 wheel 组的任何成员不用输入任何东西就能变成 root。改成要求输入密码,并在几分钟内记住它:

echo 'permit persist :wheel' > /etc/doas.d/wheel.conf

从现在起,doas apk add nano 的用法就和 Ubuntu 上的 sudo apt install nano 一样。

4. SSH:只用密钥,禁止 root

sshd 按文件名顺序读取 /etc/ssh/sshd_config.d/ 里的文件,每项设置取它找到的第一个值。在我们的镜像里,第一个文件是 00-eqvps.conf,它允许 root 和密码登录,方便你第一天进入服务器。替换它的内容:

cat > /etc/ssh/sshd_config.d/00-eqvps.conf <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
EOF
sshd -t && rc-service sshd restart
sshd -T | grep -E '^(permitrootlogin|passwordauthentication|kbdinteractiveauthentication) '

第三行在 Alpine 上很关键。镜像用的是带 PAM 的 OpenSSH 版本,只写前两行时,我们的测试服务器仍然提供 keyboard-interactive 登录。三行都写上后,不带密钥的登录尝试会得到:

Permission denied (publickey).

保持 root 会话不要关闭。在第二个终端里确认 ssh deploy@YOUR.SERVER.IP 能登录(NAT 套餐要加上 -p 和控制面板里的专属端口),并确认 doas id 接受密码。

5. 防火墙:ufw

ufw 在 community 仓库里,我们的镜像已经启用了这个仓库:

apk add ufw
ufw limit 22/tcp
ufw --force enable
rc-update add ufw default
ufw status

limit 放行 SSH,但会拖慢连续打开大量连接的一方。这里 rc-update 很重要,因为如果不把防火墙加入 runlevel,OpenRC 重启后不会启动它。重启后,我们的服务器回来时显示 Status: active。在 NAT 套餐上,让 SSH 留在 22 端口:你的专属外部端口会转发到服务器内部的 22。在带独立 IPv4 的套餐上,需要时再开放网页端口(ufw allow 80/tcp、ufw allow 443/tcp)。其余内容见 ufw 指南。

6. 开启 cron 和每日更新

全新的 Alpine 服务器根本没有运行 cron。把它打开:

rc-update add crond default
rc-service crond start

Alpine 中 root 的 crontab 已经会在每天 02:00 运行 /etc/periodic/daily 里的所有内容。把更新脚本放进去:

cat > /etc/periodic/daily/apk-upgrade <<'EOF'
#!/bin/sh
apk upgrade --update-cache --no-progress >> /var/log/apk-auto.log 2>&1
EOF
chmod +x /etc/periodic/daily/apk-upgrade
run-parts --test /etc/periodic/daily

最后一条命令会列出 cron 将要运行的脚本,你的脚本应该在列表里。这样你就能持续获得 3.21 的修复。升级到下一个 Alpine 版本是另一个需要手动完成的步骤。内核更新仍然需要重启:时不时重复一下第 1 步里的 uname -r / ls /lib/modules 检查。

7. 一张表看懂 OpenRC

如果你熟悉 systemd,变化大致就是这些:

任务systemdAlpine (OpenRC)
启动服务systemctl start nginxrc-service nginx start
开机自启systemctl enable nginxrc-update add nginx default
状态systemctl status nginxrc-service nginx status
正在运行的服务systemctl list-unitsrc-status
系统日志journalctl/var/log/messages

8. Docker,以及 ufw 挡不住的端口

Alpine 很适合做 Docker 主机,因为系统本身几乎不碍事:

apk add docker docker-cli-compose
rc-update add docker default
rc-service docker start
docker run --rm hello-world

在我们的服务器上,包括下载在内用了 12 秒。Docker 守护进程运行后,已用内存从 57 MB 增加到 124 MB。

有一个陷阱并不只存在于 Alpine:Docker 会写入自己的防火墙规则。在 ufw 只放行 SSH 的情况下,我们用 -p 8080:80 启动了 nginx,结果从服务器外部通过 8080 端口访问到了它。ufw 没有拦住。如果一个容器只应通过同一台服务器上的反向代理访问,就把它发布到 localhost:

docker run -d -p 127.0.0.1:8080:80 nginx:alpine

选哪个套餐

Alpine 几乎把全部内存都留给你自己的软件。Nano 套餐(2 vCPU、1 GB、15 GB,$3/月)足够跑一个小服务或几个容器。这是 NAT 套餐,SSH 通过专属端口进入。如果需要向互联网开放 80 和 443 端口,Nano-IP 带独立 IPv4,$8/月。较重的 Docker 栈可以选 Micro,2 GB,$5/月。

Alpine 3.21 在 Alpine VPS 页面上,所有 VPS Linux 套餐都可选。支付方式为 Base、Ethereum 或 Polygon 网络上的 USDT、USDC 或 ETH,无需证件,也无需银行卡。

常见问题

为什么 Alpine 比 Ubuntu 或 Debian 小这么多?

它用 musl 代替 glibc,用 BusyBox 提供基础命令,用 OpenRC 代替 systemd。在我们的服务器上,全新的 Alpine 3.21 空闲时占用 55 MB 内存和 153 MB 磁盘。Ubuntu 24.04 占用 313 MB 和 2.7 GB。

密钥没错,为什么新用户还是提示 "account is locked"?

adduser -D 创建的账户没有密码,Alpine 会把它标记为锁定,sshd 随后即使面对有效密钥也会拒绝该用户。日志里的那一行是 "User deploy not allowed because account is locked"。用 passwd 给用户设置密码,密钥登录就能用了。

为什么 SSH 隧道在 Alpine 上不起作用?

Alpine 默认的 /etc/ssh/sshd_config 设置了 AllowTcpForwarding no,所以 ssh -L 转发会被拒绝。如果需要隧道,在该文件里改为 yes,然后运行 rc-service sshd restart。

我的程序能在 Alpine 上运行吗?

Alpine 软件仓库里的东西都能运行,基于任何基础镜像的 Docker 容器也能运行。为 glibc 编译的现成 Linux 二进制文件在 musl 上经常无法启动。找 Alpine 或 musl 版本,或者在 Docker 里运行程序。gcompat 包对一些简单的 glibc 二进制文件有帮助。

Alpine 用哪个套餐就够?

每月 $3 的 1 GB Nano 套餐绰绰有余:系统本身只用约 55 MB。如果需要向互联网开放 80 和 443 端口,选每月 $8、带独立 IPv4 的 Nano-IP。

评论

暂无评论。来做第一个吧。

发表评论

评论在显示前会经过审核。