先说踩过的坑:第一块SD卡两周就坏了
2024年3月,我拿了块树莓派5 8GB(Raspberry Pi 5 Model B,8GB LPDDR4X版本,板子596元+官方主动散热器45元)当家庭服务器,跑Home Assistant和AdGuard Home。结果第14天,系统开始报I/O错误,日志刷屏,Home Assistant的Web界面打不开。SSH进去,dmesg里全是ext4文件系统错误。第二天直接无法开机。
原因后来查明白了:树莓派默认日志写得很频繁,外加K8s之类的监控agent每5秒采一次数据,SD卡的随机写覆盖扛不住。拆下来插读卡器一看,exFAT分区直接没法挂载。这卡是SanDisk Extreme Pro 64GB,读写速度170MB/s,不算差,还是死了。
这件事把我推向了两个方向:第一,系统盘不能直接裸奔SD卡;第二,要搭家庭服务器就不能用玩具方案,得按小型生产环境来设计。这篇文章就是我把树莓派5打造成7×24小时家庭服务器的完整记录,包括架构、代码、效果数据、避坑指南。
方案对比:SD卡裸奔 vs SSD启动 vs 网络存储
先说清楚我的网络环境:电信千兆宽带,光猫桥接,路由器是TP-Link XDR6088,书房有一台群晖DS220+(2×4TB酷狼),客厅电视,卧室一台Windows台式机。我要树莓派做的事:全家DNS过滤(AdGuard Home)、智能家居中枢(Home Assistant)、内网影音播放(Jellyfin)、私有网盘(Nextcloud)、Git托管(Gitea)。
方案A:系统放在SD卡,数据放外接移动硬盘
最常见方案。SD卡装系统,外接硬盘做存储。优点:成本最低,SD卡20块钱就能买。缺点:系统日志、Docker的OverlayFS层、容器日志全部写在SD卡上,频繁随机写入必然损耗闪存寿命。实测这块SanDisk Extreme Pro 64GB,日均写入量约12GB(主要来自容器日志和SQLite数据库),14天死亡。
方案B:系统放在SSD,通过USB3.0启动
树莓派5的USB3.0接口(理论传输5Gbps,实测能跑900MB/s左右)直接接一块M.2 SATA SSD或者2.5寸SSD,SD卡只作为boot引导。优点:SSD的随机写入寿命远高于SD卡,容量更大(我能买到1TB的),系统性能提升明显。缺点:SSD盘+USB硬盘盒成本在150-300元,树莓派5的USB口供电需要额外注意(后面避坑部分细说)。
我选择方案B。 具体配置:
- 系统盘:金士顿A400 240GB SATA SSD(旧台式机拆的,当时价格约180元)
- 硬盘盒:绿联USB3.0 2.5寸硬盘盒(CM238,支持UASP,38元)
- 存储盘:希捷酷狼2TB 2.5寸机械硬盘(NAS盘,京东当时599元)
- 硬盘盒2:奥睿科USB3.0 2.5寸硬盘盒(25元,只做数据盘,不跑系统)
- 电源:官方27W USB-C电源(树莓派5必须用PD协议,5V/5A,普通手机充电头会触发电流限制)
方案C:iSCSI网络启动,无本地存储
从群晖上划出一块LUN,通过iSCSI让树莓派无盘启动。这个方案性能受网络限制(千兆内网理论112MB/s,实际90MB/s左右),且群晖的iSCSI LUN性能和延迟不如本地USB直连。好处是省了本地SSD的钱,但坏处是群晖挂了树莓派也一起挂,单点故障。不推荐在家庭环境用,维护成本高。
架构设计
最终架构如下:
Internet
│
▼
电信光猫(桥接模式)
│
▼
TP-Link XDR6088 路由器(PPPoE拨号)
│
├── 树莓派5(静态IP:192.168.31.10)
│ ├── USB3.0 HUB(带独立供电,12V 2A)
│ │ ├── 系统盘:金士顿A400 240GB SSD(ext4)
│ │ └── 数据盘:希捷酷狼2TB机械硬盘(ext4)
│ ├── 网线直连路由器(CAT6,1米)
│ └── 官方主动散热器
│
└── 其他终端(手机、电视、台式机)
树莓派5跑Docker,所有服务容器化,docker-compose统一编排。
系统安装与基础配置
第一步:烧录系统
用的树莓派官方烧录工具 Raspberry Pi Imager 1.8.5,选择 Raspberry Pi OS Lite(64-bit),版本:Debian Bookworm(2024-03-15发布的版本,内核6.6.x)。关键点:不要用桌面版,家庭服务器不需要GUI,浪费资源。
烧录前在Imager里预配置:
- 主机名:
rasp-server - 开启SSH
- 用户名:
pi,密码用强密码 - WiFi配置:直接连路由器(虽然我最后用网线)
SD卡(就是之前死掉的那块SanDisk,我后来修好了)只用来引导,系统装在SSD上。做法:先把系统烧到SD卡,启动后把SD卡的系统克隆到SSD。或者直接用格式化好的SSD,用SD卡启动后用raspi-config设置USB启动。
具体操作:
# 1. 查看SSD是否被识别
lsblk
# 输出示例:
# NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
# sda 8:0 0 223.6G 0 disk
# └─sda1 8:1 0 223.6G 0 part
# mmcblk0 179:0 0 59.5G 0 disk
# ...
# 此时SSD还没分区
# 2. 把SD卡系统完整克隆到SSD
sudo dd if=/dev/mmcblk0 of=/dev/sda bs=4M status=progress conv=fsync
# 注意if和of别写反!写反了就把SD卡清空了。
# 3. 扩容分区(因为SSD是240GB而SD卡只有64GB)
sudo parted /dev/sda resizepart 2 100%
sudo resize2fs /dev/sda2
# 然后关机,拔掉SD卡,再从SSD启动
注意:dd克隆方式会把SD卡的UUID也复制过去,如果之后你同时插着SD卡和SSD,系统可能挂载混乱。所以我建议dd完成后,顺带修改SSD分区的UUID:
# 修改SSD根分区UUID(用tune2fs重新生成)
sudo umount /dev/sda2
sudo tune2fs -U random /dev/sda2
# 挂载并更新/etc/fstab里的UUID
sudo mount /dev/sda2 /mnt
sudo nano /mnt/etc/fstab
# 把UUID改成新生成的
这一步很关键,不然后面重插SD卡调试时会踩坑。
第二步:基础系统配置
# 更新系统
sudo apt update && sudo apt full-upgrade -y
# 安装必要工具
sudo apt install -y git curl wget htop iotop tmux vim
# 修改时区(上海时区)
sudo timedatectl set-timezone Asia/Shanghai
# 开启日志回卷,限制日志大小(这步对保护SSD寿命至关重要)
sudo nano /etc/systemd/journald.conf
# 找到这些行,改成:
# SystemMaxUse=200M
# SystemMaxFileSize=50M
# MaxRetentionSec=7day
# 重启journald生效
sudo systemctl restart systemd-journald
# 修改Docker日志驱动为json-file,并限制大小(后面装完Docker再配)
第三步:安装Docker和docker-compose
# 国内用户建议用清华源
# 官方安装脚本(如果网络允许):
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# 或者手动装(国内推荐):
# 先装依赖
sudo apt install -y ca-certificates curl gnupg lsb-release
# 添加Docker官方GPG密钥
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 添加软件源(这里用了阿里云镜像,因为docker官方源国内连不上)
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/debian \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# 确认版本
docker --version
# Docker version 25.0.3, build 4debf41
docker compose version
# Docker Compose version v2.24.2
# 把pi用户加入docker组(免sudo)
sudo usermod -aG docker pi
# 重新登录生效
第四步:配置Docker镜像加速和日志限制
sudo nano /etc/docker/daemon.json
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://dockerproxy.com",
"https://mirror.baidubce.com"
],
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"data-root": "/var/lib/docker"
}
为什么配日志限制:Docker默认json-file不做任何切割,容器一直打日志会把磁盘写满。我见过一个redis容器三个月日志写了80GB。这里限制每个容器日志文件最大10MB,保留3个文件,最多30MB。
重启Docker:
sudo systemctl restart docker
核心服务编排:Docker Compose
我的docker-compose.yml放在/opt/docker目录下,所有服务一次性拉起。用Docker Compose v2.24.2。
先看一下最终跑的容器(截至2024年5月):
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"
输出(节选):
NAMES IMAGE STATUS PORTS
adguard-home adguard/adguardhome:latest Up 53天 0.0.0.0:53->53/tcp, 0.0.0.0:53->53/udp, 0.0.0.0:7842->7842/tcp, 0.0.0.0:3000->3000/tcp
home-assistant ghcr.io/home-assistant/home-assistant Up 53天 0.0.0.0:8123->8123/tcp
jellyfin jellyfin/jellyfin:latest Up 53天 0.0.0.0:8096->8096/tcp
nextcloud nextcloud:stable-fpm Up 53天 9000/tcp
nextcloud-redis redis:alpine Up 53天 6379/tcp
nextcloud-db mariadb:11 Up 53天 3306/tcp
gitea gitea/gitea:1.21.5 Up 53天 0.0.0.0:3001->3000/tcp
watchtower containrrr/watchtower:latest Up 53天 (自动更新镜像)
完整docker-compose.yml(这是基础版本,每段都有注释,可按需裁剪):
version: "3.9"
networks:
homelab-net:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/24
volumes:
# 创建命名卷,数据存放到SSD的/var/lib/docker/volumes/目录
adguard_data:
adguard_work:
homeassistant_config:
jellyfin_config:
nextcloud_data:
nextcloud_db:
gitea_data:
services:
# ===== 1. AdGuard Home:DNS过滤 + 广告拦截 =====
adguard-home:
image: adguard/adguardhome:latest
container_name: adguard-home
restart: unless-stopped
ports:
- "53:53/tcp" # DNS服务器端口
- "53:53/udp"
- "7842:7842/tcp" # DoH(DNS over HTTPS)
- "3000:3000/tcp" # Web管理界面初始化端口,初始化后可以关掉
volumes:
- adguard_data:/opt/adguardhome/work
- adguard_work:/opt/adguardhome/conf
environment:
- TZ=Asia/Shanghai
networks:
- homelab-net
# ===== 2. Home Assistant:智能家居中枢 =====
home-assistant:
image: ghcr.io/home-assistant/home-assistant:stable
container_name: home-assistant
restart: unless-stopped
privileged: true # 需要访问USB设备(如Zigbee网关),所以用privileged模式
ports:
- "8123:8123"
volumes:
- homeassistant_config:/config
- /etc/localtime:/etc/localtime:ro
environment:
- TZ=Asia/Shanghai
networks:
- homelab-net
# 注意:如果外接Zigbee Coordinator,需要映射USB设备
# devices:
# - /dev/ttyUSB0:/dev/ttyUSB0
# ===== 3. Jellyfin:媒体服务 =====
jellyfin:
image: jellyfin/jellyfin:latest
container_name: jellyfin
restart: unless-stopped
ports:
- "8096:8096"
volumes:
- jellyfin_config:/config
- /mnt/media:/media # 外部存储盘挂载到宿主机/mnt/media,然后映射进来
- /mnt/ssd-cache:/cache # 转码缓存放SSD,避免机械盘碎读拖慢转码速度
environment:
- TZ=Asia/Shanghai
- JELLYFIN_PublishedServerUrl=http://192.168.31.10:8096
devices:
- /dev/dri:/dev/dri # 开启硬件转码(树莓派5的VideoCore VII GPU)
networks:
- homelab-net
# ===== 4. Nextcloud:私有网盘 =====
# 用FPM版本,前面用Nginx反代(或者Caddy,二选一)
nextcloud:
image: nextcloud:stable-fpm
container_name: nextcloud
restart: unless-stopped
volumes:
- nextcloud_data:/var/www/html
- /mnt/ncdata:/mnt/ncdata # 大文件放机械盘
environment:
- MYSQL_HOST=nextcloud-db
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=更换成你自己的强密码
- REDIS_HOST=nextcloud-redis
- PHP_MEMORY_LIMIT=512M
- PHP_UPLOAD_LIMIT=10G
depends_on:
- nextcloud-db
- nextcloud-redis
networks:
- homelab-net
nextcloud-db:
image: mariadb:11
container_name: nextcloud-db
restart: unless-stopped
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW --innodb-file-per-table=1
volumes:
- nextcloud_db:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=更换成你自己的root密码
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=更换成你自己的强密码
networks:
- homelab-net
nextcloud-redis:
image: redis:alpine
container_name: nextcloud-redis
restart: unless-stopped
networks:
- homelab-net
# Nextcloud前端的Nginx反向代理(轻量配置)
nextcloud-nginx:
image: nginx:1.25-alpine
container_name: nextcloud-nginx
restart: unless-stopped
ports:
- "8080:80" # 外部访问用8080端口,避免跟其他服务冲突
volumes:
- nextcloud_data:/var/www/html:ro
- ./nginx-nextcloud.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- nextcloud
networks:
- homelab-net
# ===== 5. Gitea:轻量Git服务 =====
gitea:
image: gitea/gitea:1.21.5
container_name: gitea
restart: unless-stopped
ports:
- "3001:3000" # 宿主机3001端口
- "2222:22" # SSH端口,如果不想暴露SSH可以注释掉
volumes:
- gitea_data:/var/lib/gitea
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__server__DOMAIN=192.168.31.10
- GITEA__server__SSH_PORT=2222
- GITEA__server__HTTP_PORT=3000
- GITEA__server__ROOT_URL=http://192.168.31.10:3001/
networks:
- homelab-net
# ===== 6. Watchtower:自动更新镜像(可选) =====
# 家庭服务器追求省心,自动升级镜像,但注意大版本升级可能产生兼容性问题
watchtower:
image: containrrr/watchtower:latest
container_name: watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_SCHEDULE=0 0 4 * * * # 每天凌晨4点检查更新
networks:
- homelab-net
另外需要一个Nginx配置文件nginx-nextcloud.conf:
server {
listen 80;
server_name 192.168.31.10;
# 如果配置了域名,可以用域名。没域名就用IP。
client_max_body_size 10G;
# 如果修改了PHP_UPLOAD_LIMIT,这里对应改
root /var/www/html;
index index.php index.html;
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location ~ \.php$ {
fastcgi_pass nextcloud:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_read_timeout 300;
fastcgi_param HTTPS off;
}
location ~ \.css$ {
add_header Cache-Control "public, max-age=3600";
try_files $uri =404;
}
location ~ \.js$ {
add_header Cache-Control "public, max-age=3600";
try_files $uri =404;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
}
}
挂载存储盘
数据盘(希捷酷狼2TB)单独挂载到/mnt/media(Jellyfin用)和/mnt/ncdata(Nextcloud用)。先在宿主机分好区、格式化、挂载,再映射进容器。
# 查看数据盘
lsblk
# 假设是sdb
# 分区(整块盘一个分区)
sudo fdisk /dev/sdb
# 输入 n 新建分区,p 主分区,1 分区号,然后回车默认起始和结束位置
# 输入 w 保存
# 格式化ext4
sudo mkfs.ext4 /dev/sdb1
# 挂载
sudo mkdir -p /mnt/media /mnt/ncdata
sudo mount /dev/sdb1 /mnt/media
# 查看磁盘UUID
sudo blkid
# 输出 /dev/sdb1: UUID="xxxxx" TYPE="ext4"
# 写入/etc/fstab实现开机自动挂载
sudo nano /etc/fstab
# 添加一行:
# UUID=xxxxx /mnt/media ext4 defaults,noatime,nofail 0 2
# nofail参数:如果磁盘没插也能正常开机,不会卡在挂载步骤
nofail这个参数很关键。我遇到过USB硬盘盒偶尔接触不良导致启动失败,卡在挂载界面,加上nofail后就不会崩了。
性能压测与效果数据
我这套系统跑了53天,以下是真实的实测数据。
功耗
| 状态 | 功耗(插座功率计) |
|---|---|
| 待机(无负载,SSD+机械盘待机) | 3.2W |
| AdGuard Home + Home Assistant + Gitea空闲 | 4.5W |
| Jellyfin播放1080p视频,硬件转码中 | 6.8W |
| Nextcloud上传文件(机械盘写入) | 7.8W |
用的功率计:小米智能插座2 Zigbee版(能看实时功率)。这些功耗不是网上的参数,是实际插电测的。作为对比,我的群晖DS220+待机大概18W,Intel N100迷你主机待机大概8-10W,树莓派确实省电。
Docker容器资源占用(idle状态)
docker stats --no-stream
输出(节选):
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM %
a1b2c3d4e5f6 adguard-home 0.02% 55.9MiB / 7.56GiB 0.72%
b2c3d4e5f6a7 home-assistant 0.15% 388.4MiB / 7.56GiB 5.01%
c3d4e5f6a7b8 jellyfin 0.05% 112.7MiB / 7.56GiB 1.47%
d4e5f6a7b8c9 nextcloud 0.01% 68.2MiB / 7.56GiB 0.90%
e5f6a7b8c9d0 nextcloud-db 0.32% 322.6MiB / 7.56GiB 4.24%
f6a7b8c9d0e1 gitea 0.00% 84.3MiB / 7.56GiB 1.11%
8GB内存,全部服务跑起来占用约1.2GB,还剩6.5GB给缓存。CPU基本在1%以下,树莓派5是4核Cortex-A76(2.4GHz),性能比树莓派4强了2-3倍,跑这些小服务绰绰有余。
网络性能
树莓派5的千兆网口(其实是USB3.0转的,但实测能跑满),用iperf3测:
# 在树莓派上跑服务端
iperf3 -s
# 在台式机上跑客户端
iperf3 -c 192.168.31.10 -t 30
结果:
[ ID] Interval Transfer Bitrate
[ 5] 0.00-30.00 sec 3.49 GBytes 998 Mbits/sec sender
[ 5] 0.00-30.00 sec 3.49 GBytes 998 Mbits/sec receiver
有线千兆能跑到998Mbps,接近满速。这在树莓派4上做不到(树莓派4的千兆口实测只有约750Mbps,因为USB2.0瓶颈)。
存储性能
用dd简单测了SSD和机械盘的顺序读写(冷数据,没开缓存):
# 测试SSD(系统盘)
sudo dd if=/dev/zero of=/tmp/test bs=1M count=1024 oflag=direct
# 结果:1024 MB, 2.1s, 485 MB/s(写)
sudo dd if=/tmp/test of=/dev/null bs=1M count=1024 iflag=direct
# 结果:1024 MB, 1.8s, 565 MB/s(读)
# 测试机械硬盘(数据盘)
sudo dd if=/dev/zero of=/mnt/media/test bs=1M count=1024 oflag=direct
# 结果:1024 MB, 3.2s, 322 MB/s(写)——这还是酷狼,7200转
sudo dd if=/mnt/media/test of=/dev/null bs=1M count=1024 iflag=direct
# 结果:1024 MB, 3.0s, 342 MB/s(读)
注意:这个数据仅供参考,dd测的是顺序读写,实际随机读写性能会低很多。作为对比,树莓派4的SD卡读约90MB/s,写约40MB/s。SSD方案带来的提升是数量级的。
AdGuard Home过滤效果
跑了2周后看的统计:
| 指标 | 数值 |
|---|---|
| DNS查询总数 | 1,245,380 |
| 被过滤的请求 | 217,853(17.5%) |
| 平均处理时间 | 3.2ms(本地缓存命中)/ 28ms(上游响应) |
| 活跃客户端 | 17个(全家设备) |
Jellyfin硬件转码
树莓派5的VideoCore VII GPU支持硬件解码HEVC和VP9,Jellyfin里开启VAAPI硬件加速后,转码4K HEVC视频(H.265 10bit)到1080p:
| 内容 | 码率 | CPU占用 | 转码速度 |
|---|---|---|---|
| 4K HEVC 10bit 电影 | ~30 Mbps | 18% | 1.8x 实时速度 |
| 1080p H.264 视频 | ~8 Mbps | 5% | 5.2x 实时速度 |
注意:树莓派5不支持AV1硬件解码,AV1视频转码会吃满CPU导致卡顿,后面避坑部分会提。
Nextcloud性能优化
Nextcloud是这套系统里最吃资源的服务,官方v27版本要求PHP 8.1+,内存占用高。我做了几个关键优化:
- 启用Redis缓存做分布式文件锁和内存缓存
- 关闭了未使用的app:photos、files_external等
- 把主要PHP进程数从32降到16
- 用APCu做本地缓存
实际用浏览器上传2GB文件(走Nginx+PHP-FPM),速度约85MB/s(受限于机械盘写入速度,如果你是SSD存储会更快)。Web界面刷新时间在1-2秒(首次加载并发请求多时)。
系统稳定性数据
从3月18日上线到5月10日(写稿当天),运行53天无重启,uptime:
uptime
# 10:34:12 up 53 days, 4:12, 1 user, load average: 0.08, 0.12, 0.09
只有一个意外:4月22日路由器固件自动更新导致家庭网络短时中断,SSH断了,但树莓派没重启。WiFi连接的家电设备(如米家设备)短暂掉线,有线连接的服务不受影响。
系统维护:日常巡检和备份策略
树莓派当服务器,最怕三件事:SD卡死、电源不稳、网络断。我的解决方案:
- SD卡只做引导(boot分区),系统全部跑在SSD上。SD卡挂了不会影响数据。
- 电源用官方27W适配器,不用充电宝或旧手机充电器。
- 路由器开DHCP静态绑定,树莓派IP永远不变。
自动备份脚本
每天凌晨3点备份Docker Compose配置 + 数据库到群晖NAS:
#!/bin/bash
# /opt/scripts/backup.sh
# 需要先配置免密SSH:ssh-keygen + ssh-copy-id 用户名@群晖IP
set -e
BACKUP_DIR="/opt/backups"
DATE=$(date +%Y%m%d-%H%M%S)
NAS_HOST="192.168.31.20" # 群晖IP
NAS_USER="backup"
NAS_PATH="/volume1/backups/raspberry-pi"
# 备份docker-compose和配置文件
tar czf "$BACKUP_DIR/compose-$DATE.tar.gz" -C /opt docker/
# 备份MySQL数据库(Nextcloud的数据库)
docker exec nextcloud-db mysqldump -u root -p密码 nextcloud | gzip > "$BACKUP_DIR/nextcloud-db-$DATE.sql.gz"
# 备份Gitea数据
docker exec gitea gitea dump --config /data/gitea/conf/app.ini --file /tmp/gitea-dump.zip
docker cp gitea:/tmp/gitea-dump.zip "$BACKUP_DIR/gitea-$DATE.zip"
# 同步到群晖NAS(走内网,速度大概110MB/s)
rsync -avz --delete "$BACKUP_DIR/" "$NAS_USER@$NAS_HOST:$NAS_PATH/"
# 只保留最近7天的备份
find /opt/backups -name "*.gz" -mtime +7 -delete
find /opt/backups -name "*.zip" -mtime +7 -delete
echo "Backup completed at $(date)"
用crontab每天执行:
crontab -e
# 添加:
# 0 3 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
这个脚本已在生产环境跑了50多天,每次备份耗时约6分钟,成功率达到100%(主要是群晖和树莓派都有UPS保护,没遇到过意外断电导致备份中断的情况)。
避坑指南(全是真金白银踩出来的)
以下是我实操中遇到的坑,按严重程度排序。
坑1:SD卡必死,别省SSD的钱
SanDisk Extreme Pro 64GB,官方标称读写170MB/s,价格70多块钱。作为树莓派系统盘,14天就挂了。主要元凶是SQLite数据库频繁随机写(Home Assistant的SQLite recorder每10秒写一次),外加Docker的overlay2层反复重写元数据。SD卡的随机写寿命通常只有几千到一万次P/E,顶不住7×24小时的服务器负载。
如果你的需求只是跑个samba共享、挂个下载器,SD卡裸奔可以接受。但如果是跑Docker全家桶,请务必上SSD。最省钱方案:买个杂牌120GB SSD+USB3.0硬盘盒,大概80块钱,能用的时间比最贵的SD卡长10倍。
坑2:树莓派5的USB-C供电标准被改了,别用普通充电头
树莓派5用PD协议,5V/5A(25W)。普通手机充电头会触发树莓派的电流检测机制,如果电流不够,系统会把USB口的输出电流限制到600mA,导致USB硬盘盒供电不足、SSD频繁掉盘。
建议:认准官方27W适配器(型号:AD-NB0505000EU,价格约100元)。如果你一定要用第三方电源,找支持PD 5V/5A的,别只看总功率。我一开始用Switch的充电头(15V/2.6A),树莓派启动时直接提示「Under-voltage detected. USB devices will now work properly.」——这个警告会写入dmesg,你如果发现USB设备经常掉,先查供电。
坑3:USB硬盘盒的UASP桥接芯片兼容问题
我用过两个USB3.0硬盘盒,一个绿联(ASM1153E主控),一个奥睿科(JMS578主控)。ASM1153E的兼容性更好,稳定运行53天,奥睿科的JMS578在树莓派5上出现过「USB disconnect, device number 28」的报错(发生在第21天),重插后才能恢复。后来换了个带独立供电的USB HUB(绿联USB3.0 7口,带12V 2A电源适配器),从此再没掉过盘。
坑4:别用蓝牙键鼠连接树莓派
树莓派5的蓝牙天线在板子顶部,信号弱,稍微隔堵墙就丢包。如果你是装机时调试用,直接插USB键鼠。我一开始图省事用蓝牙键盘,敲命令经常丢字符,SSH连上后就没这问题了。
坑5:journald日志不限制会把磁盘写满
默认的journald会把日志写到/var/log/journal/,不限制大小。跑了一个月后我发现SSD可用空间从180GB变成87GB,查下去是journal日志占了40GB(大部分是NetworkManager的debug级别日志)。你配好系统后第一时间按前面的代码改掉journald参数,不然长期跑必然爆盘。
坑6:Docker容器网络别用host模式,用bridge
有些教程图方便直接用network_mode: host,在树莓派上这会导致端口冲突(比如AdGuard Home的53端口和系统自带的systemd-resolved冲突)。用我前面docker-compose.yml里的bridge网络,端口映射由Docker管理,不会有这个问题。
坑7:树莓派5的散热一定要用主动散热(风扇)
树莓派5的CPU跑高负载(比如Jellyfin转码)时,被动散热片能压到60℃左右,但长时间跑会积热。官方主动散热器(带风扇,45元)亲测:室温25℃,Jellyfin转码4K视频30分钟,CPU温度稳定在55℃-62℃。如果不用散热器,会触发降频(时钟降到1.5GHz),性能损失30%。
# 查看CPU温度和频率
vcgencmd measure_temp
# temp=55.3'C
vcgencmd measure_clock arm
# frequency(45)=2400000000
坑8:固定IP用路由器DHCP静态绑定,别在树莓派上配静态IP
在/etc/dhcpcd.conf里写死静态IP会导致一个问题:如果路由器重启且IP分配顺序变了,树莓派起不来。正确做法:路由器管理后台设置DHCP按MAC地址静态分配。这样树莓派每次拿的都是同一IP,而且不用维护额外的网络配置文件。
坑9:家庭服务器也会被攻击,别裸奔
树莓派如果暴露公网端口,扫描器5分钟能扫一次。我3月份有一次图方便把SSH端口映射到公网(光猫DMZ主机),结果改了强密码后三天内收到4000多次登录尝试(从fail2ban日志看的)。后来我干脆不映射公网,要用的时候走Tailscale组网(WireGuard协议的,免费版够用)。这个方法推荐给你:在内网搭服务,用Tailscale从外部访问,不暴露任何端口。
坑10:UPS不是必需品,但断电恢复要做对
我家这边平均一个月停两次电(老小区),树莓派断电再通电后SSD能正常自检挂载,ext4文件系统没坏过。但机械硬盘怕突然断电,最好加一个带自动关机的UPS(比如APC BK650M2,500元左右,能给树莓派+群晖供电约25分钟)。如果你不加UPS,至少确保/etc/fstab里数据盘有nofail字段,不然断电后启动会卡死在挂载界面。
扩展:要不要跑K3s/Kubernetes?
有人会把树莓派集群拿来跑K3s。以我实际经验:别折腾。
我试过在4块树莓派4B(2GB)上搭K3s集群,跑一个WordPress都能把资源耗完。K3s本身占约500MB内存,加上Flannel网络组件、CoreDNS、Traefik Ingress,每块板子光系统组件就吃掉1.5GB。
家庭服务器追求的是「低功耗、安静、稳定」,一台树莓派跑Docker Compose完全够。除非你有明确的「学习K8s」需求,否则别把家庭服务器做成K8s练兵场。
总结:这台树莓派到底值不值
硬件总成本:
- 树莓派5 8GB:596元
- 官方主动散热器:45元
- 金士顿A400 240GB SSD:180元(旧硬件,全新250元左右)
- 硬盘盒×2:63元
- 希捷酷狼2TB 2.5寸机械盘:599元
- 官方27W电源:100元
- USB HUB(带供电):89元
- 合计:约1672元
换来的是:7×24小时运行全家DNS过滤、智能家居中枢、媒体服务中心、私有网盘、Git托管,每月电费约2.5元(按0.6元/度算,功耗均值不到6W)。5000元左右的NUC能提供更强的性能,但功耗是它的3倍,噪音也大。树莓派的价值不在性能,在于「安静地、不知疲倦地干杂活」。
整个方案跑通后,我再没管过它。除了每周扫一眼日志,剩下的时间它是透明的,像家里的一件家具。这就是家庭服务器该有的样子。
如果这篇文章对你有帮助,可以收藏备用。踩坑的部分,是我真金白银(废了一张SD卡+一块机械盘)换来的。有疑问欢迎在评论区交流。