狐狸会喜欢树莓做的派吗?树莓派鼓捣记

by SouthFox

2025-12-12

今年双十一的时候出于好像得买点什么非常「消费主义」念头购入了一块 8G 版的树莓派 5 和一块 2T 的七彩虹 ME700 固态硬盘。 现在一个月过去了,在不断折腾下也算是有点能写的东西了,所以在这里写成一篇文章。

在硬件上折腾并不多,除了开头买的固态硬盘转接板小了点一开始很灵车的拿了板子暂时压住(见 FoxThinking #5 ),之后再加购了个合适 长度的转接板接上最后没什么问题了。用 fio 测速了一下,读写标称 7000MB/s 和 5500MB/s 的硬盘通过转接板后只能跑出读写均只有 420MB/s 的「好成绩」,真算得上是吕布骑狗了。

不过想开点上固态硬盘不用听「炒豆声」也是件好事,而且找补一下在双十一购入的时机也正是时候,在现在 DRAM 芯片价格飙升的时候买也是赶 上末班车了 1 2 。在考虑买树莓派之前我也考虑过其它的「国产派」,纸面参数更好而且更便宜,似乎是更好的选择?但我在实际逛 了相关的店铺后发现有点不对劲,可选的东西很少而且并没有参与什么活动。网上搜了下发现一些吐槽,包括找不到什么工程师啦、快速发板的策略 导致旧产品很快就没维护啦等等。为了减少折腾我还是直接买树莓派吧,而且也有一些店铺参与了双十一活动,最后就购入了最基本入门套餐(那些 嵌入式的传感器马达之类的我不怎么感兴趣就觉得没必要买了)。

然后来说说在系统上面的折腾吧,首先就是刷入系统,查找了下相关资料发现 Arch linux 对于 ARM 的支持比较堪忧,社区似乎没什么活跃度,看起来没多少 人用 Arch 系统来折腾树莓派这种边缘设备啊。之后不折腾选择官方系统,这方面我直接用官方的镜像刷入应用将桌面版系统刷入到店铺附赠的 SD 卡然后通过 VNC 打开远程桌面里面打开镜像刷入应用然后往固态硬盘刷入无桌面的 lite 版。这个看起来很古怪的流程是因为我没有其它能够刷入固态硬盘的手段,然后试了下 将 lite 系统刷入到 SD 然后在系统中将数据拷贝到固态硬盘的方式失败了,索性就直接通过官方的镜像刷入应用操作不操其它心了。刚好将这个 SD 卡内的系统 作为一个救援系统。刷好系统后通过官方 raspi-config 将从固态硬盘调整到第一启动项就可以了,用官方系统的这些设置上就不用怎么操心也是挺好的。

想当然的鼓捣

软件上的折腾倒是没有什么稀奇的,跟其它在 VPS 等 linux 机器上折腾的差不多,不过就是因为太差不多了所以有点倦了:弄点 docker-compose.yml 或者 在包管理器装点应用;编辑配置文件;调一下 nginx 文件……这些事因为做过太多次了所以就没有热情了。欸,如果有一个方式只需要填点参数就能配好服务就好了 啊,最好不要是什么类似 ansible 的基于 yaml 的方式而是更直接的方式,用「正常」的编程语言例如 python 写点配置:

setup_service(application="tailscale", systemd_enable="tailscaled")
setup_nginx_service(host="blog.example.com", nginx_root="/var/host/blog")
setup_nginx_service(host="pihole.internal", application="pihole", config_path="...")

之后通过一些「神奇」的一通操作就能配好所有相关服务和配置文件了, 这好像有点想当然了(wishful thinking),在顶层这么只是想想那底层该怎么考虑呢?可以考虑到将服务使用一个 规范来规定 如何解释自己服务如何影响其它服务 。一个生活化比方就是做菜:

做菜需要准备很多东西并执行很多步骤,如何尽可能地管控复杂度呢?例如我想要做一碗「黯然销魂饭」,可 以先声明一个「做菜声明」服务:里面「如何解释自己」为具体做菜的步骤,例如将什么食材放入什么厨具做什么 操作(将米饭进行淘米后放入煤气炉灶蒸煮……);而「如何影响其它服务」是向「食材准备服务」声明想要 什么材料(米饭、肉、盐、油……)和「厨具准备材料」声明想要什么厨具(煤气炉灶、锅铲、勺子……)。然 后「下面」的服务可以继续执行这套流程,「食材准备服务」和「厨具准备服务」的「如何解释自己」是将自己收到 的需求列成一份清单;而「如何影响其它服务」是向「购物服务」提交清单。最后的「购物服务」的「如何解释自己」 就是将收到的清单汇总并到商场里头购买,至于「如何影响其它服务」?这是个底下实际办事的服务,做好 自己的事就好了,谈不上影响(好吧其实就是不需要)。

这种方式就类似软件设计,将一个模糊宽泛的需求拆成一个个具体的「函数」,这里带来的好处就是如果是以 一个「正经」编程语言实现(不要用 yaml 实现了,求求了)的话,可以很轻松复用流程控制语法和已有的函数。例如通过主机名 进行判断达成在不同机器上部署不同服务的效果:

if hostname == "homelab":
    setup_service(application="zerotier", systemd_enable="zerotier-one")
    setup_nginx_service(host="blog.example.com", nginx_root="/var/host/blog")
    setup_nginx_service(host="pihole.internal", application="pihole", config_path="...")
    ...
if hostname == "vps1":
    setup_service(application="tailscale", systemd_enable="tailscaled")
    setup_nginx_service(host="git.example.com", application="forgejo", port="8081")
    ...


calculate_services()

在上面这个例子中,一个可能的实现是假设一层层传递到底下会有 类似「包管理服务」收集了 nginx, docker, tailscale 这种软件,那么里面「如何解释自己」是将自己收集到的包转成一行命 令,例如: apt install -y nginx docker tailscale ,而最后的「如何影响其它服务」就是向「代码执行服务」添加 命令。而「代码执行服务」就是将所有声明服务传递进来的命令收集到一个类似 final_script.sh 这样的脚 本中。这样等「计算」完整体的服务后,执行这个脚本就相当于完成了部署操作了。

凑合就好

虽然上面的方案好像挺简单并且可能鼓捣一下也确实能用,不过我这种懒狐还是很「拿来主义」的,上面所说的基本就是 Guix Service Types and Services 的解释。这种方式在理解后确实还是很直接的,只用记住如 何 如何解释自己服务如何影响其它服务 就能掌握个大概。用这种方式我也是成功的把相关的配置塞进了少数 几个文件里,虽然离完全抽象顶层的简单定义还有段距离,不过还是,也不是不能用吧。

鼓捣的服务

podman

首先在树莓派上我是用了 Podman 作为容器的方案,不选 docker 是因为看重了 podman 注重 rootless 还不需要一个在后台常驻的守护进程。 Podman 在 Guix 里就可以直接安装,不过好像基本都要自己源码编译安装,官方的缓存服务器经常命中不了二进制产物,看来不管是 Arch ,在 Guix 里 也很少用 ARM 平台的啊。

因为 podman 不是 docker ,所以默认并不会觉得镜像是在 docker.io 上,所以相关的镜像名称要写全,例如 nginx 在 docker 里 只用写 nginx:latest 但在 podman 里要写成 docker.io/library/nginx:latest 。同时还需要往 ~/.config/containers/policy.json 声明 能向什么服务商拉取镜像,不安全的写法可以写接受全部:

{ "default": [ { "type": "insecureAcceptAnything" } ]

calibre-web

通过 podman-compose 拉起的程序,因为在 Humble Bundle 买了几个书籍捆绑包也是堆了百来个电子书了(详情见 FoxThinking #6 ), 所以需要一个管理的程序,最后也是选择了 calibre-web 。官方不推荐将数据库文件放到网络存储上所以我现在就简单通过 rsync 来同步状态, 不过这需要我自己维护状态手动选择哪边的状态进行同步,可能之后可以写点脚本自动比对树莓派上和本地的状态哪边新就更新到哪边吧,感觉 有点类似 git 了……

aria2

通过 guix 安装,是一个简单的下载程序,从网上拷贝了一份配置文件就这么直接用了,虽然用的不多但是胜在多线程和 bt 下载的能用上。

ariang

一个静态的前端,通过 json-rpc 和后面的 aria2 交互,在网页上展示点下载速度曲线和新增下载任务,比敲命令行好点(主要不会将又长又杂的下载地址放到 历史记录干扰到 fzf )。

webhook

通过 guix 安装,是一个用 go 写的程序 3 提供 webhook 服务,webhook 简单说就是提供一个 uri 当有 GET 或者 POST 的 HTTP 请求时执行一些动作 (例如执行脚本), 我现在用来触发下我的博客构建流程。

syncthing

通过 guix 安装,一个 P2P 式的文件同步软件,我通过它来同步我的笔记。因为我的树莓派现在没有作任何的备份措施所以我就在我的设备 上(包括手机)用 syncthing 来进行备份(感觉……有点类似 git 了)。

rslsync

虽然是直接从官网下载的二进制文件但通过 guix 定义的安装过程也算是通过 guix 安装,我用来同步书格的一些古籍资料,对比起 syncthing ,rslsync 是面向公网有点类似种子下载而 syncthing 是面向个人的比较私域(类似 git )。

cloudflared

通过 guix 定义的编译流程所以也能算是通过 guix 安装。用 cloudflare 的网络进行内网穿透,我现在用来提供博客(树莓派不得不尝的用途) 和 webhook 服务的访问。 虽然 cloudflare 免费且功能丰富,不过为了更有独立性我看看之后能不能找到一个可自托管选项,简单点 frp 也可以不过感觉面对大墙可能 会有点不稳定。

anki

通过 podman 安装 4 然后开启的代替 anki-web 的 sync 服务,用来在各种设备之间的同步统计资料和牌组文件,通过 cloudflared 提供公 网访问,资料在所有设备上都会存一份只不过用树莓派提供一个同步渠道(感觉……还是有点类似 git )。

nginx

通过 guix 安装,不过因为上游的定义里没有带上 realip module 所以我简单继承了上游的定义加上了 --with-http_realip_module 的参数。 对这个程序再无话说,只是速速用起来。

pihole

使用 podman-compose 安装,一个自建的 dns 服务,对比起四年前的博文 搭建无污染的DNS服务 不同是 pihole 里终于在 pi 上运行了,而且在可触及范围内搭建 比较方便该路由器设置 DNS 让局域网内的设备网络请求都经过 pihole 。

另外就是 podman 里的服务似乎会占用 53 端口和 pihole 冲突,得需要在 ~/.config/containers/containers.conf 里配置成另外的端口规避:

[network]
dns_bind_port=5000

smartdns

一个功能丰富的 dns 应用,在最近支持网页控制台后其实完全就可以替换 pihole 了,不过既然都用树莓派了我还是 继续用着 pihole 吧,现在用着 smartdns 主要是作为 pihole 的上游然后搭配 dnsmasq-china-list 项目作为国内服务 的加速和国外的 DOH 分流。

zerotier

通过 guix 定义的编译流程所以也能算是通过 guix 安装,用来组建方便在公网环境的访问的虚拟局域网。不得不说在 guix 上的投入还是值得 的,之前为 steam deck 写的 5 zerotier 定义在 debian 系统也能轻松跑起来,这种编写一次到处运行的滋味还是挺美妙的。

总结

这篇博文到最后快要变成 guix 的安利文了?

不过我现在用着 GNU/Linux 然后用着 Emacs 写着东西然后用点 Lisp 折腾树莓派,感觉快要成为那种典型的自由极客了。一路过来感想是 虽然有点痛苦但好像也没那么痛苦,在现在互联网发展快三十年的时代哪怕不融入社区不和人交流只凭一些网上「捕风捉影」的消息也能在小众领域行走。 说到这发现我确实不怎么依赖社区和求助于他人,遇到难题只会死磕实在磕不过就会放弃睡大觉,虽然这也没什么 6 ,不过想想有时候求助他人 可能是一个「省力」的选择呢?或许这点可以作为下一年的课题……

脚注

1 奇客Solidot | DRAM 芯片价格涨幅超过黄金

2 奇客Solidot | 树莓派因为内存价格飙升而涨价

3 Webhook GitHub 地址

4 GitHub - LuckyTurtleDev/docker-images

5 Steam Deck 可劲折腾

6 奇客Solidot | 很多时候放弃是最明智的选择

修改历史

<2026-02-06 Fri 00:22> 将用 python 伪代码的例子更改为用做菜煮饭的例子。

如不想授权 Giscus 应用,也可以点击下方左上角数字直接跳转到 Github Discussions 进行评论。