树莓派5搭家庭服务器从零到稳定运行
发布日期: 2026/08/20 阅读总量: 0

先说踩过的坑:第一块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 Mbps18%1.8x 实时速度
1080p H.264 视频~8 Mbps5%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卡+一块机械盘)换来的。有疑问欢迎在评论区交流。