
如果你能用1瓦的功率运行一个博客,通过4G网络从太阳能供电的树莓派零上提供服务会怎样?
作为软件工程师,我们大部分时间都生活在一个拥有几乎无限云资源的世界里,硬性限制已经被弹性账单和一层又一层让我们远离硬件的抽象(IaaS、PaaS、SaaS)所取代。很容易忘记用很少的东西能做什么。
这是一个用更少做更多的实验。跟我一起踏上这段旅程。
这是一个2部分系列的第1部分。 第1部分(本文)涵盖使用Cloudflare隧道通过4G构建和提供博客。 第2部分将进一步离网:用太阳能板和电池扩展板为整个装置供电,让它在夜间持续运行,设置扩展板上的GPS模块,以及一些从树莓派挤出每一毫瓦的技巧。
前提条件
开始前的先决条件:
- 一个添加到Cloudflare的域名(免费计划)——参见Cloudflare文档
- 你机器上的SSH密钥对(
~/.ssh/id_rsa)- 在本教程中,将
<user>替换为你选择的用户名(例如thylong),将<hostname>替换为你选择的主机名(例如solar)
硬件
| 组件 | 费用 |
|---|---|
| 树莓派零 2 W(推荐零2 W——它同时支持32位和64位系统;原始零W仅支持32位) | 18€ |
| 微雪电子SIM7600G-H 4G扩展板 | 75€ 哎哟… |
| Micro-SD卡(最小8GB)+ MicroSD转SD适配器(用于从笔记本电脑烧录) | 5€ |
| 10W 5V太阳能板USB-C | 25€ |
| Pi Sugar 3 Plus电池扩展板1200mAh——设置在第2部分中介绍 | 34€ |
| Nano SIM卡配合手机订阅 | 起价1€/月 |
| 总计 | 150€ + 1€/月 |

注意: 这个4G扩展板有很多更便宜的替代方案,电池也一样。
软件
| 组件 | 费用 |
|---|---|
| Cloudflare上的域名设置 | ~ |
| Cloudflare隧道 | 免费 |
步骤
硬件组装
- 关闭树莓派
- 将扩展板插到树莓派零的顶部,应该看起来像这样:

- 在4G扩展板中插入一张nano SIM卡
软件设置
安装操作系统
下载树莓派镜像工具:https://www.raspberrypi.com/software/
将树莓派操作系统精简版(零W用32位,零2 W用64位)烧录到你的MicroSD卡。
在镜像工具的高级选项(齿轮图标)中,在写入之前:
- 设置主机名(例如
solar)——这是你SSH登录的方式:ssh <user>@solar - 设置你的用户名和密码(例如
thylong) - 启用SSH并使用你的公钥
- 添加你的WiFi凭据——树莓派在首次启动时需要互联网访问才能激活树莓派连接
注意: 如果你没有键盘或显示器连接到树莓派,请确保提供有效的WiFi凭据并开启树莓派连接,这样你就可以使用屏幕共享。
树莓派连接到服务可能需要几分钟。如果5分钟后设备仍未出现,可能是WiFi和/或互联网连接不成功。你需要重新进行SD卡烧录阶段。
常见错误:错误的WiFi SSID、密码拼写错误或无效的认证密钥。
配置4G/LTE扩展板
启动树莓派。
确保扩展板正确连接
确保扩展板上的LED:
- PWR灯亮着
- NET灯闪烁模式:
- 慢闪(1秒亮/1秒灭)= 正在搜索网络
- 快闪(100ms)= 已注册并连接 ✓
如果30秒后NET灯仍然关闭或慢闪,说明扩展板与树莓派零的物理连接不正确,或者SIM卡未被识别。

确保从树莓派连接扩展板
连接到树莓派连接
安装所需软件包:
sudo apt update && sudo apt install -y minicom modemmanager network-manager
打开终端,确保/boot/firmware/config.txt中存在以下两行:
enable_uart=1
dtoverlay=disable-bt
这两行释放了GPIO头上的UART引脚,调制解调器使用这些引脚进行串行通信。没有它们,扩展板可能无法正确检测。
如果你做了任何修改,重新启动以应用(sudo reboot)。
然后运行ls /dev/ttyU*来列出ttys,树莓派应该已经通过USB检测到扩展板并输出:
/dev/ttyUSB0 /dev/ttyUSB1 /dev/ttyUSB2 /dev/ttyUSB3 /dev/ttyUSB4
以下是ttys的简单映射:
| 端口 | 功能 |
|---|---|
| /dev/ttyUSB0 | 诊断 |
| /dev/ttyUSB1 | GPS/NMEA |
| /dev/ttyUSB2 | AT命令 ← 使用这个 |
| /dev/ttyUSB3 | PPP/数据 |
| /dev/ttyUSB4 | 音频/其他 |
你可以通过AT命令端口测试通信:
sudo minicom -D /dev/ttyUSB2 -b 115200
然后:
- 按
Ctrl+A然后按E启用回显- 输入
AT+回车 - → 应返回
OK
- 输入
- 然后验证SIM卡:
- 输入
AT+CPIN? - → 应返回
+CPIN: READY
- 输入
- 然后验证网络
- 输入
AT+COPS? - → 应显示Orange详情(如果你使用Orange多SIM卡)
- 输入
其他测试用AT命令(供好奇者参考):
| AT命令 | 描述 | 返回值 |
|---|---|---|
| AT | AT测试命令 | OK |
| ATE | ATE1:开启回显,ATE0:关闭回显 | OK |
| AT+CGMI | 请求制造商识别 | OK |
| AT+CGMM | 请求型号识别 | OK |
| AT+CGSN | 请求产品序列号识别 | OK |
| AT+CSUB | 请求产品版本 | OK |
| AT+CGMR | 请求固件版本 | OK |
| AT+IPREX | 配置模型波特率 | +IPREX:OK |
| AT+CRESET | 重置模型 | OK |
| AT+CSQ | 查询信号质量 | OK |
| AT+CPIN? | 查询SIM卡状态 | +CPIN:READY |
| AT+COPS? | 查询运营商信息 | +COPS:OK |
| AT+CREG? | 查询网络注册状态 | +CREG: OK |
| AT+CPSI? | 查询UE系统信息 | |
| AT+CNMP | 选择网络模式 | OK |
如果你到了这一步,恭喜——调制解调器准备好创建连接了!
如果你使用minicom时遇到任何错误或没有预期输出,请检查
mmcli -L的输出,它会帮助调试。
要创建连接,运行以下命令:
我们使用APN
orange(不是orange.fr)。orange.frAPN用于网络共享并禁用IPv6——我们需要orange来稍后获取公共IPv6地址。
sudo nmcli connection add type gsm ifname '*' con-name orange-4g apn orange
sudo nmcli connection up orange-4g
sudo nmcli connection modify orange-4g connection.autoconnect yes
要测试连接,使用curl:
curl --interface wwan0 https://ifconfig.me
如果你看到你的公共IP,恭喜,你已经连接到4G了!
启用IPv6并使其持久化
Orange的4G在IPv4(CGNAT)和IPv6(防火墙)上都阻止入站连接。但是,Cloudflare隧道需要在端口7844上进行出站连接——Orange在IPv4上阻止了这个端口,但在IPv6上允许。因此,我们需要配置双栈IPv4v6并使其在重启后持久化。
# 将初始EPS承载设置为双栈
sudo mmcli -m 0 --3gpp-set-initial-eps-bearer-settings="apn=orange,ip-type=ipv4v6"
# 用双栈重新连接
sudo mmcli -m 0 --simple-disconnect && sleep 3 && sudo mmcli -m 0 --simple-connect="apn=orange,ip-type=ipv4v6"
# 从承载读取IPv6配置并应用到wwan0
BEARER=$(mmcli -m 0 --output-json | grep -o "/org/freedesktop/ModemManager1/Bearer/[0-9]*" | tail -1)
IPV6=$(mmcli -b ${BEARER##*/} --output-json | grep -oP '"address"\s*:\s*"\K[0-9a-f:]+(?=")' | head -1)
GW=$(mmcli -b ${BEARER##*/} --output-json | grep -oP '"gateway"\s*:\s*"\K[0-9a-f:]+(?=")' | head -1)
sudo ip -6 addr add ${IPV6}/64 dev wwan0
sudo ip -6 route add default via ${GW} dev wwan0
# 验证——应返回你的公共IPv6
curl -6 -s --interface wwan0 https://ifconfig.me && echo
上面分配的IPv6地址在重启后会丢失。为了使其持久化,创建一个systemd oneshot服务,在每次调制解调器连接后重新应用它:
sudo tee /usr/local/bin/apply-ipv6.sh << 'EOF'
#!/bin/bash
sleep 5
BEARER=$(mmcli -m 0 --output-json | grep -o "/org/freedesktop/ModemManager1/Bearer/[0-9]*" | tail -1)
IPV6=$(mmcli -b ${BEARER##*/} --output-json 2>/dev/null | grep -oP '"address"\s*:\s*"\K[0-9a-f:]+(?=")' | head -1)
GW=$(mmcli -b ${BEARER##*/} --output-json 2>/dev/null | grep -oP '"gateway"\s*:\s*"\K[0-9a-f:]+(?=")' | head -1)
if [ -n "$IPV6" ] && [ -n "$GW" ]; then
ip -6 addr add ${IPV6}/64 dev wwan0 2>/dev/null || true
ip -6 route add default via ${GW} dev wwan0 2>/dev/null || true
fi
EOF
sudo chmod +x /usr/local/bin/apply-ipv6.sh
sudo tee /etc/systemd/system/wwan-ipv6.service << 'EOF'
[Unit]
Description=Apply IPv6 to wwan0
After=ModemManager.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/apply-ipv6.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload && sudo systemctl enable --now wwan-ipv6
验证IPv6在重启后仍然有效:
sudo reboot
# 重新连接后:
ip -6 addr show wwan0
# 预期:一个全局IPv6地址(以2a01:或类似开头)
设置Web服务器
由于CGNAT和移动运营商防火墙通常会阻止其4G网络上的入站请求,我们需要使用反向隧道。有多种解决方案可用:Cloudflare隧道、使用VPS进行流量转发等。
我们将使用Cloudflare隧道,因为它简单、免费,并且不需要额外资源。在本教程中,我们假设你已经在Cloudflare上获取并设置了自己的域名(参见上面的前提条件)。
使用darkhttpd将Hugo博客部署到树莓派
在本地构建Hugo站点
安装Hugo并使用主题搭建新站点:
# 安装Hugo(macOS)
brew install hugo
# 创建新站点
hugo new site myblog && cd myblog
# 添加主题(例如Ananke)
git init
git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke
echo "theme = 'ananke'" >> hugo.toml
# 创建你的第一篇文章
hugo new content posts/hello-world.md
# 编辑content/posts/hello-world.md,设置draft: false
# 本地预览
hugo server
准备部署时,构建生产站点:
hugo --environment production --minify
这会在public/中生成静态站点(所有HTML、CSS、JS和准备提供的资源)。
同步到树莓派
将<user>和<hostname>替换为你在镜像工具中设置的值。
ssh <user>@<hostname> 'sudo mkdir -p /var/www/myblog && sudo chown <user>:<user> /var/www/myblog'
rsync -avz --delete public/ <user>@<hostname>:/var/www/myblog/
安装darkhttpd
ssh -t <user>@<hostname> 'sudo apt-get update -qq && sudo apt-get install -y -qq darkhttpd'
创建systemd服务
隧道将配置为指向http://localhost:8080,所以darkhttpd必须监听8080端口。
sudo tee /etc/systemd/system/myblog.service << 'EOF'
[Unit]
Description=My blog (darkhttpd)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/darkhttpd /var/www/myblog --port 8080
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
启用并启动
sudo systemctl daemon-reload
sudo systemctl enable --now myblog
sudo systemctl status myblog
预期输出:Active: active (running)
本地验证
curl -s http://localhost:8080/ | head -5
预期输出:博客HTML的前几行。博客现在在8080端口上提供服务,准备好让Cloudflare隧道转发流量到它。
设置Cloudflare隧道
注意:Orange在IPv4上阻止端口7844
cloudflared通过端口7844(QUIC)连接到Cloudflare的边缘。Orange在IPv4上阻止了此端口,但在IPv6上允许。我们用--edge-ip-version 6强制cloudflared使用IPv6——这就是为什么上面的IPv6持久化设置需要在此步骤之前完成。
在Cloudflare中创建隧道
- 前往Cloudflare Zero Trust https://one.dash.cloudflare.com → Networks → Tunnels
- 创建一个隧道(例如
solar) - 添加公共主机名:
solar.<your_domain>.com→http://localhost:8080 - 复制隧道令牌
在树莓派上安装cloudflared
curl -fSL -o /tmp/cloudflared https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm
sudo mv /tmp/cloudflared /usr/local/bin/cloudflared
sudo chmod +x /usr/local/bin/cloudflared
存储隧道令牌
sudo mkdir -p /etc/cloudflared
echo 'TUNNEL_TOKEN=<your-token>' | sudo tee /etc/cloudflared/env
sudo chmod 600 /etc/cloudflared/env
创建systemd服务
sudo tee /etc/systemd/system/cloudflared.service << 'EOF'
[Unit]
Description=Cloudflare Tunnel
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/bin/cloudflared tunnel --no-autoupdate --edge-ip-version 6 run --token ${TUNNEL_TOKEN}
EnvironmentFile=/etc/cloudflared/env
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
关键标志是--edge-ip-version 6:这强制cloudflared通过IPv6连接到Cloudflare,绕过Orange在IPv4上的端口7844阻止。
启用并启动
sudo systemctl daemon-reload
sudo systemctl enable --now cloudflared
sudo systemctl status cloudflared
预期输出:Active: active (running)
验证
journalctl -u cloudflared --no-pager -n 10
寻找包含Connection established或Registered tunnel connection的行——这确认隧道已启动。你还会在Cloudflare Zero Trust仪表板中看到隧道标记为Healthy。

然后从任何设备:curl https://solar.<your_domain>.com/
下一步——第2部分:完全离网
博客已经上线,通过4G提供服务,通过Cloudflare隧道传输。但它仍然插在墙上。
在第2部分中,我们将完全切断电源线:
- 太阳能板——连接10W USB-C面板为树莓派在白天供电
- 电池扩展板(Pi Sugar 3 Plus)——储存能量以度过夜晚和阴天
- GPS——使用SIM7600扩展板上的内置GPS模块为设备进行地理标记
- 省电技巧——禁用未使用的硬件(HDMI、LED、USB)以节省每一毫瓦