前言
文章来源:CrociDB
原文作者:CrociDB(Antonio Vivace)
原文标题:This blog ran on Ubuntu 16.04 for 10 years. I migrated it to FreeBSD
原文发布时间:2026-05-21
原文链接:https://crocidb.com/post/this-blog-ran-on-ubuntu-16-04-for-10-years-i-migrated-it-to-freebsd/
本文为全文翻译,译文由 AI 辅助整理,若有理解偏差欢迎指正。
这篇博客已经在一台 DigitalOcean VPS 上运行了十多年。那是一台托管在纽约、运行着 Ubuntu 16.04 LTS 的机器。而这个 LTS 版本至少已经有 5 年不再受支持了。是时候做些改变了。经过一番权衡,我把它迁移到了一台 Hetzner 的虚拟机上:配置比我旧的 Ubuntu 机器强得多,价格还不到以前的一半,而且机房就在我所在国家的另一端。不仅如此,我还顺便挑战了一下自己,把整套栈迁到了 FreeBSD。这篇文章会有点长,但如果你愿意读下去,会看到一个关于 FreeBSD Jails、Bastille,以及一些有意思的网站负载测试结果的故事。
动机
如果你了解 Ubuntu 的发布和支持周期(我自己其实也不算熟),就会知道一旦某个版本结束支持,apt 对应的软件仓库也就没了,你再也拿不到更新。运行这样一套过时系统会带来不少问题,其中最显而易见的一点就是:你的服务器不再那么安全了。互联网上肯定有各种机器人,专门扫描存在漏洞的节点,然后想办法塞进去恶意内容。幸运的是(我想大概算幸运),我这里一直没出过事。反正机器里也没什么特别重要的东西可偷。但我记得很久以前,我还有一个 WordPress 博客,也是跑在一台老旧 VPS 上,结果某天文章正文里突然被插满了可疑的赌场和赌博链接。
我原本就有一台 Hetzner VPS,当作远程开发机来用,可以随时 SSH 上去,考虑到价格,它一直都很可靠。所以我决定先从对比配置开始。下面这台就是原来跑我的博客和其它网站的 droplet:
(原文此处有旧 DigitalOcean 服务器截图)
它有 2GB 内存、1 个 vCPU、50GB 磁盘、每月 2TB 流量,运行的是 Ubuntu 16.04 x64。机房位于纽约,这大概也是它比较贵的原因:我每个月要为它支付 13 美元。
Hetzner 是一家老牌欧洲 IT 公司,在德国有大型数据中心,而我也住在德国。它最便宜的一款服务器,只要 3.56 欧元,配置就已经比我原来那台更好了:
(原文此处有 Hetzner 入门套餐截图)
内存和 CPU 都翻倍,存储稍微少一点,但月流量多了十倍。不过我最后还是选了一台更“豪华”的配置,每月不到 6 欧元:
(原文此处有更高配套餐截图)
对我的这些站点来说,这配置甚至有点过头了,不过为什么不呢?
旧的部署方式
我那套旧环境托管的不只是这个博客,还有几个别的网站。它们都不算热门;在所有站点里,这个博客流量算最高的了,但每个月也不过几千次页面浏览。除了偶尔有几篇文章在 Hacker News 上爆一下,平时根本没多少流量。说到底,这台机器基本就是在提供静态网站服务,没有复杂 CGI,也没有什么自定义后端代码在跑。整套栈很简单:所有内容都通过 nginx/1.10.3 以静态方式提供。我基本上就是在 /etc/nginx/sites-available 里给每个站点放一份配置文件。像静态站点生成器、LaTeX 套件之类的附加程序(比如这个博客就是用 Hugo 生成的)则通过 apt 或 snap 安装。事实上,我更新博客的流程一直是这样:
- 在本地写文章
- 提交并推送到仓库
- SSH 登录服务器
- 拉取仓库更新
- 运行
hugo
这台 VPS 刚开始用的那些年里,我还会拿它做一些测试和编程实验。所以机器里积累了很多已经不再使用的老旧软件,显得很臃肿。但它就是能跑,而且跑得还挺好。
(原文此处有 Linux 4.4 截图)
它甚至好到什么程度呢?我关机前,它的 uptime 达到了 1491 天,也就是差不多连续 4 年没中断过。
为什么选 FreeBSD
说实话,我的主要动机之一就是想亲手折腾点不一样的东西。我最近读了很多、也看了很多关于 BSD 家族的内容,而我之前也曾短暂用过 FreeBSD,所以我觉得这是一个把它放到真实生产场景里试一试的好机会。FreeBSD 常常因为它的一体化设计、安全性以及 Jails 而被人称赞。后面我会详细展开。
我不想装得好像自己一开始就完全知道该怎么做,但当我读到 Jails 时,我立刻就知道自己想怎么搭了。Jails 是一种虚拟化/容器化机制,已经存在于 FreeBSD 里超过 25 年了,比 Docker 诞生还早得多。乍一看,它实现的效果和你对 Docker 容器的预期很像:在系统里面隔离出一个“小系统”,你可以在里面运行一些拿不到宿主机权限的东西。但在我看来,Docker 以及其它容器方案更适合“打包程序”——它们强调短生命周期和不可变;容器内处理的数据来自外部,但容器内部本身最好始终保持一致。而 Jails 更像真正的子系统,几乎可以把它看作迷你虚拟机,只不过底层仍然共享同一个内核。
除此之外,FreeBSD 的文件系统 ZFS 对服务器场景也确实非常好用。如果你来自 Linux 世界,大概听说过 Btrfs,它是近几年越来越多发行版开始采用的新文件系统。它和 ZFS 有一些相似点,比如数据完整性和快照。不过 ZFS 大概比 Btrfs 要成熟得多。如果我能频繁地给系统做快照,就不需要依赖 VPS 提供商的快照或备份服务,而那些通常都要额外付费。
我的想法是:每个网站一个 Jail,里面装上构建这个网站所需的工具(比如博客需要 Hugo),再在 Jail 里运行一个 nginx 实例来提供服务;另外再单独放一个主 Web 服务器 Jail,通过反向代理把外部世界和这些站点连起来。这样一来,哪怕某个 Jail 被攻破了,我也可以把它直接销毁,再建一个新的。后面我会更具体地介绍配置过程。
Hetzner VPS
先给所有喜欢看系统信息的人一点细节:
(原文此处有 fastfetch 截图)
搭建过程
我会快速讲一下自己是如何把这台服务器搭起来的,以及其中最关键的几个点。平时我会记开发日志,所以这次也是边做边记。不过不要把这篇文章当作教程,因为我可能漏掉了一些步骤。更准确地说,这是一篇“在 Hetzner 上用 FreeBSD 搭 Web 服务器是什么感觉”的记录。
安装 FreeBSD
Hetzner 在创建虚拟机时会提供一些镜像,但选择其实非常有限:
(原文此处有 “No BSD” 截图)
不过我在 FreeBSD 官方 YouTube 频道 上看到了一份讲如何在 Hetzner 上安装 FreeBSD 的指南。顺带一提,这个频道非常推荐。
关键在于:Hetzner 其实提供了 FreeBSD 镜像,只是藏得比较深,需要多点几步。它是以 ISO 镜像的形式提供的。所以在创建虚拟机、选择操作系统镜像的时候,你先随便选一个,反正稍后都要把它抹掉。创建完虚拟机后,只需要去控制台里的 ISO Images 标签页,挂载你想要的镜像即可:
(原文此处有 FreeBSD ISO 镜像截图)
我选的是 14.3。然后重启,基本上就按安装器一路走下去。印象里我没有改什么默认选项,当时是跟着官方 FreeBSD 频道里的安装视频一步步做的。很快,系统就装好并跑起来了。
Bastille
前面我已经提了好几次 Jails。但我用的不只是 Jails,还用了 Bastille,这是一个用来管理 Jails 的系统。原因很简单:手动创建 Jail 这件事比我想象中复杂,而且每新建一个 Jail,都有一堆独立步骤需要自己处理。Bastille 把这些都简化了,很多事情只差一条 bastille 命令。比如 bastille list 可以列出系统里的所有 Jail,bastille create 用来创建新 Jail,bastille console 则可以直接打开某个 Jail 的 shell,等等。
安装并启用它(几乎)就像 官方文档 里说的这么简单:
pkg install bastille
sysrc bastille_enable="YES"
当然也有别的 Jail 管理器,我只是选了一个名字最酷的。
整体架构
整套思路是:先有一个运行 Caddy 的 Jail,负责对外提供所有站点,并处理域名和 SSL 证书;然后每个站点再单独有自己的 Jail,里面安装各自构建和服务所需要的软件。这个“服务器 Jail”会把所有流量反向代理到对应的站点 Jail。所以第一步就是配置一个内部虚拟网卡。你可以把这套结构理解成:一组跑在同一个宿主机里的小型虚拟机网络。
配置虚拟网络接口的方式如下:
sudo sysrc cloned_interfaces+="lo1"
sudo sysrc ifconfig_lo1_name="bastille0"
sudo service netif cloneup
sudo sysrc ifconfig_bastille0="inet 10.0.0.1 netmask 255.255.255.0"
这几条命令本质上就是克隆一个回环接口,把它命名为 bastille0,再给它分配网络参数。所有 Jail 只会跑在这张网络接口上。至于 Caddy 所在的 Jail,因为它需要监听外部请求,就必须具备访问外网的能力。为此,我们要用 PF(Packet Filter,也就是 FreeBSD 的 防火墙)配置一条出网规则。
我们需要编辑 /etc/pf.conf:
# the main interface `vtnet0` and the virtual one we created `bastille0`
ext_if = "vtnet0"
int_if = "bastille0"
vpn_if = "tailscale1"
# skip internal traffic
set skip on $int_if
set skip on $vpn_if
# allow outbound access to the internet from the jails
nat on $ext_if from 10.0.0.0/24 to any -> ($ext_if)
# redirect HTTP/HTTPS traffic from the web to the server jail (10.0.0.5)
rdr pass on $ext_if proto tcp from any to any port {80, 443} -> 10.0.0.5
# block everything else
block all
# allows outbound traffic from host
pass out quick on $ext_if keep state
正如配置里的注释所写,这段规则主要做了几件事:把 bastille0 和 tailscale1 上的内部流量跳过处理;允许 Jail 和宿主机出网;再把所有 80 和 443(HTTP/HTTPS)流量重定向到内部 IP 10.0.0.5,也就是我们的 Caddy 服务器。
然后启用 PF:
sysrc pf_enable="YES"
service pf start
sysrc gateway_enable="YES"
至此,网络层的基础就完成了。接下来开始创建 Caddy 服务器 Jail。
创建第一个 Jail:Caddy Server
我的旧服务器一直在跑老朋友 nginx。除了早年短暂用过一点 Apache,我人生的大多数时间都在用 nginx。不过 nginx 有个烦人的点,而 Caddy 正好能漂亮地解决:SSL 证书。以前在旧服务器上,我得隔三差五跑一遍 certbot 去续域名证书,而且续签忘掉的次数比我愿意承认的要多。Caddy 会自动处理这些事情。
要创建一个新 Jail,先得为当前要使用的 FreeBSD 版本做 bootstrap,在我的场景里是 14.3-RELEASE:
bastille bootstrap 14.3-RELEASE
然后创建真正的 Jail:
bastille create caddy 14.3-RELEASE 10.0.0.5 bastille0
bastille start caddy
这里我们创建了一个名为 caddy 的 Jail,使用 14.3-RELEASE,IP 为 10.0.0.5,挂在 bastille0 接口上。
检查 Jail 状态:
# bastille list
JID Name Boot Prio State Type IP Address Published Ports Release Tags
3 caddy on 99 Up thin 10.0.0.5 - 14.3-RELEASE -
这样它就已经跑起来了!要记住,Jails 并不是像 Docker 容器那样追求 ephemeral 的东西。你不会先把容器完全定义好,然后指望它永远都保持一模一样。这里的感觉更接近虚拟机。你随时都可以通过下面的命令进到它的 shell:
# bastille console caddy
[caddy]:
root@caddy:~ #
配置 Caddy Server
既然我们已经在 caddy 这个 Jail 里了,那只需要把 Caddy 装上:
pkg install caddy
sysrc caddy_enable="YES"
service caddy start
Caddy 的所有配置都放在 Jail 里的 /usr/local/etc/caddy/Caddyfile。如果我们想在宿主机上也能直接访问这份配置文件,就需要把宿主机上的一个目录挂载到 Jail 里。甚至还可以用只读模式挂载,这样 Jail 自己就无法修改配置。大概像这样:
bastille mount caddy /usr/local/etc/my-caddy-config /usr/local/etc/caddy nullfs ro 0 0
好了,服务器差不多配完了,但我们还没有一个真正的站点。所以先建一个站点 Jail,然后再回来配置 Caddy。
第一个站点:es.cro.to
疫情期间,巴西总统选择把 Covid-19 当作感冒来对待,没有采取任何紧急封锁政策。他不断强调国家不能停摆,承担不起代价,哪怕有人因此死掉也无所谓。这完全无视科学,甚至无视常识。历史已经证明他有多错。对此我很不爽,于是我想做一点“抗议”。
所以我做了一个小页面 es.cro.to。它在葡萄牙语里字面上是“阴囊”的意思,但更常被用来形容一个人是个 混蛋、烂人,或者别的类似意思。我买下了 cro.to 这个域名(现在回头看,这域名其实挺酷的,英文里听起来也不错),然后加了一个 es 子域名。它刚好把这个词按字典式的音节拆开,于是我就在页面里放上了这个词的词义和对应生物的图片:
(原文此处有 escroto 页面截图)
它当然也是跑在我的旧服务器上的,而且在封锁那段时间还获得了不小的流量。我决定先从它开始迁,因为它本质上只是一个带着一张压得很惨照片的单页站点,而且现在也没那么重要了。
这个站点和我其它站一样,也是一个 Git 仓库。所以我准备把所有网站都放在宿主机的 /usr/local/www 下,然后把各个站点对应的目录以只读方式挂载到对应 Jail 里。于是,当我把这个站点放到 /usr/local/www/escroto 后,就开始用 Bastille 创建 Jail。这次我直接用了一个用于 nginx 的 bastille 模板:www/nginx。模板其实就是预装一些软件的小脚本。其实不用也行,但既然有,为什么不用呢?
bastille bootstrap https://github.com/bastillebsd/templates
bastille create escroto 14.3-RELEASE 10.0.0.11 bastille0
bastille template escroto www/nginx
我给它分配的 IP 是 10.0.0.11,等会会用到。此时,这个 Jail 里的 nginx 已经在提供默认页面了。它的站点目录位于 /usr/local/www/nginx(注意,FreeBSD 几乎什么都放在 /usr/local 下)。
接着,我把宿主机上的站点目录挂到 Jail 里:
bastille mount escroto /usr/local/www/escroto /usr/local/www/escroto nullfs ro 0 0
这样一来,我在 Jail 内就能访问 /usr/local/www/escroto 这个站点目录了。因为它是个 Git 仓库,里面带有 .git 之类不该被直接提供出去的文件,所以我写了一个 deploy.sh 脚本,把 /usr/local/www/escroto/* 复制到 /usr/local/www/nginx/*,再删掉 .git 目录:
rm -fr /usr/local/www/nginx/*
cp -R /usr/local/www/escroto/* /usr/local/www/nginx/
rm -fr /usr/local/www/nginx/.git
这样以后每次要部署这个站点的新版本,只需要登录宿主机,更新仓库,然后执行这个脚本:
cd /usr/local/www/escroto
git pull
bastille cmd escroto /root/deploy.sh
后来我发现这个思路挺好,于是也给其它站点都放了一份 /root/deploy.sh。
让 Caddy 把域名指向这个 Jail
回到 Caddy 配置:
cro.to {
redir https://es.cro.to{uri} permanent
}
es.cro.to {
reverse_proxy 10.0.0.11
}
配置非常简单:主域名重定向到 es.cro.to,再由后者反向代理到 10.0.0.11,也就是 escroto Jail。
配置好 DNS 记录后,这个站点就上线了。
部署这个博客
这个博客本身是用 Hugo 写的,仓库放在 GitHub 上。所以我把它克隆到了 /usr/local/www/blog,然后像 escroto 一样创建了一个新的 Jail:
bastille create blog 14.3-RELEASE 10.0.0.12 bastille0
bastille template blog www/nginx
bastille mount blog /usr/local/www/blog /usr/local/www/blog nullfs ro 0 0
然后在这个 Jail 里安装 Hugo:
bastille pkg blog update
bastille pkg blog install gohugo
部署脚本也很类似:
rm -fr /usr/local/www/nginx/*
cd /usr/local/www/blog
hugo -d /usr/local/www/nginx
在正式把站点迁离旧服务器前,我想先做一些基准测试,所以先把博客绑定到了一个旧域名上:
crocidb.cro.to {
reverse_proxy 10.0.0.12
}
就这么简单,博客已经在新服务器上跑起来了。
给我的服务器做基准测试
在正式更新 DNS 记录前,我想确认这台新服务器到底能不能扛住流量。理论上看它当然行,但万一我哪里配错了呢?于是我开始琢磨,怎么比较旧服务器上的 crocidb.com 和新服务器上的 crocidb.cro.to。
一开始我先想清楚,到底该测什么。测延迟没什么意义,因为我知道,对大多数访问我博客的人来说,新服务器的延迟本来就会稍微更长一些。这个站点的大部分流量通常来自北美,其次是欧洲,再然后是南美。不过那点差距其实不至于影响体验。所以更值得测的是:服务能力和高负载表现。
市面上有一些免费的在线工具,可以做比较通用的测试,比如 GTMetrix、Pingdom 和 WebPageTest。但老实说,这两台服务器在这些工具里的差异几乎只体现在延迟上,其它方面基本差不多。所以我决定往更深一点挖。
我发现了 wrk 和 hey 这两个 HTTP 压测工具。它们本质上就是对网站发起成千上万的并发请求,然后收集诸如请求延迟、错误响应、每秒传输量等信息。比如,我在另一台 Hetzner VPS 上跑了下面这个 wrk 命令:
wrk -t4 -c100 -d30s --latency https://crocidb.com/
这表示让 wrk 用 4 个线程、维持 100 个并发连接、持续压测 30 秒。这个数字其实也不算特别离谱。结果如下:
Running 30s test @ https://crocidb.com/
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 89.63ms 18.31ms 189.09ms 95.29%
Req/Sec 211.74 38.44 313.00 87.69%
Requests/sec: 833.41
Transfer/sec: 8.29MB
而对 crocidb.cro.to 测出来是:
Running 30s test @ https://crocidb.cro.to/
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 6.75ms 3.59ms 51.98ms 74.41%
Req/Sec 3.08k 260.11 4.34k 81.83%
Requests/sec: 12260.10
Transfer/sec: 130.80MB
旧服务器每秒能处理 833 个请求,而新服务器则达到 12,260。平均延迟则是 89ms 对 6ms。但这当然不公平:压测机器和新服务器在同一个数据中心。所以我想,要不试试挂 VPN,从不同地区去测?
我用的是 Proton VPN,于是写了一个小脚本,从一组地点里选一个,连上 VPN,再跑 wrk。结果非常平淡:旧服务器平均大概 300 req/s,新服务器大概 800 req/s。测试地点如下:
LOCATIONS=(
"US//New York|US - New York"
"US//Los Angeles|US - Los Angeles"
"BR//São Paulo|BR - São Paulo"
"GB//London|GB - London"
"DE//Frankfurt|DE - Frankfurt"
"FR//Paris|FR - Paris"
"SE//Stockholm|SE - Stockholm"
"CH//Zurich|CH - Zurich"
"IN//Mumbai|IN - Mumbai"
"JP//Tokyo|JP - Tokyo"
"KR//Seoul|KR - Seoul"
"SG//Singapore|SG - Singapore"
"AU//Sydney|AU - Sydney"
"ZA//Johannesburg|ZA - Johannesburg"
"AR//Buenos Aires|AR - Buenos Aires"
)
于是我放弃了“用终端用户 VPN 视角来测”的思路,转而采用一种更硬核的办法:直接在世界各地的数据中心创建真正的 VPS 节点来跑测试。
Vultr VPS 基准测试
我需要一家不同于 DigitalOcean 和 Hetzner 的 VPS 提供商,以免底层基础设施带来额外优势。除了这两家,我唯一用过的 VPS 服务商就是 Vultr。于是我决定在不同地区各开一台机器跑测试。因为整个过程是手工完成的,所以最后只选了四个地区:伦敦、圣保罗、硅谷 和 东京。我在这些地区各创建了一台最便宜的 Fedora 虚拟机。
经过几轮测试后,我发现 hey 更符合我的需求。于是我的流程就变成:SSH 登录测试机,执行脚本,然后把结果拷出来。第一个测试点是圣保罗:
dnf install -y tmux vim htop
wget https://storage.googleapis.com/hey-releases/hey_linux_amd64
chmod +x hey_linux_amd64
./hey_linux_amd64 -n 1000000 -c 10000 -t 10 -z 5m -h2 https://crocidb.com/ > crocidb.com.log
./hey_linux_amd64 -n 1000000 -c 10000 -t 10 -z 5m -h2 https://crocidb.cro.to/ > crocidb.cro.to.log
这会下载 hey,然后以一种非常夸张的配置运行:总请求数 1M,并发 10k,超时 10s(也就是任意单个请求超过 10 秒就算失败),总时长 5m。
第一次跑的时候,我很快就发现新 FreeBSD 服务器确实有个问题:它很早就开始失败,因为它根本扛不住 1 万并发连接。查了很多资料后,我发现可以用 netstat -Lan 查看 socket 队列大小,而我的队列值全都是 128。继续追下来才发现,原来 kern.ipc.somaxconn 的默认值就是这个数字。于是我把它调高了:
sysctl kern.ipc.somaxconn=16384
差不多十分钟后,日志跑完了,我开始看结果:
(原文此处有圣保罗 VPS 上 hey 输出对比图)
左边是旧服务器,右边是新服务器,差异简直夸张。
虽然两台机器都返回了不少错误,但 FreeBSD 这边至少完成了预期的 1M 请求,而 Ubuntu 那边连 20k 都没撑住!这个差距实在是太大了。
基准结果分析
(原文此处有成功率图表)
旧服务器 crocidb.com 只能完成极少一部分请求,这一点真的很惊人。实际上,它只完成了大约 7% 的请求,而 FreeBSD 服务器完成了 94%。东京地区里新服务器的成功率略微低一点,但我觉得还不至于值得担心。
从每秒请求数来看,新服务器最少也有 3 倍提升,最高甚至能到 11 倍。
(原文此处有 Requests per second 图表)
这里的差距看起来更夸张,而我猜测东京那边的延迟可能确实更高一些。
(原文此处有延迟百分位图表)
如果看延迟百分位(例如 p50 表示 50% 的请求都比这个值更快返回),会发现两台服务器呈现出很不一样的曲线形态。新服务器直到大约 90% 之前都保持比较 线性 的增长,所以表现更可预测;而旧服务器的增长曲线则明显更不稳定。
这说明,即使在高负载下,全球范围内 90% 的访问者在尝试加载我博客首页时,仍然能在 3.5 秒 内拿到内容。我觉得这已经相当不错了。
我没有再继续深挖东京地区的问题,不过目前我也没那么担心。看 hey 的请求阶段分解(也就是它会拆分 DNS、连接、等待响应、读取响应等耗时),确实能看出日本方向的流量更慢一些:
(原文此处有请求阶段耗时分解图)
不过这些数据在我看来又有点怪。首先,第二个域名的 DNS 拨号和查询时间低得离谱,也许是因为它是个 CNAME 记录?其次,resp wait(基本可以理解成首字节时间)和 resp read(传输时间)在这里高得有点异常。但这也可能是因为它统计的只是成功请求:也就是说,旧服务器可能一开始响应很快,但很快就把新请求都拒掉了。
结论
我并不认为这个差距是因为我选的这套栈本身就有多神奇。更有可能的原因是:旧 Ubuntu 系统本身就有一些配置问题,再加上我选的 Hetzner VPS 有 4 个 CPU 核,而旧 DigitalOcean 机器只有 1 个,自然能同时处理更多请求。我也不觉得这在实际意义上真的有多重要,因为这些服务器几乎不可能真的遇到这么大的并发量。也许跑一遍 WebPageTest 这样的 Web 基准工具就已经够了。
真正切换
虽然这些基准测试还留下了很多未解答的问题,但我对结果已经很满意了。所以我直接更新了 DNS 记录。现在,这个博客已经正式跑在那台新机器上了。
说到底,经过很多个小时的实验、折腾、构建、推倒重来之后,我意识到:搭一台用 FreeBSD 托管网站的机器,其实并没有我想象中那么复杂。满足我需求的 Web 托管服务其实也有不少,我本来也完全可以用别的方案。或者装一个 Proxmox,用图形化仪表盘来管理容器和系统。甚至也可以试试它在 FreeBSD 世界里的对应物 Sylve。但我还是很喜欢自己这次走过的这条路,因为整个过程让我学到了很多。
其中几个最主要的收获是:
- 那台 Ubuntu 服务器真的非常皮实。十年来,它一直把我这些站点的负载扛得很好。最后四年甚至一次都没重启过。而这一切并不需要多复杂的配置。
- 配置 FreeBSD 比我原本想象的容易。我很喜欢把系统配置集中在一个地方管理的感觉,而且它的在线文档也真的非常好。
- 想自己搭一台托管博客的机器,往往需要大量网络知识,而这些远远超出了一个游戏开发者通常具备的范围。
- 学习另一套系统真的很有趣。也许下次我会试试 OpenBSD 或 NetBSD。
不过说到底,这一切也没什么意义,因为我的大部分流量现在反正都来自各种 AI 抓取器……
