从零开始构建家庭共享存储
Contents
一切都要从前几天给手机刷新 ROM,导致数据丢失说起。
前些日子,我的 RedmiK40S MIUI13 突然给我自动更新至 MIUI14,这违背了我的意愿。但这还不至于让我动刷机的年头,毕竟年事已高,不再那么想折腾手机。可这次更新,不单单是 MIUI 版本的提升,更是 Android 12 到 13 的版本升级。这直接导致了我的钛备份闪退了,并且使用钛备份还原在 a12 上备份的应用,如果勾选还原应用数据,则必然导致对应应用闪退。应用备份出了问题我是无法接受的。于是,开始上 XDA 找 ROM,随便下了几个,准备动手。
我自觉这么多年刷机从未失手,再不济也能在 recovery 里面把数据迁移出来再进行格式化。不成想多年未刷机,出了个新名词"a/b slot". 一下子给我整懵了,在刷完 rom 之后的第一次启动卡 logo. 然后再进 recovery 直接给我把 data 分区锁上了。换了几个 recovery 还是无法解锁 data,最后只能无情 format data. 数据无价啊!
后来翻了几篇帖子,弄弄 a/b slot 到底是啥意思,放在下面供以后参考吧:
- How A/B Partitions and Seamless Updates Affect Custom Development on XDA
- How to fix unable to mount data internal storage 0mb in twrp permanently
- A/B slots flashing in TWRP
此外,这次踩坑在此处做了简单记录。折腾一宿加一天之后,终于用上了新 ROM,贴几张美图:
言归正传,新 ROM 装好之后,发现钛备份在 a12 创建的备份,如果还原应用数据,统统都会闪退。感概一波钛备份的过时之后,我寻到了两个替代品:
并且这次迎来了新的需求:在本地备份 app 数据之后,即时在移动硬盘上做一个备份。于是我想起来,我的小米路由器 3 具有一个 USB 接口。有没有可能将移动硬盘插在路由器上,然后连接该路由器的设备都可以访问这个移动硬盘呢?
然后兴冲冲的打开小米路由器的管理界面,发现文件共享需要下载他的软件,过于辣鸡了。一怒之下,给小米路由器 3 刷了 OpenWrt1.
给路由器刷 OpenWrt
这个网上教程很多,列举一下:
- 小米路由 3 刷 OpenWRT
- 小米路由器 3 刷机记录
- [OpenWrt Wiki] Xiaomi Mi WiFi R3 (Mi Wifi Router 3 / MIR3 / MI3)
- 小米路由器 3 刷机潘多拉 (Openwrt) 以及刷回教程
看这几篇应该够了,其中需要注意的点:
- 用于开启 ssh 功能的 U 盘必须是 fat 文件系统;
- 先刷开发版固件,再降级到 miwifi_r3_all_55ac7_2.11.20.bin,2.11.20 版本更容易打开 ssh.
OpenWrt 路由器部署 WebDAV 服务器
刷好之后,打开网关地址进入管理界面,如下图所示:
LuCI(Lua Configuration Interface)是 OpenWrt 的前端管理界面,默认基于 uhttpd 运行,而它不支持 WebDAV,所以我们换一个支持的 – lighttpd.
下面是我安装的 lighttpd 的相关软件包,可以用 luci 前端安装,也可以 ssh 到路由器执行opkg install lighttpd-xxx
.
|
|
接下来就需要编辑配置文件了,lighttpd 的配置文件位于/etc/lighttpd
下。经过配置的目录结构如下:
|
|
Lighttpd 采用模块化的配置方式,主配置文件为lightttpd.conf
,其会自动将conf.d
文件夹中的配置加载出来。所以我们对单模块做配置,只需要在 conf.d 文件夹中新增相关配置文件即可。
例如,conf.d 中的 30-webdav.conf 就是 WebDAV 服务相关的配置:
|
|
其中重要的地方我都加了注释,猛击 这里 详细了解配置语法。简单说明下第三行是个 条件配置,意思是 url 匹配后面这个正则表达式的话,scope 里面的配置才生效。其中,home_dir 和 conf_dir 这两个变量均来自于父文件夹的 lighttpd.conf:
|
|
接下来配置 WebDAV 的用户和密码,
|
|
可以配置多个用户,以及简单的权限管理。比如我的配置/dav/yychi
文件夹只能给用户 yychi 或 admin 访问,/dav/yukynn
文件夹只能给 yukyyn 或 admin 访问。
这里认证方式是明文密码,其实还有其他方式,不过需要安装其他包,觉得太麻烦,而且是局域网比较安全所以就不管了。
配置到现在就差不多了,让我们启动一下:
|
|
用同一局域网下的手机连接验证一下:
Ok,现在我们已经在路由器上部署好了 WebDAV server.
LuCI 后端更改
如果你打开网关地址(X-Wrt 默认是 192.168.15.1),你会发现 LuCI 已经打不开了。当然了,因为我们关闭了 LuCI 的后端 uhttpd,现在我们要把 LuCI 后端改为 lighttpd,这一点 OpenWrt Wiki 上有很详细的教程,这里我们就简短概括一下。
主要使用 lighttpd 的 cgi 功能,使得当用浏览器访问网关地址时,重定向到 luci 启动的 cgi 脚本。
|
|
这里的luci
就是启动脚本。
具体配置参考这里:
|
|
最后,
|
|
重启 lighttpd 查看效果,现在访问网关地址应该可以打开 LuCI 了。
Lighttpd 启用 HTTPS
到这一步为止,我们已经无痛在 OpenWrt 上搭建了一个 WebDAV server,你可以插个移动硬盘上去,然后使用任意支持 webdav 协议的客户端去操作这块存储空间,LuCI 也能访问了,很好。
然而偏偏有些应用,他不支持 http,他强制让你使用 https,确实,够安全。但对于局域网来说,难免有些多次一举。我说的就是 FolderSync,这是个好应用,可以将本地文件夹与云端(OneDrive, DropBox, WebDAV 等)文件夹进行双向同步,详询酷安#foldersync 话题。但我确实恼他不支持 http 协议。
没办法,只好安排一下。由于我是局域网内使用,而 FolderSync 其实也开了个后门,他支持自签名证书。
那我们就给他安排一下,参考这篇 wiki,非常简单。
网页端访问
你是否想在浏览器中也能访问 WebDAV server?Lighttpd 自带一个简单的页面,可通过以下配置开启:
# Override the /dav/ folder configured in 30-webdav.conf
$HTTP["url"] =~ "^/dav($|/)" {
# The root / is ovveriden by an alais in turris-root.conf so we must add another override
alias.url = ( "/dav/" => "/srv/disk/dav/" )
server.document-root := "/srv/disk/"
auth.backend := "plain"
auth.backend.plain.userfile := "/etc/lighttpd/webdav.shadow"
auth.require := (""=>("method"=>"basic","realm"=>"webdav","require"=>"valid-user"))
# (Optional) add a directory index to see files from a browser
server.dir-listing := "enable" # 这里
dir-listing.encoding := "utf-8" # 和这里
webdav.sqlite-db-name := "/etc/lighttpd/webdav_lock.db"
}
cf. https://gist.github.com/stokito/77c42f8aff2dade91621c1051f73e58c
加上上面两行配置,重启下 lighttpd,然后打开 192.168.15.1/dav 即可访问 webdav server:
这个界面只能读,不能写。
加载 webdav-js
OpenWrt 的 wiki 上提到一个方法可以让你在浏览器中访问 webdav server,是通过在根目录创建一个 index.html 文件实现的。这个文件里面引入了 webdav-js,作为一个精简的 web client,他支持对 webdav server 的写入操作(包括上传文件,创建文件夹,复制,移动,重命名等)。所以我们在根目录创建一个这样的文件,就可以看到如下界面:
原本这中方法有个问题,wiki 中也有提到:就是子文件夹中没有这个 index.html,因此访问子文件夹就无法展示了。但加了 lighttpd 本身的网页前端之后,每个子文件夹都是可访问的,我猜想应该是开启 dir-listing 选项之后,访问的时候会自动生成 index 文件。而因为 webdav-js 缓存的缘故,跳转到子文件夹,只有里面包含 index 文件,就可以进行访问,即便子文件夹中的 index 文件没有加载 webdav-js. 这样一来,就只需要在根目录添加一个加载了 webdav-js 的 index 文件,就能浏览任意子目录的效果。
Alist 文件共享服务
一路走来,我们在局域网搭建了一个 WebDAV server,实现了局域网内的文件共享。但是 WebDAV client 对于父母一辈的其实不太友好。而网页端也很简陋,如果他们想打开网页直接看视频什么的,还不够方便。
又忽然联想到家里还有一台旧笔记本躺在那里吃灰。于是翻将出来直接格式化,装了个 archlinux,不过没装图形界面。由于路由器的性能毕竟吃紧,把移动硬盘接在旧电脑上做文件服务器才是正理。我准备在这台机器上部署一个 Alist 服务器,archlinux 直接
|
|
即可安装。也可以使用官方文档中的一键脚本进行安装,使用脚本安装之后的路径在:
|
|
运行之后,就可以在浏览器输入 http://192.168.15.233:5244 打开 alist 界面了。
上面是我配置之后的样子2。更多关于 alist 的配置,网上多不胜数,我就不献丑了。
Alist 支持文件交互,就像云盘一样,可以上传/下载文件,在线播放音视频图片等,也可以用作 WebDAV server,更可以挂载阿里云盘,总之功能多多,值得一玩。
一点体验优化
上面说到,我将废弃的笔记本(dell-inspiron)用作文件服务器,它需要 7*24 小时开机,妥妥的就是一个正经的服务器。那万一停电了,路由器重启了,就是服务器 ip 变了怎么办?我还得去路由器上或者服务器本身上面去看看 ip,这显然很麻烦。所以必须给 dell-inspiron 一个固定的 ip. 使用 OpenWrt 很容易做到这一点。
甚至可以做个主机名映射,不用再记烦人的 ip.
这样就可以通过域名来访问文件服务。
总结
至此,我们就搭建了一个家庭共享存储。只要连上指定局域网,就可以访问并操作共享存储,而且可以基于 Alist 在线观看影视,十分方便。不过还有个痛点就是这个局域网其实是楼下路由器的子网,如果连楼下 wifi,就无法访问了。本来可以通过配置静态路由实现,但楼下路由偏偏不支持配置,只能先搁置一下了。