前言
自打小神兽落地以后,个人数据存储需求是越发的强烈,故打算整合一下现有资源,打造一个家庭服务器,以下是我的几个痛点:
找图片麻烦:日积月累的数据太多,需要查找的时候非常麻烦,手机存储的照片视频成千上万,找一张照片如同大海捞针
存储焦虑:无论换再多手机,容量始终是有上限的,即便是换了更大容量的手机,数据始终是要迁移的,现在一台手机容量上限也就1T
数据安全:各个网盘厂家都是冲着马内去的,且数据在他们手上,被拿过去了,谁知道会用于什么途径,去做什么事情
性能下降:手机存储<25%卡顿会非常严重
PC功耗太高:设想过使用x86架构的设备搭建NAS服务,但考虑到作为家庭服务器需要常年开机,再一寻思功耗及散热问题的便放弃了,但是不得不说x86架构的设备生态是很友好的,黑群晖、飞牛os等,在我了解这些产品的时候,飞牛已经有了超越黑群晖的趋势
总的来说,我对家庭服务器的需求如下:
低功耗
大容量,支持扩容
支持AI搜索
支持硬编解码
多线程,大内存(需要部署多个服务)
硬件选择:
SOC:这里选择的是ARM架构的RK3588,8核心(1.8Ghz-2.4Ghz)、6TOPS算力、8K硬编解码
内存(RAM):32G
eMMC(板载ROM):256G
外置存储(外置ROM):拼夕夕14T硬盘
散热:板载被动散热
软件选择:
immich:自动备份照片和视频到自建服务器。支持多客户端上传,提供便捷的Web界面管理媒体文件。
nginx:高性能HTTP服务器与反向代理,擅长处理高并发请求,低资源消耗,并支持SSL/TLS加密。
ddns-go:简单易用的动态域名解析工具,自动更新域名指向最新的公网IP地址,无需复杂配置。
portainer:轻量级Docker管理UI,轻松管理容器、镜像和网络,支持Swarm集群管理,提升运维效率。
certd:自动化获取和更新SSL/TLS证书,确保网站和服务的安全通信,简化HTTPS部署流程。
halo:现代化的个人出版平台,专为博客设计,支持Markdown写作,拥有丰富的主题和插件,易于搭建个人网站。
相比起x86架构生态的完善方便快捷,这里选择的路线更为折腾和定制化,下面开始搞起。



系统安装
镜像选择
香橙派官方镜像:Orange Pi - Orangepi
更高RKNPU版本的镜像:Release Armbian 24.11 with NPU driver 0.9.8 · Pelochus/armbian-build-rknpu-updates
如果没有特殊的需求,就选择官方的镜像下载就好了。
比如说immich如果想要开启硬件加速机器学习,就需要rknpu打到v0.9.8的版本及以上Hardware-Accelerated Machine Learning | Immich,但是香橙派最新的官方镜像支持到的rknpu的版本只到0.9.6,而上面提供的镜像,RKNPU driver的版本为:v0.9.8,虽然只差了两个小版本,但是二者的差别还是挺大的。
rknpu driver 0.9.8 相对于 0.9.6 主要有以下一些区别:
更好的芯片适配性3:0.9.8 版本主要是为了更好地适配 rk3588 和 rk3576 芯片对大模型端的支持。在 0.9.8 版本的内核代码中存在一段对 rk3576 的一个类型的引用,不过在驱动源码中一开始未定义,需要将其注释掉或修改为提示的
MONITOR_TPYE_DEV(作者内核版本是 5.10),以解决编译报错问题,而 0.9.6 版本可能在这些芯片的大模型支持方面存在不足。功能完善与优化:通常情况下,驱动程序的版本升级会对一些功能进行完善和优化,可能包括提高 NPU 的性能、稳定性,或者修复了 0.9.6 版本中存在的一些漏洞和问题,使 NPU 在处理神经网络推理计算等任务时更加高效和可靠。例如,可能优化了数据传输、处理的流程,减少了延迟或提高了运算速度,但具体的优化细节可能因芯片厂商的更新日志和实际测试情况而异。
下载到所需的镜像后,下面就开始正式进行系统的安装,这里使用的是内存卡进行安装镜像系统,你需要准备以下东西:
内存卡(>8G)
SD Card Formatter(SD Memory Card Formatter for Windows/Mac - SD Association)
usbimager(bzt / usbimager · GitLab)
安装过程
执行过程:
使用SD Card Formatter将内存卡快速格式化
使用usbimager将下载好的镜像文件烧录到格式化的内存卡中,注意:只支持.xz或img后缀的镜像,若你的下载的镜像是上面提供的高rknpu driver的版本,那么你得到的可能是个.gz的压缩文件,你需要解压并得到.img的文件,以便于镜像的安装
安装完成后,将内存卡插入开发板,稍等片刻,便会出现登录窗口
配置系统
香橙派默认账号密码:
root:orangepi
orangepi:orangepi
armbian默认账号密码:
root:1234
若希望将系统安装到emmc中,请参考这里:
Armbian:入门 - Armbian Documentation
期间,可能需要apt update和apt upgrade,可以替换为国内的镜像源,这里使用清华大学的镜像源,注意选择自己系统对应的镜像源,当前系统是armbian:armbian | 镜像站使用帮助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror
环境配置
系统信息
root@orangepi5plus:/# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 24.04.2 LTS
Release: 24.04
Codename: noble
root@orangepi5plus:/# uname -r
6.1.43-rockchip-rk3588
root@orangepi5plus:/# lscpu
Architecture: aarch64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
root@orangepi5plus:/# docker --version
Docker version 28.0.4, build b8034c0
root@orangepi5plus:/# docker compose version
Docker Compose version v2.34.0
root@orangepi5plus:/# cat /sys/kernel/debug/rknpu/version
RKNPU driver: v0.9.6更改镜像源
这里选择Ubuntu Ports镜像,Ubuntu Ports是Arm64,Armhf等平台的Ubuntu软件仓库
官方镜像地址:https://developer.aliyun.com/mirror/ubuntu-ports?spm=a2c6h.13651102.0.0.1ecc1b11fC2McV
修改镜像源文件:/etc/apt/sources.list
deb https://mirrors.aliyun.com/ubuntu-ports/ noble main restricted universe multiverse
deb-src https://mirrors.aliyun.com/ubuntu-ports/ noble main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu-ports/ noble-security main restricted universe multiverse
deb-src https://mirrors.aliyun.com/ubuntu-ports/ noble-security main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu-ports/ noble-updates main restricted universe multiverse
deb-src https://mirrors.aliyun.com/ubuntu-ports/ noble-updates main restricted universe multiverse
# deb https://mirrors.aliyun.com/ubuntu-ports/ noble-proposed main restricted universe multiverse
# deb-src https://mirrors.aliyun.com/ubuntu-ports/ noble-proposed main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu-ports/ noble-backports main restricted universe multiverse
deb-src https://mirrors.aliyun.com/ubuntu-ports/ noble-backports main restricted universe multiverse随后执行apt update更新镜像源包
挂载硬盘
下载挂载硬盘所需包:exfat-fuse以及exfatprogs
root@orangepi5plus:/etc/apt# apt-get install exfat-fuse
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
exfat-fuse
0 upgraded, 1 newly installed, 0 to remove and 324 not upgraded.
Need to get 25.6 kB of archives.
After this operation, 82.9 kB of additional disk space will be used.
Get:1 https://mirrors.aliyun.com/ubuntu-ports noble/universe arm64 exfat-fuse arm64 1.4.0-2 [25.6 kB]
Fetched 25.6 kB in 0s (88.2 kB/s)
Selecting previously unselected package exfat-fuse.
(Reading database ... 39869 files and directories currently installed.)
Preparing to unpack .../exfat-fuse_1.4.0-2_arm64.deb ...
Unpacking exfat-fuse (1.4.0-2) ...
Setting up exfat-fuse (1.4.0-2) ...
Processing triggers for man-db (2.10.2-1) ...
root@orangepi5plus:/etc/apt# sudo apt-get install exfatprogs
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
exfatprogs
0 upgraded, 1 newly installed, 0 to remove and 324 not upgraded.
Need to get 64.9 kB of archives.
After this operation, 435 kB of additional disk space will be used.
Get:1 https://mirrors.aliyun.com/ubuntu-ports noble/universe arm64 exfatprogs arm64 1.2.2-1build1 [64.9 kB]
Fetched 64.9 kB in 0s (244 kB/s)
Selecting previously unselected package exfatprogs.
(Reading database ... 39854 files and directories currently installed.)
Preparing to unpack .../exfatprogs_1.2.2-1build1_arm64.deb ...
Unpacking exfatprogs (1.2.2-1build1) ...
Setting up exfatprogs (1.2.2-1build1) ...
Processing triggers for man-db (2.10.2-1) ...
查看硬盘设备地址,找到最大的分区,这里是sda2,一会儿就用它挂载到系统
root@orangepi5plus:/etc/apt# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 12.7T 0 disk
├─sda1 8:1 0 16M 0 part
└─sda2 8:2 0 12.7T 0 part
mtdblock0 31:0 0 16M 0 disk
mmcblk0 179:0 0 233.3G 0 disk
├─mmcblk0p1 179:1 0 1G 0 part /boot
└─mmcblk0p2 179:2 0 229.9G 0 part /var/log.hdd创建硬盘要挂载到系统的目录,并挂载
root@orangepi5plus:/etc/apt# mkdir -m 777 /mnt/wukongroot@orangepi5plus:/etc/apt# mount -t exfat-fuse /dev/sda2 /mnt/wukong/
FUSE exfat 1.4.0 (libfuse3)
WARN: volume was not unmounted cleanly.查看/dev/sda2分区是否挂载到/mnt/wukong
root@orangepi5plus:/etc/apt# df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 3.2G 17M 3.1G 1% /run
/dev/mmcblk0p2 227G 2.2G 222G 1% /
tmpfs 16G 0 16G 0% /dev/shm
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 16G 4.0K 16G 1% /tmp
/dev/mmcblk0p1 1022M 120M 903M 12% /boot
/dev/zram1 188M 2.6M 171M 2% /var/log
tmpfs 3.2G 0 3.2G 0% /run/user/1000
tmpfs 3.2G 0 3.2G 0% /run/user/0
/dev/sda2 13T 267G 13T 3% /mnt/wukong开机自动挂载硬盘
获取分区UUID
root@orangepi5plus:~# sudo blkid /dev/sda2
/dev/sda2: LABEL="EXFAT_14T" UUID="3A34-BB7F" BLOCK_SIZE="512" TYPE="exfat" PARTLABEL="Basic data partition" PARTUUID="3d6c752f-c336-405e-ab51-2eb0966a0e84"编辑/etc/fstab,追加以下内容
UUID=3A34-BB7F /mnt/wukong exfat-fuse defaults,uid=1000,gid=1000,umask=0000,allow_other 0 0完整内容
root@orangepi5plus:~# cat /etc/fstab
UUID=4694b5ee-9f59-4564-8f67-d51ccf671fe4 / ext4 defaults,noatime,commit=600,errors=remount-ro 0 1
UUID=B7B5-A91A /boot vfat defaults 0 2
tmpfs /tmp tmpfs defaults,nosuid 0 0
UUID=3A34-BB7F /mnt/wukong exfat-fuse defaults,uid=1000,gid=1000,umask=0000,allow_other 0 0定时挂载
由于某些特殊情况,如磁盘高温保护,断电,磁盘挂载延时等情况,磁盘可能未能正常挂载到系统,这里设定每隔五分钟自动挂载设备,编辑/etc/crontab文件,追加以下内容:
*/5 * * * * root mount -a >> /var/log/mount_a.log 2>&1完整内容:
root@orangepi5-plus:/var/log# cat /etc/cron
cron.d/ cron.daily/ cron.hourly/ cron.monthly/ crontab cron.weekly/
root@orangepi5-plus:/var/log# cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
# You can also override PATH, but by default, newer versions inherit it from the environment
#PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
# 每天凌晨3点自动备份
0 3 * * * root RESTIC_PASSWORD=****** restic backup --repo /mnt/wukong/os/backup/ / --exclude /dev --exclude /proc --exclude /sys --exclude /tmp --exclude /run --exclude /mnt >> /var/log/restic_backup.log 2>&1
# 每隔五分钟自动挂载设备
*/5 * * * * root mount -a >> /var/log/mount_a.log 2>&1指令详解:
mount -a是 Linux 系统中的一个命令,用于挂载/etc/fstab文件中列出的所有文件系统。- *
mount:** 是 Linux 中用于挂载文件系统的命令。挂载是指将一个文件系统 (例如硬盘分区、USB 设备、网络共享) 连接到文件系统树中的一个目录 (称为挂载点),使得可以通过该目录访问文件系统中的文件和目录。- *
-a:** 是mount命令的一个选项,表示 "all",即挂载所有在/etc/fstab文件中定义的文件系统。执行
mount -a命令后,系统会读取/etc/fstab文件,并尝试挂载其中列出的所有文件系统。如果某个文件系统已经挂载,则mount -a会跳过该文件系统。系统启动时会自动执行
mount -a命令,挂载/etc/fstab中定义的所有文件系统。如果某些文件系统由于某种原因未正确挂载,可以使用
mount -a命令尝试重新挂载。
关于是否需要手动重启服务:
tips:
cron守护进程会定期扫描/etc/crontab文件以及/etc/cron.d/目录下的所有文件,以查找新的或修改过的定时任务。当cron守护进程检测到文件发生更改时,它会自动重新加载配置文件,而无需手动重启服务。
安装代理客户端
在服务搭建的过程中,很多时候我们所用到的资源,如:镜像、模型、开源项目等,这些资源不可避免的很多都在国外,在搭建自己的服务过程中,最头疼的也是这个问题,很多时候,尤其是在linux服务器上,经常会因为网络受限,导致服务器软件包更新失败、源码拉取失败、镜像拉取失败等等问题,为了解决这些问题,这里找到一个基于Linux系统的代理软件
开始安装,clone项目
root@orangepi5plus:/app/docker/immich# cd /etc/
root@orangepi5plus:/etc# mkdir -m 777 clash
root@orangepi5plus:/etc# cd clash/
root@orangepi5plus:/etc/clash# $ git clone https://github.com/Elegycloud/clash-for-linux-backup.git clash-for-linux
Cloning into 'clash-for-linux'...
remote: Enumerating objects: 681, done.
remote: Counting objects: 100% (59/59), done.
remote: Compressing objects: 100% (22/22), done.
remote: Total 681 (delta 49), reused 37 (delta 37), pack-reused 622 (from 2)
Receiving objects: 100% (681/681), 18.42 MiB | 7.95 MiB/s, done.
Resolving deltas: 100% (243/243), done.
root@orangepi5plus:/etc/clash# cd clash-for-linux/编辑.env文件,添加订阅url,由于各大vpn厂商提供的代理节点列表格式不统一,这里需要将地址转换为clash需要json格式
转换地址网站:SoCloud 订阅转换、飞鸟云
订阅地址:https://fn1.476579.xyz/api/v1/client/subscribe?token=s9d9c3c1a7h4e3b9n7q0f4g9t1r5e8j6
转换后的地址:
root@orangepi5plus:/etc/clash/clash-for-linux# nano .env修改代理启动脚本,找到sed -n 开头的代码替换:
## Clash 配置文件重新格式化及配置
# 取出代理相关配置
#sed -n '/^proxies:/,$p' $Temp_Dir/clash.yaml > $Temp_Dir/proxy.txt
sed -n '/^proxies:/,$p' $Temp_Dir/clash_config.yaml > $Temp_Dir/proxy.txt
# 合并形成新的config.yaml
cat $Temp_Dir/templete_config.yaml > $Temp_Dir/config.yaml
cat $Temp_Dir/proxy.txt >> $Temp_Dir/config.yaml
\cp $Temp_Dir/config.yaml $Conf_Dir/启动代理:
root@orangepi5plus:/etc/clash/clash-for-linux# bash start.sh
CPU architecture: arm64
正在检测订阅地址...
Clash订阅地址可访问! [ OK ]
正在下载Clash配置文件...
配置文件config.yaml下载成功! [ OK ]
判断订阅内容是否符合clash配置文件标准:
订阅内容符合clash标准
正在启动Clash服务...
服务启动成功! [ OK ]
Clash Dashboard 访问地址: http://<ip>:9090/ui
Secret: a2s7m4l7b4e5t2s7b1j0t1m2t6v5j5r8r7a0m1g7d4s2w1z0i9a2a9o9e4o6n5b5
く__,.ヘヽ. / ,ー、 〉
\ ', !-─‐-i / /´
/`ー' L//`ヽ、
/ /, /| , , ',
イ / /-‐/ i L_ ハ ヽ! i
レ ヘ 7イ`ト レ'ァ-ト、!ハ| |
!,/7 '0' ´0iソ| |
|.从 _ ,,,, / |./ |
レ'| i>.、,,__ _,.イ / .i |
レ'| | / k_7_/レ'ヽ, ハ. |
| |/i 〈|/ i ,.ヘ | i |
.|/ / i: ヘ! \ |
kヽ>、ハ _,.ヘ、 /、!
!'〈//`T´', \ `'7'ーr'
レ'ヽL__|___i,___,ンレ|ノ
ト-,/ |___./
'ー' !_,.:
本项目完全免费,若你是收费买的,恭喜您,您被骗了!
项目地址:https://github.com/Elegycloud/clash-for-linux-backup
项目随时会寄,且行且珍惜!
请执行以下命令加载环境变量: source /etc/profile.d/clash.sh
请执行以下命令开启系统代理: proxy_on
若要临时关闭系统代理,请执行: proxy_off
root@orangepi5plus:/etc/clash/clash-for-linux# source /etc/profile.d/clash.sh
root@orangepi5plus:/etc/clash/clash-for-linux# proxy_on
[√] 已开启代理
安装GPU驱动
根据immich官网提供的资料,若我们想要开启immich的硬件转码功能,需要设备拥有GPU驱动,详细介绍如下


这里要求我们安装libmali,根据提供的网址以及我们RK3588所需对应版本(libmali-valhall-g610-g13p0-gbm_1.9-1_arm64.deb),我这里下载的是最新的发布版本

下载完成之后,进入服务器进行安装。
要安装 libmali-valhall-g610-g13p0-gbm 并确保 /usr/lib/aarch64-linux-gnu/libmali.so.1 存在,我们按照以下步骤操作:
步骤 1:安装依赖项
sudo apt update
sudo apt install -f libdrm2 libgbm1 # 确保基础依赖已安装步骤 2:安装下载的 .deb 文件
sudo dpkg -i libmali-valhall-g610-g13p0-gbm_1.9-1_arm64.deb步骤 3:确认库文件位置
安装后库文件默认会出现在以下路径之一:
/usr/lib/libmali.so.1/usr/lib/aarch64-linux-gnu/libmali.so.1
检查是否已存在:
ls /usr/lib/aarch64-linux-gnu/libmali.so.1
ls /usr/lib/libmali.so.1步骤 4:若文件不存在,手动创建符号链接
如果库文件在 /usr/lib/libmali.so.1 但不在目标路径:
sudo ln -s /usr/lib/libmali.so.1 /usr/lib/aarch64-linux-gnu/libmali.so.1步骤 5:更新动态链接库缓存
sudo ldconfig步骤 6:验证安装
ls /usr/lib/aarch64-linux-gnu/libmali.so.1 # 确认文件存在
ldconfig -p | grep libmali.so.1 # 检查是否被缓存识别系统备份
Restic 简介
Restic 是一个现代化的备份程序,可以备份你的文件:
- 支持 Linux, BSD, macOS 和 Windows 系统 [6](https://restic.net/)
- 支持多种存储类型,包括本地目录、远程服务器、云存储等 [6](https://restic.net/)
- 易于使用,只需一个可执行文件 [3](https://tech.coe.drexel.edu/data/backups/restic/)
- 执行增量备份,只传输更改的部分 [3](https://tech.coe.drexel.edu/data/backups/restic/)
- 数据去重,节省存储空间 [3](https://tech.coe.drexel.edu/data/backups/restic/)
- 安全,使用加密技术 [3](https://tech.coe.drexel.edu/data/backups/restic/)
- 可以轻松验证备份,确保文件可以恢复
1. 安装 Restic
root@orangepi5-plus:~# apt install restic
正在读取软件包列表... 完成
正在分析软件包的依赖关系树... 完成
正在读取状态信息... 完成
下列软件包是自动安装的并且现在不需要了:
libpython2-stdlib libpython2.7-minimal libpython2.7-stdlib python-pkg-resources python-setuptools python2 python2-minimal python2.7 python2.7-minimal
使用'apt autoremove'来卸载它(它们)。
建议安装:
libjs-sphinxdoc sphinx-rtd-theme-common
下列【新】软件包将被安装:
restic
升级了 0 个软件包,新安装了 1 个软件包,要卸载 0 个软件包,有 1 个软件包未被升级。
需要下载 6,859 kB 的归档。
解压缩后会消耗 19.5 MB 的额外空间。
获取:1 http://ports.ubuntu.com jammy-security/universe arm64 restic arm64 0.12.1-2ubuntu0.3 [6,859 kB]
已下载 6,859 kB,耗时 4秒 (1,923 kB/s)
正在选中未选择的软件包 restic。
(正在读取数据库 ... 系统当前共安装有 40382 个文件和目录。)
准备解压 .../restic_0.12.1-2ubuntu0.3_arm64.deb ...
进度:[ 0%] [..................................................................................................................................................................................................................................................]
正在解压 restic (0.12.1-2ubuntu0.3) ...#######################..................................................................................................................................................................................................]
正在设置 restic (0.12.1-2ubuntu0.3) ...#######################################################################..................................................................................................................................................]
进度:[ 60%] [#################################################################################################################################################.................................................................................................]
正在处理用于 man-db (2.10.2-1) 的触发器 ...####################################################################################################################################################################.................................................] 2. 更新 Restic
root@orangepi5-plus:~# restic version
restic 0.12.1 compiled with go1.18.1 on linux/arm64
root@orangepi5-plus:~# restic self-update
writing restic to /usr/bin/restic
find latest release of restic at GitHub
latest version is 0.18.0
download SHA256SUMS
download SHA256SUMS.asc
GPG signature verification succeeded
download restic_0.18.0_linux_arm64.bz2
downloaded restic_0.18.0_linux_arm64.bz2
saved 28180664 bytes in /usr/bin/restic
successfully updated restic to version 0.18.0
root@orangepi5-plus:~# restic version
restic 0.18.0 compiled with go1.24.1 on linux/arm643. 初始化 Restic 仓库
root@orangepi5-plus:/mnt/wukong/os/backup# restic init --repo /mnt/wukong/os/backup/
enter password for new repository:
enter password again:
created restic repository c89fe5815b at /mnt/wukong/os/backup/
Please note that knowledge of your password is required to access
the repository. Losing your password means that your data is
irrecoverably lost.4. 首次备份
这里使--exclude指定要排除备份的目录,首次备份大约需要几分钟
root@orangepi5-plus:/mnt/wukong/os/backup# restic backup --repo /mnt/wukong/os/backup/ / --exclude /dev --exclude /proc --exclude /sys --exclude /tmp --exclude /run --exclude /mnt
enter password for repository:
repository c89fe581 opened (version 2, compression level auto)
created new cache in /root/.cache/restic
no parent snapshot found, will read all files
[0:00] 0 index files loaded
Files: 431376 new, 0 changed, 0 unmodified
Dirs: 65819 new, 0 changed, 0 unmodified
Added to the repository: 15.391 GiB (10.213 GiB stored)5. 自动备份
后续的自动备份这里使用系统自带的crontab添加一条任务:
编/etc/crontab文件,追加以下内容:
0 3 * * * root RESTIC_PASSWORD=***** restic backup --repo /mnt/wukong/os/backup/ / --exclude /dev --exclude /proc --exclude /sys --exclude /tmp --exclude /run --exclude /mnt >> /var/log/restic_backup.log 2>&1完整内容:
root@orangepi5-plus:/mnt/wukong/os/backup# cat /etc/cron
cron.d/ cron.daily/ cron.hourly/ cron.monthly/ crontab cron.weekly/
root@orangepi5-plus:/mnt/wukong/os/backup# cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
# You can also override PATH, but by default, newer versions inherit it from the environment
#PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#
0 3 * * * root RESTIC_PASSWORD=***** restic backup --repo /mnt/wukong/os/backup/ / --exclude /dev --exclude /proc --exclude /sys --exclude /tmp --exclude /run --exclude /mnt >> /var/log/restic_backup.log 2>&1首次备份完后,后续的备份就很快速了,不管是首次还是后续备份,命令都是一样的。
root@orangepi5-plus:/mnt/wukong/os/backup# RESTIC_PASSWORD=******* restic backup --repo /mnt/wukong/os/backup/ / --exclude /dev --exclude /proc --exclude sys --exclude /tmp --exclude /run --exclude /mnt
repository c89fe581 opened (version 2, compression level auto)
using parent snapshot 60b8b6be
[0:00] 100.00% 5 / 5 index files loaded
Files: 0 new, 16 changed, 431360 unmodified
Dirs: 0 new, 23 changed, 65796 unmodified
Added to the repository: 5.022 MiB (1.457 MiB stored)
processed 431376 files, 45.882 GiB in 0:45
snapshot d1758662 saved6. 恢复系统
要恢复系统,你需要使用 restic restore 命令。
restic restore latest --repo /mnt/wukong/os/backup --target /Docker安装及配置
由于 Ubuntu 官方仓库中的 Docker 版本可能不是最新的,我们将从 Docker 官方仓库安装 2。
更新软件包列表:
sudo apt update安装必要的依赖包,以便 apt 可以通过 HTTPS 使用仓库:
sudo apt install apt-transport-https ca-certificates curl software-properties-common添加 Docker 官方 GPG 密钥:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -添加 Docker 仓库到 APT 源:
sudo add-apt-repository "deb [arch=arm64] https://download.docker.com/linux/ubuntu jammy stable"注意:这里指定了
arch=arm64,因为您的系统是 aarch64 架构。同时,jammy是 Ubuntu 22.04 的代号。再次更新软件包列表,以应用新的仓库:
sudo apt update安装 Docker Engine:
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin验证 Docker 是否成功安装并运行:
sudo systemctl status docker如果 Docker 正在运行,您应该看到类似以下的输出:
● docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) Active: active (running) since ... Docs: https://docs.docker.com(可选) 允许非 root 用户执行 Docker 命令:
默认情况下,只有 root 用户或 docker 组的用户才能运行 Docker 命令。要允许您的用户执行 Docker 命令而无需 sudo,请执行以下操作:
bashsudo usermod -aG docker $USER newgrp docker注销并重新登录,或运行
newgrp docker命令以使更改生效。
步骤 2:安装 Docker Compose
从 Docker CE 20.10 开始,Docker Compose 已经集成为 Docker 的一个插件。在上面的步骤中,我们已经安装了 docker-compose-plugin,所以您现在可以使用 docker compose 命令。
验证 Docker Compose 是否安装成功:
docker compose version如果安装成功,您应该看到 Docker Compose 的版本信息。
更改docker镜像源
sudo nano /etc/docker/daemon.json完整内容
{
"builder": {
"gc": {
"defaultKeepStorage": "20GB",
"enabled": true
}
},
"experimental": false,
"registry-mirrors": [
"https://0c105db5188026850f80c001def654a0.mirror.swr.myhuaweicloud.com",
"https://5tqw56kt.mirror.aliyuncs.com",
"https://docker.ckyl.me/",
"https://docker.hpcloud.cloud",
"https://docker.m.daocloud.io",
"https://docker.unsee.tech",
"https://docker.1panel.live",
"http://mirrors.ustc.edu.cn",
"https://docker.chenby.cn",
"http://mirror.azure.cn",
"https://dockerpull.org",
"https://dockerhub.icu",
"https://hub.rat.dev",
"https://proxy.1panel.live",
"https://docker.1panel.top",
"https://docker.m.daocloud.io",
"https://docker.1ms.run",
"https://docker.ketches.cn"
]
}保存后,重启docker服务
sudo systemctl restart docker验证镜像源是否修改成功,在输出信息中,找到 Registry Mirrors 字段,若显示了你添加的镜像源地址,则表示修改成功。
sudo docker info自建服务
Portainer服务
Docker Portainer是一个开源的轻量级容器管理界面,用于简化Docker环境的管理。以下是关于Portainer的简要介绍:
功能介绍
直观的Web界面:提供易于使用的图形界面,无需深入了解Docker命令。
资源管理:管理容器、镜像、卷、网络等Docker资源。
多环境支持:支持本地和远程Docker环境的管理。
访问控制:提供用户管理和权限控制,确保安全访问。
应用模板:支持快速部署常见应用。
Docker配置
创建portainer的docker-compose.yml文件存放目录:
root@orangepi5plus:/# mkdir -m 777 app
root@orangepi5plus:/# cd app/
root@orangepi5plus:/app# mkdir -m 777 docker
root@orangepi5plus:/app# cd docker/
root@orangepi5plus:/app/docker# mkdir -m 777 portainer
root@orangepi5plus:/app/docker# cd portainer/新增docker-compose.yml配置文件
services:
portainer:
image: 6053537/portainer-ce
container_name: portainer
restart: unless-stopped
ports:
- "9443:9443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
volumes:
portainer_data:运行Portainer容器
docker compose up -d访问Portainer
https://<your_server_ip>:9443这个网站要求密码长度必须至少为 12 个字符。
使用该网站生成一个密码:随机密码生成器 | 菜鸟工具
用户名:admin
密码:rC4-oO7>iS9)
设置开机自启
修改docker-compose.yml文件,主要新增:restart: unless-stopped
version: '3.9'
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
restart: unless-stopped
ports:
- "9443:9443"
- "8000:8000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
volumes:
portainer_data:设置docker自启
sudo systemctl enable docker检查是否设置成功
sudo systemctl is-enabled docker # 应返回enabled重启,检查是否成功
# 模拟重启测试
sudo reboot
docker ps | grep portainerImmich服务
简要介绍
Immich是一款开源的、自托管的照片和视频备份解决方案,允许用户在私有服务器上存储、管理和分享他们的媒体文件。以下是Immich的主要特点:
自托管:所有数据存储在用户自己的服务器上,确保数据隐私和安全。
自动备份:支持移动设备中的照片和视频自动备份,确保数据安全无忧。
跨平台支持:提供移动端(iOS和Android)和Web端应用,方便用户随时随地访问和管理备份内容。
隐私保护:由于数据存储在自己的服务器上,用户的照片和视频不会被未经授权的第三方访问。
开源免费:项目在GitHub上开源,用户可以自由查看、修改和分发。
易于部署:支持Docker容器化部署,安装和维护简单。
安装配置
安装方式有很多种,这里使用之前安装的portainer来安装immich,以便于管理 参考官网安装方式:Portainer | Immich
完整配置截图:

点击部署后会自动拉取容器并运行,看到下面的服务都启动后便可使用immich了

常规配置,我们这里不做过多介绍,参考官方文档即可,下面我们针对两种特殊情况进行配置。
开启GPU硬件转码
在前面的步骤,我们已经安装好了GPU驱动,符合immich服务开启硬件转码的条件,下面是关于硬件转码的介绍
硬件转码:
此功能允许您使用GPU来加速转码并减少CPU负载。 请注意,与具有类似设置的软件转码相比,硬件转码产生的视频要大得多,通常质量较低。使用慢速预设和首选更高效的编解码器可以缩小这一差距。
所以,这里就按照官方的说法,添加immich-server开启GPU加速的参数(官方示例):
services:
rkmpp:
security_opt: # enables full access to /sys and /proc, still far better than privileged: true
- systempaths=unconfined
- apparmor=unconfined
group_add:
- video
devices:
- /dev/rga:/dev/rga
- /dev/dri:/dev/dri
- /dev/dma_heap:/dev/dma_heap
- /dev/mpp_service:/dev/mpp_service
#- /dev/mali0:/dev/mali0 # only required to enable OpenCL-accelerated HDR -> SDR tonemapping
volumes:
#- /etc/OpenCL:/etc/OpenCL:ro # only required to enable OpenCL-accelerated HDR -> SDR tonemapping
#- /usr/lib/aarch64-linux-gnu/libmali.so.1:/usr/lib/aarch64-linux-gnu/libmali.so.1:ro # only required to enable OpenCL-accelerated HDR -> SDR tonemapping配置完成后,记得重新启动immich-server服务。
开启机器学习加速
在安装当前系统的时候,我们选择的是Armbian24.11的镜像,系统自带NPU 0.9.8的驱动,这里我们天然的具备了immich-machine-learning服务开启硬件加速机器学习的条件,以下是相关介绍
硬件加速的机器学习:
此功能允许您使用GPU来加速机器学习任务,例如智能搜索和面部识别,同时降低CPU负载。
理论上我们可以使用GPU进行加速的,但是我们使用的SOC是RK3588,它内置了一个NPU芯片,具有6Tops的算力,关于为什么使用NPU加速而不是GPU加速,这里给出我找到的说法:
RKNPU:专为加速人工智能任务,特别是神经网络计算而设计,针对矩阵乘法、卷积等操作进行优化。
GPU:最初用于图形渲染,擅长并行计算,适合同时处理大量简单任务。
以及immich官方给出的说法:
与ARM NN(GPU)相比,RKNPU具有:
更广泛的模型支持 (包括搜索,其中ARM NN不加速)
更少的热量产生
精度略低 (RKNPU始终使用FP16,而ARM NN默认情况下使用更高的精度FP32,除非
MACHINE_LEARNING_ANN_FP16_TURBO已启用)变速 (在RK3588上测试):
如果
MACHINE_LEARNING_RKNN_THREADS默认值为1,则在大多数情况下,RKNPU的ML作业吞吐量将比ARM NN低得多,但延迟相似 (例如在搜索时)如果
MACHINE_LEARNING_RKNN_THREADS设置为3时,它将比FP32处的ARM NN快一些,但比ARM NN慢一些,如果MACHINE_LEARNING_ANN_FP16_TURBO已启用当其他任务也使用GPU (如转码) 时,RKNPU比ARM NN具有显着优势,因为它使用其他空闲的NPU而不是竞争GPU使用
降低RAM使用率,如果
MACHINE_LEARNING_RKNN_THREADS默认值为1,但如果大于1 (这是充分利用NPU所必需的,因此速度与ARM NN相当)
所以我们这里选择的是使用官方提供的rknn驱动而不是armnn(理论上我们拥有GPU驱动,这里是没问题的,但是没测)驱动的方式来启用加速。
添加immich-machine-learning开启NPU机器加速的参数(官方示例):
更改镜像名称,名称后追加"-rknn"
services: immich-machine-learning: # For hardware acceleration, add one of -[armnn, cuda, rocm, openvino, rknn] to the image tag. # Example tag: ${IMMICH_VERSION:-release}-cuda image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}-rknn
增加配置
services: rknn: security_opt: - systempaths=unconfined - apparmor=unconfined devices: - /dev/dri:/dev/dri
更改完配置后,需要重新拉取新的immich-machine-learning镜像并重新部署。
完整配置
#
# WARNING: To install Immich, follow our guide: https://immich.app/docs/install/docker-compose
#
# Make sure to use the docker-compose.yml of the current release:
#
# https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
#
# The compose file on main may not be compatible with the latest release.
name: immich
services:
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
# extends:
# file: hwaccel.transcoding.yml
# service: cpu # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding
security_opt: # enables full access to /sys and /proc, still far better than privileged: true
- systempaths=unconfined
- apparmor=unconfined
group_add:
- video
devices:
- /dev/rga:/dev/rga
- /dev/dri:/dev/dri
- /dev/dma_heap:/dev/dma_heap
- /dev/mpp_service:/dev/mpp_service
#- /dev/mali0:/dev/mali0 # only required to enable OpenCL-accelerated HDR -> SDR tonemapping
volumes:
# Do not edit the next line. If you want to change the media storage location on your system, edit the value of UPLOAD_LOCATION in the .env file
- ${UPLOAD_LOCATION}:/usr/src/app/upload
- /etc/localtime:/etc/localtime:ro
#- /usr/local/etc/OpenCL:/etc/OpenCL:ro # only required to enable OpenCL-accelerated HDR -> SDR tonemapping
#- /usr/local/lib/aarch64-linux-gnu/libmali.so.1:/usr/lib/aarch64-linux-gnu/libmali.so.1:ro # only required to enable OpenCL-accelerated HDR -> SDR tonemapping
env_file:
- stack.env
ports:
- '2283:2283'
depends_on:
- redis
- database
restart: always
healthcheck:
disable: false
immich-machine-learning:
container_name: immich_machine_learning
# For hardware acceleration, add one of -[armnn, cuda, rocm, openvino, rknn] to the image tag.
# Example tag: ${IMMICH_VERSION:-release}-cuda
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}-rknn
# extends: # uncomment this section for hardware acceleration - see https://immich.app/docs/features/ml-hardware-acceleration
# file: hwaccel.ml.yml
# service: cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference - use the `-wsl` version for WSL2 where applicable
security_opt:
- systempaths=unconfined
- apparmor=unconfined
devices:
- /dev/dri:/dev/dri
volumes:
- /app/immich/cache:/cache
env_file:
- stack.env
restart: always
healthcheck:
disable: false
redis:
container_name: immich_redis
image: docker.io/redis:6.2-alpine@sha256:148bb5411c184abd288d9aaed139c98123eeb8824c5d3fce03cf721db58066d8
healthcheck:
test: redis-cli ping || exit 1
restart: always
database:
container_name: immich_postgres
image: docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:739cdd626151ff1f796dc95a6591b55a714f341c737e27f045019ceabf8e8c52
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_DB: ${DB_DATABASE_NAME}
POSTGRES_INITDB_ARGS: '--data-checksums'
volumes:
# Do not edit the next line. If you want to change the database storage location on your system, edit the value of DB_DATA_LOCATION in the .env file
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
healthcheck:
test: >-
pg_isready --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" || exit 1; Chksum="$$(psql --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" --tuples-only --no-align --command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')"; echo "checksum failure count is $$Chksum"; [ "$$Chksum" = '0' ] || exit 1
interval: 5m
start_interval: 30s
start_period: 5m
command: >-
postgres -c shared_preload_libraries=vectors.so -c 'search_path="$$user", public, vectors' -c logging_collector=on -c max_wal_size=2GB -c shared_buffers=512MB -c wal_compression=on
restart: always
volumes:
model-cache:
环境变量:
UPLOAD_LOCATION=/mnt/wukong/immich
DB_DATA_LOCATION=./postgres
IMMICH_VERSION=release
DB_PASSWORD=postgres
DB_USERNAME=postgres
DB_DATABASE_NAME=immich
TZ=Asia/Shanghai
TRANSFORMERS_CACHE=/app/immich/cache访问Immich:
http://<your_server_ip>:2283地图主题
模型配置
模型选择
我们在创建immich服务的时候会涉及到以下几种模型,主要用于机器学习的设置,当然这些模型也源自于官方推荐的模型:
人脸识别模型(immich-人脸识别-人脸识别模型):
immich-app/antelopev2
immich-app/buffalo_l
智能搜索模型(immich-智能搜索-CLIP模型):
immich-app/XLM-Roberta-Large-Vit-B-16Plus(注意:若为aarch64架构的设备,仅支持cpu运行,不支持RKNN (Rockchip)的硬件加速机器学习)
ViT-L-16-SigLIP2-384__webli(这个模型也是经历过使用上面的模型遇到的问题,在issue中找到的解决方案,该模型支持RKNN加速)
模型下载
模型下载地址:
1、huggingface镜像网:HF-Mirror
2、异性岛:https://aliendao.cn
3、国内替代:https://modelscope.cn/home
4、模力方舟(Gitee AI)https://ai.gitee.com/
模型下载解决办法:
参考知乎(https://zhuanlan.zhihu.com/p/663712983)
这里使用推荐的huggingface-cli 进行下载的方式
# 按需修改参数
# 修改1:模型名称-immich-app/ViT-L-16-SigLIP2-384
# 修改2:模型下载目录名称-ViT-L-16-SigLIP2-384__webli
huggingface-cli download immich-app/ViT-L-16-SigLIP2-384__webli --local-dir ViT-L-16-SigLIP2-384__webli部分执行日志如下:
部分情况可能下载不成功,大概率是网络问题,这里建议使用科学工具下载,并将代理更改为TUN模式(不懂的可以百度:TUN模式和系统代理模式的区别)
PS E:\leeleo\immich模型> huggingface-cli download immich-app/ViT-L-16-SigLIP2-384__webli --local-dir ViT-L-16-SigLIP2-384__webli
⚠️ Warning: 'huggingface-cli download' is deprecated. Use 'hf download' instead.
Fetching 164 files: 1%|▊ | 1/164 [00:00<00:53, 3.07it/s]Downloading 'textual/onnx__MatMul_4693' to 'ViT-L-16-SigLIP2-384__webli\.cache\huggingface\download\textual\6umd0cxo5zyrYxJ1oQuQ9JrZ0fo=.045527ee754ccf37d05cc3d8e12a4476921efed6bb63c0015079d468288b60f4.incomplete'
Xet Storage is enabled for this repo, but the 'hf_xet' package is not installed. Falling back to regular HTTP download. For better performance, install the package with: `pip install huggingface_hub[hf_xet]` or `pip install hf_xet`
Downloading 'textual/onnx__MatMul_4651' to 'ViT-L-16-SigLIP2-384__webli\.cache\huggingface\download\textual\xAPNXXnW_3oVaPjX6ojjYZklE8o=.d3328f759a8a1c78188083313f57a96ae09f03842c531df8e24b9734c2bab5fa.incomplete'
Downloading 'textual/onnx__MatMul_4612' to 'ViT-L-16-SigLIP2-384__webli\.cache\huggingface\download\textual\mg1mkykMcSkL2Cmo8jlvsRL1tt0=.575e95b60986547dce34e2a663908dc2852cdde5ea7ead78849e5ff8ce7a5ecf.incomplete'
Xet Storage is enabled for this repo, but the 'hf_xet' package is not installed. Falling back to regular HTTP download. For better performance, install the package with: `pip install huggingface_hub[hf_xet]` or `pip install hf_xet`
Xet Storage is enabled for this repo, but the 'hf_xet' package is not installed. Falling back to regular HTTP download. For better performance, install the package with: `pip install huggingface_hub[hf_xet]` or `pip install hf_xet`
Downloading 'textual/onnx__MatMul_4692' to 'ViT-L-16-SigLIP2-384__webli\.cache\huggingface\download\textual\CaogzFCi0wzG5zDpSi1gGWsQxWU=.6eb18939b8285643d2f762eeaab656166f104a915a53699dd8c3a64143782628.incomplete'
Xet Storage is enabled for this repo, but the 'hf_xet' package is not installed. Falling back to regular HTTP download. For better performance, install the package with: `pip install huggingface_hub[hf_xet]` or `pip install hf_xet`
Downloading 'textual/onnx__MatMul_4694' to 'ViT-L-16-SigLIP2-384__webli\.cache\huggingface\download\textual\g2AMHBkBmE2vZEnBWMBhHaLc10c=.72d923170816fc964ec8f5e51bdebddae0ca8c7e2a47108c1342621560abd698.incomplete'
Xet Storage is enabled for this repo, but the 'hf_xet' package is not installed. Falling back to regular HTTP download. For better performance, install the package with: `pip install huggingface_hub[hf_xet]` or `pip install hf_xet`
Downloading 'textual/onnx__MatMul_4652' to 'ViT-L-16-SigLIP2-384__webli\.cache\huggingface\download\textual\oLFFiVwLDVvx_4R1Xrzg33LZ0pA=.ebf2a071cb262d814953b09f1ee49976fbf90bd503057cb9a315b99314db6d50.incomplete'
Xet Storage is enabled for this repo, but the 'hf_xet' package is not installed. Falling back to regular HTTP download. For better performance, install the package with: `pip install huggingface_hub[hf_xet]` or `pip install hf_xet`
Downloading 'README.md' to 'ViT-L-16-SigLIP2-384__webli\.cache\huggingface\download\Xn7B-BWUGOee2Y6hCZtEhtFu4BE=.0bddbb6d5331139dc8614a4db1273df336f655af.incomplete'
Downloading 'textual/onnx__MatMul_4653' to 'ViT-L-16-SigLIP2-384__webli\.cache\huggingface\download\textual\JvaR6sD9DPwUH3vwOzFIkHubW9Q=.549d4236a1c5fcd1b3449670443d5c739966c734522a62896b7f254c75d23c37.incomplete'
Xet Storage is enabled for this repo, but the 'hf_xet' package is not installed. Falling back to regular HTTP download. For better performance, install the package with: `pip install huggingface_hub[hf_xet]` or `pip install hf_xet`
README.md: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 320/320 [00:00<?, ?B/s]
Download complete. Moving file to ViT-L-16-SigLIP2-384__webli\textual\rknpu\rk3568\model.rknn██████████████████████████████████▋ | 965M/1.14G [12:27<01:59, 1.49MB/s]
text.token_embedding.weight: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1.05G/1.05G [13:34<00:00, 1.29MB/s]
Download complete. Moving file to ViT-L-16-SigLIP2-384__webli\textual\text.token_embedding.weight████████████████████████████████████████▌ | 1.06G/1.14G [13:28<00:53, 1.54MB/s]
model.rknn: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 674M/674M [05:46<00:00, 1.94MB/s]
Download complete. Moving file to ViT-L-16-SigLIP2-384__webli\visual\rknpu\rk3576\model.rknn██████████████████████████████████████████████▊ | 1.07G/1.14G [13:35<00:46, 1.56MB/s]
model.rknn: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1.14G/1.14G [14:24<00:00, 1.32MB/s]
Download complete. Moving file to ViT-L-16-SigLIP2-384__webli\textual\rknpu\rk3588\model.rknn██████████████████████████████████████████████████▌ | 1.11G/1.14G [14:03<00:19, 1.54MB/s]
model.onnx: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1.27G/1.27G [12:56<00:00, 1.63MB/s]
Download complete. Moving file to ViT-L-16-SigLIP2-384__webli\visual\model.onnx████████████████████████████████████████████████████████████████████| 1.14G/1.14G [14:24<00:00, 1.52MB/s]
model.rknn: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 653M/653M [06:46<00:00, 1.60MB/s]
Download complete. Moving file to ViT-L-16-SigLIP2-384__webli\visual\rknpu\rk3588\model.rknn
Fetching 164 files: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 164/164 [19:21<00:00, 7.09s/it]模型部署
下载完成后我们需要将模型放置到它该在的位置,以下目录为所有类型的模型存放位置
immich-machine-learning:
volumes:
- /app/immich/cache:/cache但是需要注意一点,我们不同的模型放到不同的目录:
人脸识别模型存放位置:/app/immich/cache/facial-recognition
能搜索模型存放位置:/app/immich/cache/clip
拷贝完成后目录结构如下:

随后,重启immich-machine-learning服务。
模型配置
接下来我们要做的就是对immich服务中,对人脸识别以及智能搜索的模型配置了:
这里需要注意的一点就是,模型名称是与上面拷贝的模型目录名称是一致的,不要输入错误了。

Nginx服务
代理配置
nginx.conf:
events {}
http {
resolver 223.5.5.5;
upstream immich_server {
server immich_server:2283;
}
upstream portainer {
server portainer:9443;
}
# yourdomain.com
server {
listen 80;
server_name yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name leeleo.cc;
ssl_certificate /etc/nginx/certs/yourdomain.com.pem;
ssl_certificate_key /etc/nginx/certs/yourdomain.com.key;
return 404; # 或者重定向到其他页面
}
# immich.yourdomain.com:443
server {
listen 443 ssl;
server_name immich.yourdomain.com;
ssl_certificate /etc/nginx/certs/immich.yourdomain.com.pem;
ssl_certificate_key /etc/nginx/certs/immich.yourdomain.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5:!TLSv1.0:!TLSv1.1;
location / {
proxy_pass http://immich_server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# portainer.yourdomain.com:443
server {
listen 443 ssl;
server_name portainer.yourdomain.com;
ssl_certificate /etc/nginx/certs/portainer.yourdomain.com.pem;
ssl_certificate_key /etc/nginx/certs/portainer.yourdomain.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5:!TLSv1.0:!TLSv1.1;
location / {
proxy_pass https://portainer;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}Docker配置
docker-compose.yml
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "80:80"
- "443:443"
networks:
- immich_default
- portainer_default
- halo_halo_network
dns:
- 223.5.5.5
- 223.6.6.6
- 8.8.8.8
- 8.8.4.4
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./certs:/etc/nginx/certs
restart: unless-stopped
networks:
immich_default: # 声明 immich_default 网络为外部网络
external: true
portainer_default: # 声明 portainer_default 网络为外部网络
external: true
halo_halo_network: # 声明 halo_halo_network 网络为外部网络
external: trueCertd证书服务
Docker配置
mkdir -p -m 777 /app/docker/certd
cd /app/docker/certd
nano docker-compose.yml 基本没做修改,只改了个版本号
version: '3.3' # 兼容旧版docker-compose
services:
certd:
# 镜像 # ↓↓↓↓↓ ---- 镜像版本号,建议改成固定版本号,例如:certd:1.29.0
image: registry.cn-shenzhen.aliyuncs.com/handsfree/certd:1.34.1
container_name: certd # 容器名
restart: unless-stopped # 自动重启
volumes:
# ↓↓↓↓↓ -------------------------------------------------------- 数据库以及证书存储路径,默认存在宿主机的/data/certd/目录下,【您需要定时备份此目录,以保障数据容灾】
# 只要修改冒号前面的,冒号后面的/app/data不要动
- /data/certd:/app/data
ports: # 端口映射
# ↓↓↓↓ ---------------------------------------------------------- 如果端口有冲突,可以修改第一个7001为其他不冲突的端口号,第二个7001不要动
- "7001:7001"
# ↓↓↓↓ ---------------------------------------------------------- https端口,可以根据实际情况,是否暴露该端口
- "7002:7002"
#↓↓↓↓ -------------------------------------------------------------- 如果出现getaddrinfo ENOTFOUND错误,可以尝试设置dns
# dns:
# - 223.5.5.5 # 阿里云公共dns
# - 223.6.6.6
# # ↓↓↓↓ --------------------------------------------------------- 如果你服务器在腾讯云,可以用这个替换上面阿里云的公共dns
# - 119.29.29.29 # 腾讯云公共dns
# - 182.254.116.116
# # ↓↓↓↓ --------------------------------------------------------- 如果你服务器部署在国外,可以用这个替换上面阿里云的公共dns
# - 8.8.8.8 # 谷歌公共dns
# - 8.8.4.4
# extra_hosts:
# # ↓↓↓↓ -------------------------------------------------------- 这里可以配置自定义hosts,外网域名可以指向本地局域网ip地址
# - "localdomain.com:192.168.1.3"
# # ↓↓↓↓ ------------------------------------------------ 直接使用主机的网络,如果网络问题实在找不到原因,可以尝试打开此参数
# network_mode: host
labels:
com.centurylinklabs.watchtower.enable: "true"
# ↓↓↓↓ -------------------------------------------------------------- 启用ipv6网络,还需要把下面networks的注释放开
# networks:
# - ip6net
environment:
# 设置环境变量即可自定义certd配置
# 配置项见: packages/ui/certd-server/src/config/config.default.ts
# 配置规则: certd_ + 配置项, 点号用_代替
# #↓↓↓↓ ----------------------------- 如果忘记管理员密码,可以设置为true,重启之后,管理员密码将改成123456,然后请及时修改回false
- certd_system_resetAdminPasswd=false
# 默认使用sqlite文件数据库,如果需要使用其他数据库,请设置以下环境变量
# 注意: 选定使用一种数据库之后,不支持更换数据库。
# 数据库迁移方法:1、使用新数据库重新部署一套,然后将旧数据同步过去,注意flyway_history表的数据不要同步
# #↓↓↓↓ ----------------------------- 使用postgresql数据库,需要提前创建数据库
# - certd_flyway_scriptDir=./db/migration-pg # 升级脚本目录
# - certd_typeorm_dataSource_default_type=postgres # 数据库类型
# - certd_typeorm_dataSource_default_host=localhost # 数据库地址
# - certd_typeorm_dataSource_default_port=5433 # 数据库端口
# - certd_typeorm_dataSource_default_username=postgres # 用户名
# - certd_typeorm_dataSource_default_password=yourpasswd # 密码
# - certd_typeorm_dataSource_default_database=certd # 数据库名
# #↓↓↓↓ ----------------------------- 使用mysql数据库,需要提前创建数据库 charset=utf8mb4, collation=utf8mb4_bin
# - certd_flyway_scriptDir=./db/migration-mysql # 升级脚本目录
# - certd_typeorm_dataSource_default_type=mysql # 数据库类型, 或者 mariadb
# - certd_typeorm_dataSource_default_host=localhost # 数据库地址
# - certd_typeorm_dataSource_default_port=3306 # 数据库端口
# - certd_typeorm_dataSource_default_username=root # 用户名
# - certd_typeorm_dataSource_default_password=yourpasswd # 密码
# - certd_typeorm_dataSource_default_database=certd # 数据库名
# ↓↓↓↓ --------------------------------------------------------- 自动升级,上面certd的版本号要保持为latest
# certd-updater: # 添加 Watchtower 服务
# image: containrrr/watchtower:latest
# container_name: certd-updater
# restart: unless-stopped
# volumes:
# - /var/run/docker.sock:/var/run/docker.sock
# # 配置 自动更新
# environment:
# - WATCHTOWER_CLEANUP=true # 自动清理旧版本容器
# - WATCHTOWER_INCLUDE_STOPPED=false # 不更新已停止的容器
# - WATCHTOWER_LABEL_ENABLE=true # 根据容器标签进行更新
# - WATCHTOWER_POLL_INTERVAL=600 # 每 10 分钟检查一次更新
# ↓↓↓↓ -------------------------------------------------------------- 启用ipv6网络,还需要把上面networks的注释放开
#networks:
# ip6net:
# enable_ipv6: true
# ipam:
# config:
# - subnet: 2001:db8::/64
docker compose up -d
HeadScale服务
官网:https://headscale.net/stable/
搭建HeadScale服务
先建三个文件夹
mkdir -p ./headscale/{config,lib,run} cd ./headscale下载配置文件,并扔到/config目录中,最终呈现:
./headscale/config/config.yaml,对配置文件稍作修改,结果如下:server_url: https://headscale.leeleo.cc listen_addr: 0.0.0.0:443 metrics_listen_addr: 0.0.0.0:9090 grpc_listen_addr: 0.0.0.0:50443 tls_letsencrypt_challenge_type: TLS-ALPN-01 tls_letsencrypt_listen: ":http" tls_cert_path: "/var/certs/headscale.leeleo.cc.pem" tls_key_path: "/var/certs/headscale.leeleo.cc.key" dns: magic_dns: false
新建
docker-compose.yaml文件到./headscale目录,内容如下:services: headscale: # 手动指定版本号为:0.26.1 image: docker.io/headscale/headscale:0.26.1 restart: unless-stopped container_name: headscale # 若想远程访问需使用0.0.0.0而不是127.0.0.1 # 这里开放80端,不然Lets Encript证书检报错很烦 ports: - "0.0.0.0:8080:8080" - "0.0.0.0:9090:9090" - "0.0.0.0:5280:80" volumes: # Please set <HEADSCALE_PATH> to the absolute path # of the previously created headscale directory. - ./config:/etc/headscale - ./lib:/var/lib/headscale - ./run:/var/run/headscale - /app/docker/nginx/certs:/var/certs command: serve部署-验证
# 部署 docker compose up -d # 跟踪日志 docker logs --follow headscale # 检查容器状态 docker ps # 验证headscale是否可用: curl http://127.0.0.1:9090/metrics部署完成后需要创建个账户给后续客户端使用
docker exec -it headscale headscale users create admin
这里基本上就算是完成了,官网上还提供了其他的指令,内容比较多,基本用不上,到这就基本满足咱的使用了
安装TailScale客户端
官网:https://tailscale.com/download
可以理解为TailScale是客户端,而HeadScale是服务端
安装TailScale客户端:不同端的下载地址
不同端连接自建HeadScale服务的方式(参考:https://tailscale.com/kb/1507/custom-control-server?q=headscale&tab=windows)
Win:
tailscale login --login-server=https://headscale.leeleo.cc
Android:
点击Tailscale应用程序右上角的用户个人资料图标以打开设置菜单。
如果您尚未登录任何其他尾网,请点击登录。菜单项。否则,点按已登录的用户。
点击右上角的菜单,然后选择使用备用服务器。
输入自定义控制服务器URL并点击登录。
完事之后,最终都会弹出一个网页,提供一个命令行,让在咱的服务端执行,示例如下:

tips:如果上面图片中的网址并未弹出,那么就需要确认下当前客户端的DNS是否需要清理一下了,最简单的办法是断开网络重连一下,不行就手动设置静态IP地址,指定DNS服务,然后再切回DHCP自动分配。
然后,去服务端执行,出现Node *** registered字样就算是完成注册了
root@orangepi5-plus:/app/docker/headscale# docker exec -it headscale headscale nodes register --user admin --key z3lUqUEZ3ydDsm9xQu3mGNDf
Node pc0003 registered
MQTT和WS通讯协议服务
❓为什么选择Mosquitto
在家庭环境的NAS中部署Mosquitto(MQTT服务器)是一个相当实用的选择,主要基于以下几个核心需求和优势:
🏠 家庭物联网中枢的核心价值
1. 解决设备"孤岛"问题
统一通信协议:不同品牌的智能设备(如小米传感器、飞利浦灯泡、ESP32开发板等)可以通过MQTT这个通用协议进行通信
跨平台集成:作为Home Assistant、Node-RED等智能家居平台的消息总线,实现设备联动
2. 数据隐私与本地控制
完全本地化:所有设备数据在家庭内部网络流转,不依赖任何云服务
避免厂商锁定:即使设备厂商的云服务停止,本地自动化仍然正常工作
自定义规则:基于本地消息的自由自动化,不受云服务功能限制
💡 具体应用场景
下面这个表格详细对比了几款常见的MQTT服务端,你可以快速了解它们的特点。
对于在NAS的Docker环境中部署,Mosquitto因其轻量和简单,是目前最省心的选择。
🐳Docker配置
使用 Docker Compose 部署服务时,我们通常通过一个 docker-compose.yml 文件来定义服务。这里是一个基础且功能完整的配置示例,你可以直接使用:
version: '3.8' # 建议使用 3.8 或更高版本
services:
mosquitto:
image: eclipse-mosquitto:2 # 使用 Mosquitto 2.x 版本
container_name: mosquitto_server
restart: unless-stopped # 设置自动重启
ports:
- "1883:1883" # MQTT 协议默认端口
- "9001:9001" # WebSocket 协议端口,适用于浏览器等客户端
volumes:
- ./mosquitto/config:/mosquitto/config # 挂载配置文件目录
- ./mosquitto/data:/mosquitto/data # 挂载数据持久化目录
- ./mosquitto/log:/mosquitto/log # 挂载日志目录
networks:
- mosquitto_net # 自定义网络,便于其他容器通信
networks:
mosquitto_net:
name: mosquitto_network
driver: bridge镜像:我们使用了官方的
eclipse-mosquitto:2镜像。端口映射:
1883端口用于标准的 MQTT 通信,9001端口则用于支持 WebSocket 连接。数据卷:通过
volumes将容器内的配置、数据和日志目录挂载到宿主机,这样即使容器被删除,你的这些重要文件也不会丢失。网络:创建了一个自定义的桥接网络
mosquitto_net。如果 Home Assistant 也运行在 Docker 中,并接入同一个网络,它们之间就可以直接使用容器名mosquitto进行通信,无需通过宿主机的 IP 地址。
📁 创建目录和配置文件
创建目录结构
在你存放
docker-compose.yml文件的同级目录下,执行以下命令来创建所需的目录:mkdir -p mosquitto/config mosquitto/data mosquitto/log创建基础配置文件
在
mosquitto/config目录中创建一个名为mosquitto.conf的文件,并填入以下基本配置:# 启用数据持久化 persistence true # 设置持久化数据存储位置 persistence_location /mosquitto/data/ # 设置日志输出文件 log_dest file /mosquitto/log/mosquitto.log # MQTT 协议监听器 - 1883 端口 listener 1883 0.0.0.0 # WebSocket 协议监听器 - 9001 端口 listener 9001 0.0.0.0 protocol websockets # 允许匿名连接(初期测试用,后期建议关闭) allow_anonymous false # 指定密码文件 password_file /mosquitto/config/passwd
🚀 启动与验证
启动服务 在
docker-compose.yml文件所在目录下,执行以下命令来启动 Mosquitto 服务:docker compose up -d检查服务状态 运行
docker compose ps可以查看服务状态,确认 Mosquitto 容器是否正常启动。测试连接 你可以使用 MQTTX-1、桌面版 MQTT Explorer 等客户端工具进行测试。连接时,使用你 Docker 宿主机的 IP 地址,端口为
1883。由于我们目前允许匿名连接,通常可以直接连上。
🔒 增强安全性(可选但重要)
设置用户名和密码
修改配置文件:编辑
mosquitto/config/mosquitto.conf文件,禁用匿名访问并指定密码文件。allow_anonymous false password_file /mosquitto/config/passwd创建用户和密码:进入容器内部创建密码文件并添加用户(这里以用户名
myuser,密码mypassword为例)。# 进入容器 docker exec -it mosquitto sh # 在容器内创建密码文件并添加用户 mosquitto_passwd -b -c /mosquitto/config/passwd admin 123456 # 退出容器 exit重启服务:修改配置后,重启 Mosquitto 容器使配置生效。
docker compose restart
🔧 Nginx配置
nginx.conf配置
events {}
# TCP/UDP代理配置 (用于MQTT 1883端口)
stream {
upstream mosquitto_mqtt_server {
server mosquitto_server:1883; # 替换为您的Mosquitto容器名
}
# mosquitto.leeleo.cc:8883 - MQTT over SSL
server {
listen 8883 ssl;
proxy_pass mosquitto_mqtt_server;
ssl_certificate /etc/nginx/certs/mosquitto.leeleo.cc.pem;
ssl_certificate_key /etc/nginx/certs/mosquitto.leeleo.cc.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5:!TLSv1.0:!TLSv1.1;
# TCP代理相关配置
proxy_connect_timeout 1s;
proxy_timeout 1h; # MQTT连接通常需要长时间保持
proxy_buffer_size 4k;
}
}
http {
resolver 127.0.0.11 valid=10s; # 使用Docker内置DNS解析器
upstream mosquitto_ws_server {
server mosquitto_server:9001; # 替换为您的Mosquitto容器名
}
# mosquitto.leeleo.cc:443 -> 转发到Mosquitto的9001
server {
listen 443 ssl; # Nginx在9001端口监听SSL
server_name mosquitto.leeleo.cc;
ssl_certificate /etc/nginx/certs/mosquitto.leeleo.cc.pem;
ssl_certificate_key /etc/nginx/certs/mosquitto.leeleo.cc.key;
ssl_protocols TLSv1.2 TLSv1.3;
location / {
proxy_pass http://mosquitto_ws_server;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}docker-compose.yml配置
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "80:80"
- "443:443"
- "8883:8883"
networks:
- mosquitto_network
dns:
- 223.5.5.5
- 223.6.6.6
- 8.8.8.8
- 8.8.4.4
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./certs:/etc/nginx/certs
restart: unless-stopped
networks:
mosquitto_network: # 声明 mosquitto_network 网络为外部网络
external: true🔗 客户端连接方式
配置完成后,客户端应该这样连接:
MQTT客户端:
mqtts://mosquitto.leeleo.cc:8883WebSocket客户端:
wss://mosquitto.leeleo.cc:443