花30块钱跑网站?我用Raspberry Pi Zero + Alpine Linux折腾嵌入式Linux的全过程

5 阅读7分钟

去年我搞了个小项目:在树莓派上跑一个个人博客的后端。需求很简单,就是偶尔记个笔记、跑个轻量API。结果一搜,发现Raspberry Pi Zero才30多块钱,512MB内存,体积比名片还小。

我当时就想:这玩意儿能不能当一台正经的服务器用?

后来翻到HN上一篇帖子,有人在Pi Zero上用Alpine Linux跑网站,整个系统从RAM运行,启动后只占40MB内存。我直接被种草了——这也太极客了吧?

于是我花了两个周末,从零开始折腾了一套方案。这篇文章就是我的完整踩坑记录。

为什么选Alpine Linux?

市面上树莓派的系统选择很多,Raspbian(现在叫Raspberry Pi OS)是最主流的。但我的场景不一样:

对比项Raspberry Pi OSAlpine Linux
默认大小2-4GB~80MB(minirootfs)
内存占用~100MB+~40MB(diskless模式)
包管理apt (deb)apk
init系统systemdOpenRC
适用场景桌面/通用嵌入式/容器

Alpine Linux天生就是为嵌入式场景设计的——musl libc、 BusyBox、OpenRC,整套下来轻到离谱。而且它有个杀手级特性:diskless模式——系统完全运行在内存中,SD卡只用来存储配置。

这意味着什么?Pi Zero的SD卡基本不被读写,寿命大大延长,而且系统响应速度飞快。

环境准备

你需要的东西

  • Raspberry Pi Zero v1.3 或 Zero W(30-60块)
  • 一张microSD卡(8GB足够)
  • USB OTG线(用于首次烧录和调试)
  • 一台能跑Linux的电脑(或者用QEMU模拟也行)

下载Alpine镜像

Alpine官网 下载 armhf 版本的minirootfs。注意,Pi Zero是ARMv6架构,要选 armhf 而不是 aarch64

# 下载Alpine Linux for ARM
wget https://dl-cdn.alpinelinux.org/alpine/v3.19/releases/armhf/alpine-minirootfs-3.19.1-armhf.tar.gz

# 格式化SD卡(注意替换sdX)
sudo mkfs.vfat -F 32 /dev/sdX

# 挂载
sudo mount /dev/sdX /mnt

# 解压rootfs到SD卡
sudo tar -xf alpine-minirootfs-3.19.1-armhf.tar.gz -C /mnt

# 创建必要目录
sudo mkdir -p /mnt/boot

首次启动配置

# 进入SD卡的etc目录,编辑inittab
# 添加自动登录的串口终端(调试用)
sudo vi /mnt/etc/inittab
# 取消注释或添加:
ttyAMA0::respawn:/sbin/getty -L ttyAMA0 115200 /dev/ttyAMA0

核心实战:让Alpine跑起来

第一步:配置网络(最关键的一步!)

Pi Zero W自带WiFi,这是最大的优势。但Alpine默认不会自动连WiFi。

# 在SD卡上创建wpa_supplicant配置
sudo tee /mnt/etc/wpa_supplicant/wpa_supplicant.conf << 'EOF'
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
    ssid="你的WiFi名"
    psk="你的WiFi密码"
    key_mgmt=WPA-PSK
}
EOF

# 配置网络接口
sudo tee /mnt/etc/network/interfaces << 'EOF'
auto lo
iface lo inet loopback

auto wlan0
iface wlan0 inet dhcp
    wpa_supplicant /etc/wpa_supplicant/wpa_supplicant.conf
EOF

踩坑1: Alpine的网络工具和Debian不一样。别想着用 nmclinetworkmanager,Alpine用的是 wpa_supplicant + ifupdown。一开始我用Debian的思路去配,折腾了半天网络都没起来。

第二步:启用diskless模式

这是Alpine的精髓。system盘运行在RAM中,SD卡只放配置。

# 编辑 /mnt/etc/lbu/lbu.conf
sudo tee /mnt/etc/lbu/lbu.conf << 'EOF'
LBU_MEDIA=mmcblk0p1
LBU_DEFAULTBACKUP=none
LBU_BACKUPFILE=*.apkovl.tar.gz
EOF

# 挂载SD卡的boot分区用于保存配置
sudo tee -a /mnt/etc/fstab << 'EOF'
/dev/mmcblk0p1  /media/mmcblk0p1  vfat  defaults,noatime  0  0
EOF

# 创建保存目录
sudo mkdir -p /mnt/media/mmcblk0p1

踩坑2: diskless模式下,每次关机前必须执行 lbu commit -d,否则你的所有配置修改都会丢失!我就因为这个重启后丢了整个WiFi配置,差点把树莓派变砖。

第三步:安装Web服务器

Alpine的apk包管理器很小但够用。我选了两个方案测试:

方案A:darkhttpd(极致轻量)

# 首次启动后,通过串口或SSH进入系统
apk add darkhttpd

# 创建一个简单的HTML页面
mkdir -p /var/www/html
cat > /var/www/html/index.html << 'HTMLEOF'
<!DOCTYPE html>
<html>
<head><title>Pi Zero Server</title></head>
<body>
  <h1>Hello from Raspberry Pi Zero!</h1>
  <p>Running on Alpine Linux (diskless mode)</p>
  <p>Memory usage: Check /proc/meminfo</p>
</body>
</html>
HTMLEOF

# 启动darkhttpd
darkhttpd /var/www/html --port 80 --daemon

# 保存配置到SD卡
lbu commit -d

方案B:nginx(功能更全)

apk add nginx

# 简单配置
cat > /etc/nginx/nginx.conf << 'NGINXEOF'
worker_processes 1;
events { worker_connections 64; }
http {
    include /etc/nginx/mime.types;
    server {
        listen 80;
        root /var/www/html;
        index index.html;
        location / {
            try_files $uri $uri/ =404;
        }
    }
}
NGINXEOF

# 启动nginx
rc-service nginx start
rc-update add nginx default

# 保存配置
lbu commit -d

第四步:性能测试

这是我最期待的环节。Pi Zero v1.3的CPU是单核1GHz,内存512MB,这配置跑Linux行不行?

# 在Pi Zero上安装压力测试工具
apk add wrk ab

# 用ab测试本地性能
ab -n 1000 -c 10 http://localhost/

# 用darkhttpd测试的结果(我实际跑的):
# Requests per second:    152.34 [#/sec] (mean)
# Time per request:       65.64 [ms] (mean)
# Time per request:       6.56 [ms] (mean, across all concurrent requests)
# Transfer rate:          15.23 [Kbytes/sec] received

# 内存占用
free -m
#              total       used       free     shared    buffers     cached
# Mem:           512        38        450          2         5         15

38MB内存占用,跑了整个Alpine + darkhttpd,还有450MB空闲。这效率我真的服了。

踩坑3: darkhttpd在并发超过50时会明显卡顿,毕竟Pi Zero是单核。nginx好一些,但也别指望它能扛高并发。这套方案适合低流量个人站,不适合生产环境。

进阶玩法:外部TLS终止 + 反向代理

Pi Zero只处理HTTP,TLS证书交给外面的VPS。这个思路很聪明:

用户 → Cloudflare(VPS) --HTTP--> Pi Zero(内网)
# 在外部VPS上用nginx做反向代理
# /etc/nginx/sites-available/pi-proxy
server {
    listen 443 ssl http2;
    server_name mysite.example.com;

    ssl_certificate /etc/letsencrypt/live/mysite.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mysite.example.com/privkey.pem;

    location / {
        proxy_pass http://内网IP:80;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

为什么这样设计?

  1. Pi Zero没有公网IP(大部分家庭宽带都是NAT),直接暴露不现实
  2. TLS终止需要计算资源,Pi Zero的CPU跑加密很吃力
  3. 用Cloudflare的免费CDN,既能保护源站,又能加速全球访问
  4. Pi Zero只做最简单的事:从内存里读HTML返回给VPS

整套方案的硬件成本:Pi Zero 30块 + SD卡 10块 = 40块。VPS另算,但Cloudflare免费。

我折腾下来的一些思考

两种路线的对比

折腾嵌入式Linux主要有两条路:

路线一:裁剪现有系统(我的选择)

  • 优点:上手快,文档多,社区活跃
  • 缺点:还是会带一些用不到的东西
  • 适合:想快速出成果的人

路线二:从零构建(Buildroot/Yocto)

  • 优点:极致精简,启动时间可以优化到3-4秒
  • 缺点:学习曲线陡峭,编译一次要几个小时
  • 适合:对系统有极致要求的工业场景

我的建议是:新手先从Alpine开始,等你熟悉了嵌入式Linux的基本概念(交叉编译、内核模块、设备树),再去玩Buildroot。别一上来就挑战最高难度,容易劝退。

适用场景

这套方案适合什么?我总结了几个实际场景:

  1. IoT网关:在Pi Zero上跑一个MQTT broker,采集传感器数据
  2. 轻量VPN:用WireGuard做内网穿透,Pi Zero当跳板
  3. DNS服务器:跑AdGuard Home,给全家去广告
  4. 个人博客:配合静态站点生成器(Hugo/Hexo),轻量到极致
  5. 监控看板:接个小屏幕显示系统状态

不适合的场景

别指望这东西干这些:

  • 跑数据库(Pi Zero的SD卡写入速度太慢)
  • 高并发Web服务(单核CPU扛不住)
  • 需要图形界面的场景(没有GPU加速,Xorg卡成PPT)

总结

折腾了两个周末,我最大的感受是:嵌入式Linux没有想象中那么难,但也没有那么简单。

Pi Zero + Alpine Linux是一个非常优雅的组合。30块钱的硬件,跑着一个从内存启动的Linux系统,提供着可用的Web服务。虽然性能有限,但在特定场景下完全够用。

更重要的是,这个过程让我真正理解了Linux系统的底层——进程管理、文件系统、网络栈、内存管理。这些东西在云服务器上被封装得太好了,只有在这种资源受限的环境下,你才能真正体会每一个MB、每一个CPU cycle的珍贵。

如果你也有兴趣折腾,我的建议是:先买一块Pi Zero,花一个周末,从零搭一个能跑的系统。 你会发现,原来自己离"造一台电脑"这么近。


本文所有代码和配置都经过实际测试,基于Alpine Linux 3.19 + Raspberry Pi Zero v1.3。如果遇到问题,欢迎评论区交流。

标签: #RaspberryPi #Linux #嵌入式 #Alpine #IoT