本文参加「自力更生」征文活动
碎碎念&需求&总体方案
尽管如此,中心辐射型还是有一些根本性的尴尬之处:它们不允许各个节点相互通信。如果您像我一样老,您还记得计算机可以直接交换文件而无需往返云端的情况。不管你信不信,这就是互联网过去的运作方式!可悲的是,开发人员已经停止构建点对点应用程序,因为现代互联网的架构几乎是偶然地完全演变为这种中心辐射式设计,通常以主要云提供商为中心收取租金。
关注NAS也有一段时间了,作为科班出身的对设备本身也比较了解。越发接近的时候就有疑问,专门的NAS和我使用自己的电脑到底有啥区别?
主要能分为软件和硬件两个方面考虑吧。
在硬件上,普通家用NAS价格比普通PC还是要低的,特别是其中一大块价格要为溢出的硬盘空间付费,一般来说NAS空间比普通PC要多不少。普通NAS计算资源应该是远不如普通PC的。本质上讲,NAS的硬件情况无非就是一个储存(硬盘)服务器。虽然不少NAS会加上一些备份策略提高储存服务的可靠性,但这种其实本来自己也可以做,多买点盘(花钱就行)。
那按照我的理解,主要目的就在于软件层面的支持咯(一直有听说买群晖就是为它的软件生态付费的说法)。那值不值?得从用户需求入手,仔细考虑需求大概分为这几个方面吧:
- 影音媒体库。相当于一个私有化的腾讯视频。这种视频平台作为成熟的产品理论上体验是最好的(只要给够钱),那么私有化只需要靠近它的体验,具体有什么呢:
- 随时随地打开即看,一般WIFI条件下没有延迟感知,直接就能开始看。
- 云同步,有许多设备同时观看,不同地方无缝衔接。比如在外面用手机看,回到家用回大屏看。
- 多账户、共享。家里多人都可以享用。
- 其他媒体库的一些使用需求。比如快速定位想看的,要有好看的海报墙(一眼看到帅哥才衡量要不要看这部剧)、一些剧的相关信息比如评分;进度条预览功能(快进时大概知道应该拖到哪里)等等。
- 备份-共享中心。相当于私有化的OneDrive、阿里/百度网盘。这里大概可以又分类抽离一下。首先讨论面向顶层应用和具体场景的,我个人觉得在日常生活里备份和共享的需求就是:照片和微信聊天记录。只说照片。也是目前很多云服务商最重要的卖点吧。包括各家手机厂商,在自家相册应用都会推云同步、云备份;阿里/百度网盘也能做、也想给你做这种事;还有其他专门做相册类应用的,著名的就是Google Photo这种。照片这种属于一定程度私密的敏感数据。特别讨论对于这个场景的需求,包括:
- 自动备份、同步终端设备的照片到服务器;
- 终端可以方便查阅服务器的储存;
- 图片管理,比如创建图集
- 支持多用户、共享、分享;
- 对于照片应用,支持一些更高级的功能:比如时间线、人物识别自动归类、AI打标签图片搜索、回忆(类似QQ的那年今日)等。主要能够帮助人更好的、更容易地管理、阅览自己的图库,毕竟积攒下来几千的照片放着一坨可能就是赛博积灰的下场。
- 对于上一点分岔出来的需求,主要就是偏下层一点的场景,比如:
- 放放不同设备不同用户的文件,需要时快速找到、使用、下载,就是普通的网盘服务;
- 文件自动备份同步,相当于OneDrive、坚果云这些备份网盘服务;
- 盘挂载,面向最底层的文件使用,不同电脑间无缝使用相同的空间和文件,像是使用本地文件资源管理器一样。
- 公网服务。随处访问。
工具本身并不重要,也没有意义,存在只是为了解决用户需求。那按照我整理的上述需求(可能有所遗漏),那只要去满足这些需求即可。而只要购买NAS就能完美满足我们的需求吗,对于这点暂时不得而知。
那我目前就按照手头的资源、现在的方案去做一个自己折腾版的NAS。这里我对NAS的定义就是一种家庭服务,能够支撑和满足我们的一些电子需求,包括但不仅限于上面所提的需求。
目前我的方案概述:
- 个人PC作为服务器
- 软件层使用EMBY作为媒体库支持+AList作为网盘支持+Immich作为图库支持。
- 中间网络层通过tailscale/zerotier的P2P打洞进行跨域访问,基本上除了移动(傻逼移动)都能打洞成功。但痛点在于必须完成前置的打洞步骤,虽然是一个设备完成过一次就一劳永逸了,但share给别人、作为一个team的配置还是有一点麻烦。
硬件方案
暂时用手头正在使用的笔记本。后续将其淘汰,专职用于NAS的硬件。
储存上目前:普通PC(3T固态),加上一个2T的移动硬盘。
储存策略:PC固态存还没看的资源,看完后的资源归档到移动硬盘,相当于备份。
扩展思路:购置一到两块更大的机械硬盘(8T左右),扩展储存空间,同时考虑认真的备份方案。比如增加一块8T储存硬盘和一块8T备份硬盘。后者周期性地手动插入,备份储存硬盘的内容(基于FrreFileSync等?)
软件方案
影音媒体库
基于PT站/普通资源站+Emby.
一种家庭媒体库方案,本身就是对下面的一堆媒体资源进行封装,然后下载元数据,整理成一些在线媒体源的形式。更方便、也更好看、更好管理。
本身使用很简单,比如我就是自己windows系统,那下载emby server部署就行。Download Emby - Emby
基本就是默认配置就好。关联本地的媒体资源。
然后作为一个管理器的话这样就行了。
除了emby,还有像plex、jellyfin等其他选择,具体参考:https://post.smzdm.com/p/awk8zn62/这里的对比。
个人首先用了emby,感觉不错,也试了一下其他两者,plex服务打不开,jellyfin开源版,个人感觉功能似乎有所不足。
照片库
原本用的是Google Photo,Google One100G空间就算是美区结算也就十来块钱,主要还是敏感数据的担心。考虑改为本地部署的方案。
Google Photo真恶心,甚至连方便清空上面照片的功能都没有(给你制造离开他平台的阻力),必须要清除空间,否则不订阅Google One后连GMail都用不了。
自部署方案选择:
- https://tonfotos.com/articles/self-hosted-photo-gallery/
- https://meichthys.github.io/foss_photo_libraries/
先使用Immich:
- github(两年开发、3w+stars):https://github.com/immich-app/immich
- 官方文档:https://immich.app/docs/overview/quick-start
- 官方频道是discord(因为正在快速开发,因此咨询官方人员挺重要的,回复很快):https://discord.com/channels/979116623879368755/994044917355663450
- windows安装流程参考:https://www.reddit.com/r/immich/comments/1b5u6p2/how_to_install_in_windows/。
概述来说主要是要通过Docker Compose使用,windows上可以通过Docker Desktop来进行。
使用起来也很简单,基本等同GooglePhoto(Logo也差不多)。但是通过ML(机器学习)进行人脸识别还是挺慢的(Google Photo也很慢),要等很久才行。
然后有和GooglePhoto一样的痛点,在移动端上传和备份照片时不能自动上传到对应文件夹名的相册中,默认情况下查看一张相册中的所有照片(数百或数千张)非常不方便。只能手动将照片一张一张地添加到不同的相册中。(一年前的issue了,可能会更新这个功能吧:https://github.com/immich-app/immich/discussions/1678)
个人解法:
先使用微力同步上传到电脑。
然后使用immich-cli命令上传,根据官方文档(here),这是支持自动命名文件夹作为相册的。
- 没有npm的话安装,考虑使用VMR一键安装。
- npm i -g @immich/cli
- 到Immich里获取API
- 登录:immich login http://localhost:2283/api key
然后就可以上传相应的图片(主要是需要文件夹信息创建相应的相册)。
可以用:immich upload --dry-run --album --recursive ./ 尝试一下发生什么. 图片在手机备份过了,检查HASH码,所以这里不会重复上传,只提取相册进行更新,不错。
Crawling for assets...
Checking files | ████████████████████████████████████████ | 100% | ETA: 0s | 1884/1884 assets
Found 0 new files and 1884 duplicates
All assets were already uploaded, nothing to do.
Would have created 12 new albums
Would have updated 1884 assets
没问题直接运行:immich upload --album --recursive ./
但是出现问题:Failed to add assets to album。然后docker logs -n 100 immich_server
查看日志会发现ERROR [QueryFailedError: duplicate key value violates unique constraint "PK_c67bc36fa845fb7b18e0e398180”。意思就是有重复的照片了就不行。Github有人提过这个issue了:https://github.com/immich-app/immich/issues/9115。看啥时候解决吧。
一种手动解决思路:根据上面issue下某个人的方案fdupes -rn --delete .
在windows上实现类似的效果,即查找重复的文件,进行删除。参考脚本:
# 这是先输出查看哪些重复的
$folderPath = "C:\\path\\to\\your\\folder"; $hashes = Get-ChildItem -Path $folderPath -Recurse -File | Get-FileHash; $duplicates = $hashes | Group-Object -Property Hash | Where-Object { $_.Count -gt 1 }; $duplicates | ForEach-Object { Write-Output "Duplicate files found:"; $_.Group | ForEach-Object { Write-Output $_.Path }; Write-Output "---" }
# 然后删除
$folderPath = "C:\\path\\to\\your\\folder"; $hashes = Get-ChildItem -Path $folderPath -Recurse -File | Get-FileHash; $duplicates = $hashes | Group-Object -Property Hash | Where-Object { $_.Count -gt 1 }; $duplicates | ForEach-Object { $_.Group | Select-Object -Skip 1 | Remove-Item -Force }
之后就可以正常导入相册了。
总体评价来说也是一种思路吧,就是有一份冗余数据存着。但也符合官方说的3-2-1备份策略。就是手机备份照片、然后同步到电脑另一个备份,之后通过这个使用CLI提取相册信息进行更新。麻烦的是每次都需要这样做(而不是在手机上使用自带图库管理后自动同步),也可以考虑完全用它的app来管理,那么就不需要多次管理了。
由于用到Docker和虚拟化环境,还是挺耗资源的,官方建议4GB内存以上,个人使用上这个服务单独就占用了4GB+的内存,开销挺大的,根据个人情况考虑取舍。
网盘(普通文件)
支持普通放放文件、多端储存下载、分享等。
选择参考:https://zhuanlan.zhihu.com/p/44103820
主要的选择标准:开源、好看、跨平台支持。
个人比较喜欢的:
- AList
- Cloudreve
- figegator
目前我自己选择了AList,能够实现的功能:
- 使用本地储存映射为网盘(意味着无需导入,想存到网盘的东西,直接就映射到网盘里了),跟本地使用一样管理文件一样,无感地初始化网盘;
- 普通网盘的功能,上传下载分享;
- 盘符挂载,挂载到文件系统里,当做普通文件使用。(windows挂载webdav参考:https://echo.xuchaoji.com/index.php/archives/400/)
网盘储存:
- 软件包
- 归档学习、工作记录。
将AList注册为开机自动服务,使用nssm。nssm install AList
.
网络方案
目前综合来看,对于自己(小家庭内部)使用而言,P2P(或者说VPN)方案是最优秀的,兼具了安全性和便捷性,一次配置一劳永逸,需要时启动软件(VPN)一键使用。进一步便捷化地,当NAS固定(一般情况都是固定的),其P2P分配的虚拟IP可以通过域名映射固定下来,就更加方便好记。就算不固定,也可以配置DDNS来进一步解决。
为什么打开VPN这步是必要的呢,这是重要的安全性保护。相比于直接暴露在公网使用服务,VPN加持下使用无疑是安全的多,也带来省心的好处,不需要太考虑安全保护和被攻击的后果。
那对于真的需要公网服务的场景呢。对于所述需求(媒体、网盘等),确实存在,比如对于网盘而言能够分享链接让任何人快速下载是一个重要的功能。对我们来说,确实不可能让每个人都先加入P2P再下载链接,或者我们使用一台临时的新设备访问资源也一样。确实存在一定的公网服务需求。
但是具体分析其实需求很小(或者很难解决)。如果还是对于个人使用的场景,无论什么设备都可以快速安装一个VPN软件,也不麻烦,或者使用常用设备(手机)来获取资源再转发到新设备。
对于任何人的场景,这个需求本来就很难办。如果兼具便捷性与安全性,没有什么风险和难度,那目前所有网盘厂商岂不是直接完蛋。毕竟对于任意Web设备,文件都存在自己Peer端,下载方和上传方都有资源,同时又都有上传和下载带宽,那为啥需要这个第三方。说着说着这其实不就是p2p下载(磁链、种子)吗。那直接用现成的P2P方案不就行了。比如qbittorrent这些软件制作种子发出去以供下载(ps种子制作需要tracker服务器,可以使用一些公用的比如:http://bt1.archive.org:6969/announce),或者类似的send anywhere这种在想服务(实测更慢,无法完全利用上行带宽)。总结来说,这种需求的方案已经被广泛地讨论和研究过,没有那么完美的,选择一个适合自己的就好。
实在想暴露服务,可以用frps等转发和内网穿透技术暴露内网服务,谨慎使用和挑选暴露的服务。
公网服务
Tailscale/zerotier P2P打洞。
关于Tailscale(它真的非常好用!):
- How it works: https://tailscale.com/blog/how-tailscale-works. 概述来说,
- 数据平面(P2P节点交互数据)使用WireGuard构建轻量级加密隧道,而且所有节点之前会组成Mesh组网,可任意联通。
- 这是通过控制平面(一个轻量的中心的协调服务器)实现的,作为公钥投递箱,负责给所有节点交换信息。同时控制域、ACL访问策略等严格控制哪些节点可以交互。这个服务器只能知道哪些节点可以互联,但无法窃听它们之间的通信,因为私钥始终保存在本地,只有持有私钥的节点自己才能解密发给自己的流量。
- 这就是所谓的"零信任"原则。控制平面是中心化的,由Tailscale运营,让网络管理变得很简单。数据平面则是去中心化的,由所有节点组成Mesh网络,让通信更高效安全。
- 在身份认证方面,基于原本的身份认证体系,比如单点登录SSO,使用常见的身份提供商有Google Workspace、Office 365等。
- 私人使用:3个用户、100台设备,基本满足需求了。
普通个人使用非常傻瓜便捷,多个设备下载app装上,用同一个身份认证账号(比如Google账号)登录即可,完全无感。不过多用户使用要注意一下,首先在原本那个账户处管理页面User中邀请新用户,用新用户登录然后接受这个邀请后。注销登录,然后重新在app里登录账户,在身份认证之后返回tailscale会询问你此时选择哪个tailnet加入,这个时候选择原本那个账户的tailnet加入,如下图。因为tailscale对于每个新注册的账户,都会默认建立分配一个tailnet,每个设备用对应账户登录后,判断这个账户在哪些net里,选择一个net加入后就进入这个域里,这个域内的设备才能相互交流。这里好像有一个bug,就是安卓app选择账户登录后,如果是在app内直接选择Google账户登录,并没有跳转到选择相应的net,而是直接进入这个账户对应的默认net,这时可以考虑选择其他登录方式,然后跳转到浏览器处进行登录,这时就没有问题了。
HTTPS保护(可选)
上面最主要的问题是,P2P打洞也是裸ip访问,没有HTTPS保护,在公网裸奔的流量(如果用Tailscale这种类似VPN的工具那还是安全的,经过了加密)。
这就需要反向代理工具以及一个域名。域名也更方便记忆,P2P分配的虚拟IP也是固定的。
反向代理使用Caddy,把内部服务器不同端口的服务,映射到不同域名,不同域名绑定相应的SSL证书(caddy自动申请管理)。
域名使用个人域名的三级域名即可。
Caddy反向代理非常简单:
example.com {
reverse_proxy 127.0.0.1:5244
}
将 `example.com` 替换为你自己解析后的域名。
问题:
在我的使用场景里,服务部署在内网中,然后不同地方的用户通过tailscale等软件进行P2P连接,然后使用P2P分配的虚拟ip地址获取到服务器的服务。这个时候,我想使用Caddy进行反向代理,通过域名访问相应的服务,同时希望加上HTTPS,但是这里是无法自动申请到证书的。
解决:
Caddy支持使用 DNS 验证方式获取证书:
- 使用支持 DNS 验证的证书颁发机构(如 Let's Encrypt、ZeroSSL 等)。
- 在您的域名注册商或 DNS 服务提供商处为您的域名添加所需的 DNS TXT 记录。
- 使用 Caddy 的 DNS 插件自动获取和更新证书。
此时的CaddyFile:
example.com {
tls {
dns tencentcloud {
secret_id YOUR_SECRET_ID
secret_key YOUR_SECRET_KEY
}
}
reverse_proxy <http://localhost:8080>
}
我是使用Windows,在Caddy官方下载页面下载的caddy,这里要使用dns.providers.tencentcloud这个插件,所以在下载页要勾选这个模块:
之后去腾讯云访问管理那添加一个API key。
然后就可以自动申请到证书,就可以使用HTTPS服务了。
注册为开机自启服务:
打开命令提示符为管理员模式,导航到NSSM的解压目录(包含nssm.exe
的目录),然后运行:
nssm install Caddy
在NSSM的界面上,设置:
- Path: 浏览到你的Caddy可执行文件的位置。
- Startup directory: 设置为Caddy可执行文件所在的目录。
- Arguments: 输入
run
。
点击“Install service”。
不同应用可能要求反向代理的一些相关配置,比如AList要求添加site_url,看各自服务的说明文档。
写在最后
来源于个人博客,为避免过于复杂的炫技,对一些内容进行了删减。但还是有较多各种工具混杂(npm、vmr、nssm),根据个人需求,觉得太复杂的话可以删去一些,只是降低一点便捷性,也不是不能用。就和最开头说的,要杀死中间商,还自己足够的自由,那确实需要一点个人折腾的精神,在如今AI加持下,这些实际上也不构成足够的阻碍,只是需要一点愿意开始的勇气。