突然想起来我在Hetzner那里还有一台闲置的纯IPv6服务器。想来想去，闲着也是闲着，不如拿来挂IRC。本文记述在这台服务器上搭建Quassel core的艰难坎坷。太长不看：IPv4的命还长着呢。IRC虽然我还年轻，但我觉得IRC这个东西挺酷的。尽管IRC并不是去中心化的，也不能发送文本之外的内容，但它可以self-host啊。如果我没记错的话，能够self host并且能做到不需要购买商业许可的聊天方案里，就只有Element/Matrix和IRC了，其他像是什么Threema OnPerm这些基本都要支付授权费。而即便是现代化的Element/Matrix，我认为在用户体验上也不是很能打IRC。当然，Element/Matrix在功能上更复杂，也更注重安全，同时还能够在不同服务器间互联，但从我的体验来说，Matrix这一套使用下来还是多多少少有一些恼人的Bug，十分影响体验；而IRC赢就赢在了功能简单，虽然打不过Matrix，但用起来没有问题，而且很纯粹。高情商：纯粹；低情商：简陋。总之，Matrix我也有在用，但是目前为止我个人更偏向IRC一些。但是IRC有一个致命的缺点，因为他太简单了，服务器甚至不会为你存储消息。也就是说，如果别人发消息时你没在线，那你就收不到消息了。这里我就不多费笔墨在介绍IRC协议上了。IRC协议作为一个已经发布了35年的经典协议，而且现今仍在使用，我想网络上一定有不少介绍和入门资料。Quassel既然IRC服务器不给我们存储消息，那我们就找一个服务器替我们挂机就是了。在众多IRC客户端中，Quassel是一个采用分离结构的IRC客户端。它分为Quassel Core和Quassel Client。其中Core的部分负责与IRC服务器交互，而Client则负责与Core交互。Core会一直在服务器上运行，与IRC服务器保持连接、接收指定频道的消息并将其存储到数据库中。而Client则运行在PC上，与Core交互，接收来自IRC的消息，也可以从数据库中调取以往的消息。如果你更倾向于在浏览器中使用IRC，你可以尝试诸如Convos等网页客户端。Convos支持在服务端持久化保存收到的消息，同时提供了一个十分易用的网页界面。我个人更喜欢在PC上以应用程序的方式使用IRC，所以我选择Quassel。安装废话不多说，我们不妨切入主题，直接说安装的部分。Quassel Core可以在没有任何依赖的情况下独立运行，此时数据存入SQLite数据库。这个数据库对于少量数据还可以应付，如果是长期使用积累下来的IRC消息，在数据量很大的情况下官方也有提示，使用SQLite数据库可能会导致拉取过往消息时出现超时或失败的情况。官方推荐使用PostgreSQL作为数据库。听人劝吃饱饭，我也决定使用PostgreSQL数据库。此外，我还想使用TLS加密Quassel Client与Core之间的通讯，我原本想使用Tailscale，但我又想使用公网访问，想来想去发现Quassel Core没办法在一个端口上提供两个不同的TLS证书，最终还是以公网访问为主，通过增加DNS的A记录指向Tailscale的IP来实现tailscale访问。具体的安装流程如下：安装Docker使用Docker安装PostgreSQL安装Quassel Core（在我的电脑上）安装Quassel Client并配置Quassel Core虽然在Docker中使用PostgreSQL数据库并不是生产环境的最佳实践，但从安全角度来说可能是最方便的。我在映射端口时可以直接把数据库端口映射到127.0.0.1上，而无需使用防火墙或修改数据库配置来实现。数据库的数据会映射到宿主机上，所以完全不需要担心数据丢失的问题。Docker我真是万万没想到，安装docker的环节都需要拿来说一下。我的服务器使用的是Ubuntu 2204LTS，安装Docker的过程遵照官方文档就是了，这个没什么可说的。意外发生在安装之后的验证阶段：docker run hello-world这一条命令本是用来验证Docker已经安装成功并且能够正常运行的。可是我一个回车按下去，却得到了一行错误：docker: Error response from daemon: Get "https://registry-1.docker.io/v2/": dial tcp 44.205.64.79:443: connect: network is unreachable.不知道为什么，Ubuntu上安装docker的默认仓库是registry-1.docker.io，而这个仓库是不支持IPv6访问的，我的服务器又没有v4地址，那肯定会网络不可达。我去网络上搜索了一圈，发现Docker hub其实早就已经支持IPv6访问了。我们只需要修改/etc/docker/daemon.json，将镜像仓库设置为registry.docker.io就好了：{ "registry-mirrors": ["https://registry.docker.com"] }千万记得前面的https://，不然Docker daemon跑不起来。保存修改后重启Docker服务，再次运行那个命令，就可以看到Docker已经能够正常拉取镜像了。理论上也可以不进行修改，但每次拉取镜像时就需要指定仓库了：docker run registry.docker.com/library/hello-world会显得很麻烦PostgreSQL解决了Docker的问题，PostgreSQL就好办了：docker run -d \ --name quassel-postgres \ --restart always \ -p 127.0.0.1:5432:5432 \ -e POSTGRES_PASSWORD=【密码】 \ -e PGDATA=/var/lib/postgresql/data/pgdata \ -v /var/lib/postgresql/quassel-data:/var/lib/postgresql/data \ postgres:latest容器的默认用户名和数据库名都是postgres，密码则通过POSTGRES_PASSWORD设置。这里我将数据库的端口映射到了127.0.0.1，只有本机能够访问，足够安全。Quassel Core这里我们需要安装两个软件包：apt install quassel-core libqt5sql5-psql前者是Quassel Core本体，后者则用于支持PostgreSQL的支持。如果没有第二个软件包的话，在下面使用Client配置Core时会发现只能使用SQLite数据库。安装完成后我们还需要配置一下TLS证书。证书位于/var/lib/quassel/quasselCert.pem，其格式就是证书的key和certs拼接到一起：-----BEGIN EC PRIVATE KEY----- 私钥。。。 -----END EC PRIVATE KEY----- -----BEGIN CERTIFICATE----- 证书链。。。 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- 证书链。。。 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- 证书链。。。 -----END CERTIFICATE-----大概是这种样子，证书链的数量取决于你的CA，关键在于这个pem文件里要提供你的私钥、域名证书和用于整明域名证书的CA证书（ca-bundle）。配置好之后，重启quasselcore服务即可让证书生效。如果quassel core启动失败，那多半是你的pem文件有问题。关于证书的部分，我原本想使用两套证书，在100.64.0.0/10上提供Tailscale的证书，在其他接口上提供公网TLS证书，但后来我发现Quassel Core做不到。后来我又想，能不能让Tailscale和公网证书用一个key。我首先用tailscale生成一套证书，然后用这套证书的key生成csr，通过acme.sh等服务请求一个公网证书。但是安装acme.sh的时候我发现纯IPv6的服务器没办法访问Github。都2023年了，微软你在干什么啊。总之这个想法就此作罢。但是我还是希望使用Tailscale访问Quassel Core，所以我只能在公网DNS上添加一条A记录来指向Tailscale里的服务器。理论上来说我这套野路子应该是可行的（取决于客户端能不能从一堆合法的证书中找到正确的证书链），甚至还可以搞一个简单的自动化。但我比较懒，这条路就暂且告一段落。当然，最理想的情况就是Tailscale能够提供一个用于进行DNS-01验证的接口，这样我们就可以自己申请证书，在申请过程中同时验证Tailscale提供的域名和我们自己的域名，这样会更舒服一些。Quassel Client接下来在我的PC上安装客户端，连接到运行在服务器上的Core，默认端口号4242。第一次连接会有一个向导来帮助你配置Quassel Core的账户（用于验证连接到core的客户端）、存储后端（PostgreSQL）。接下来你可以配置一些IRC的身份、服务器和频道等。关于Quassel Client的使用，这里就不多说了，可以参考官方文档。这里说一下主题。默认情况下Quassel Client提供了一个亮色主题，但我个人更倾向于暗色主题。我搜索了一圈，发现也就Dracula主题还能用。在安装主题之后，还需要将窗口风格切换成Fusion，不然在设置窗口和其他窗口下会看起来怪怪的。Quassel Client支持Windows和MacOS，如果想要在移动端使用的话，安卓上可以考虑Quasseldroid，iOS人士就自求多福吧，我不熟。用量统计为了具体测量数据库磁盘用量的增长趋势，我写了一个简单的bash脚本来查询文件大小：#!/bin/bash while : do (du -sb /var/lib/postgresql/quassel-data && date +%s) | tee -a result.txt sleep 1200 # every 20 minutes done这个脚本每隔20分钟查询一次数据库占用的大小，并且将当时的时间戳一起追加到result.txt里。为了分析结果，我写了一段简单的kotlin程序来处理数据：import java.io.File object ResultCounting { @JvmStatic fun main(args: Array<String>) { val startTimestamp = 1685330000 println("\n".repeat(5)) File("result.txt").readLines() .chunked(2) .map { it[0].split("\t")[0].toLong() to it[1].toLong() } .forEach { println("${it.second - startTimestamp}\t${it.first}") } println("\n".repeat(20)) } }这段程序从startTimestamp为起点输出时间T和对应的数据量。打印出来的数据刚好可以复制粘贴到excel表格里。在Excel里面做一个图标，加一个线性的趋势线，趋势线的斜率就是平均每秒增加的字节数：这里可以看到一个比较大的转折点。这是因为刚开始加入了几个IRC服务器，什么频道都想看，所以一下子加了差不多得有30多个频道，每个频道的在线人数从几十到几百不等，消息也很多。那个时候差不多每秒增加60到70字节。后来意识到加入了太多频道，平时也不看消息，于是就退出了一些频道，只留下了每天会看的，我感兴趣的频道。比如Libera Chat的#linuxba和#opensuse之类的频道。两个阶段平均起来是每秒新增30字节的数据，但从后半段的图表来看，其实实际用量应该还会更低。结语这套配置我用了得有一周了，感觉下来还是挺不错的。从服务器资源占用方面来说，Quassel Core和PostgreSQL数据库加起来内存用了不到150MB（不愧是C++写的，换成Java的话1GB都不够塞牙缝的），CPU占用就更轻松一些了。我挂了三个服务器，每个服务器差不多都有10多个频道。后来退出了一些频道，CPU和内存占用就更小了。有一些服务器不支持同时登陆多个账号，而Quassel也恰巧解决了这个问题，多个Client能够同时连接到一个Core上收发消息。还是很不错的。-全文完-
【歪门邪道】使用Hetzner Storage Box代替Google Drive和DropBox
最近处于闲的长毛但又找不到合适的工作的阶段。最近要么就是出去骑车锻炼身体（然后回来吃稻香村的点心长肉），要么就是折腾折腾电脑，也没怎么写程序。前几天突然发现我常用的一个欧洲服务器提供商Hetzner推出了专注于存储的新产品，想来想去，发现其实还不错，就拿来准备替代我即将到期的Google云端硬盘。背景以前我一直是Google的忠实粉丝：使用Google搜索，看YouTube，在Google Play上消费，订阅Google One（Google云端硬盘），不过最近几年热度有所减弱。我几个月前看了一篇新闻，说一个外国人给自己女儿的私处病灶拍摄了一张照片发给家庭医生，被谷歌的AI判定为儿童色情，这位父亲的Google账号也因此被关停。对于像是Google、苹果和IBM这种有大公司病的企业，其实他们并不那么关心「你」作为一个用户对于他们有多大的价值，而他们也不在乎「你」为他们带来的利益，尤其是当「你」是个人用户并且你的案例是个例的时候。反正根据新闻报道，这大哥申诉了几个月也没能拿回他的Google账号，这意味着他的照片、联系人等数据从此一去不复返，同时由于他手机使用了Google Fi，他出门连流量都没得用。如果他还用Google Voice，那我建议他可以考虑重开了。类似的争议在苹果方面也有。跨区封号（中国居民使用美区账号，一旦被封几乎没有恢复的可能性）就不用说了；之前苹果说要推出一个AI来扫描用户的照片，从而防止儿童色情犯罪。这个做法一度成为风口浪尖，最后不得已被停止。看起来无论是什么公司，他们似乎都在以正义的名义不断地索求更多对用户数据的访问权限。有些是索求，有些则是强制拿来。这下中国经验推广到全世界了。在这个大家越来越不把用户当人的时代，我们个人用户有没有办法站着吃饭呢？有，但是得加钱。例如提供企业级云服务的AWS，他们家就保证了永远不会偷看用户数据，即便是具有版权争议的数据，只要没有收到版权投诉（大概率是使用AWS进行了文件分享，而非因为存储），他们就不会管你在上面存了什么。但是至于价格嘛，也是非常的企业级：最便宜的存储类具有12小时的访问延迟，每月每TB要1美元；访问这些数据需要发起恢复请求，这个请求是按照对象数和对象大小分别收费的；数据恢复后，除了要为原本的存储类继续付费，你恢复出来的用于访问的数据要存在其他存储类，这个存储类的费用同样也要支付；最后如果你要在AWS之外的地方访问这些数据，你还要支付90美元每TB的下载流量费。不过归根结底，这世界上没有100%的安全。云服务商也会无故封号（这里点名批评IBM混合云）；NAS的硬盘也可能在重建时坏掉；也有可能你的存储服务提供商的机房着火了，把你的数据和备份全部烧掉了；还有可能天上掉下来陨石，正好砸中了你家的NAS和这个地球上所有存有你数据的服务器、移动硬盘、U盘、手机等设备（陨石：精确制导，不用谢）。总之，100%的安全是不可能的，但是通过遵循良好的实践原则，我们可以把数据损失的风险与代价降到最低。例如普通用户使用移动硬盘存储他们珍贵的照片，若这块硬盘受到物理损伤，那么这里面的数据也就从此一去不复返了（我们称这种用户为「亡命之徒」）。但如果这位用户遵循321原则：这些照片一共有三个副本（1份原件2份拷贝）；分开放在至少两种不同的存储介质上，例如原件在移动硬盘，一份拷贝在一个U盘上，另一份在AWS的磁带上；并且把U盘寄存在父母家或公司。这样即便你的移动硬盘坏了，你还可以通过放在其他地方的U盘，或者AWS云服务恢复数据。如果AWS发生了生产事故，除了索要赔偿外，你还可以通过移动硬盘和U盘这两种介质补充备份。只要行动及时，321备份原则能够在很大程度上保证你的数据可用性。 安全提示 当然了，一份数据的拷贝越多，其泄露的风险就越大，例如公司/父母家被盗了，AWS被入侵等。因此在考虑数据备份的同时不要忘记加密。但如果后续失去了解密的手段（例如丢失密钥、忘记密码），那么很遗憾，你的数据就在那里，但你就是访问不了它。因此时常检查你的备份是一个好习惯。存储安全并不是「设置然后遗忘」这么简单。它是一个需要你持续付出精力去维护的成果。 基于此，我目前的数据全部都存放在Google云端硬盘上，好像也没什么其他的备份。看起来很危险的样子。这几年没出什么大事情我真的烧高香了。我的需求前面说了这么多，总结成一句话就是：我要花钱了。因为一些原因，家里有一个类似NAS的存储设备，但是它并不能24小时开机，实际上家里的电也不是很稳定，大约每个月都会遇到意外停电。总的来说，这个设备就是一个大的半离线存储池，上面存储了一些长期用不到的数据，例如说远古时代的照片，我看过的动漫、电影等不需要随时访问的数据。这些数据加起来大约有4TB。目前这些数据仅受UnRaid阵列保护，一旦出现意外，没有备份。经常访问的数据位于我的电脑和一块2TB的移动硬盘上。由于电脑上的存储比较紧缺，虽然有2TB，但是除了系统、各种虚拟机、越来越大的游戏等，实际剩下能存储文件的地方不多，因此需要临时周转一些大文件的时候我会用到移动硬盘。这些数据主要有下载了但还没看的番、骑车录制的影像（多半都会删掉，但需要我过一变看看有没有值得留下的 摔车 精彩瞬间）。这部分数据大约在3TB左右，没有冗余阵列保护，没有备份，属于是亡命之徒了。其次我还有一个24小时运行的工控机，它主要运行一些服务，例如旁路网关、BT下载等。产生的数据基本上在下载完成后我都会拷贝到我的笔记本上，因此无需备份。最后就是我的手机。这上面的数据主要就是照片、截图和表情包。除了照片之外剩下的数据无关痛痒，照片主要同步到Google Photos上。鉴于我取消了Google One的订阅，因此之后的可用空间就剩下15GB了。我需要定期从Google Photos下载同步到的数据，并存储到其他地方。但总的来说，这部分数据量不大，因为我不怎么拍照片。除了存储方面的需求，我还希望可以做好备份。由于现实条件比较紧张，因此我偏向于无需增加实体的备份方法，也就是说额外购买硬盘做冗余备份不在考虑之列；对应地，我需要按月支付云服务商来租用存储服务。这并不是最佳实践，但也满足了321原则：原件在本地，两份副本在两个云服务商处，这三个副本都位于不同的地区。设计方案这里我们来列举一下需要的软件和服务，以及大概的思路。软件方面Duplicati：支持Windows、Linux和macOS的备份软件。具有去重功能（我1GB多的桌面备份了几个版本之后只有不到600MB），支持WebDAV、FTP、SSH、S3等各种存储后端。开源免费。MountainDuck：在Windows和macOS上将WebDAV、SFTP、FTP、S3等存储后端挂载为硬盘，在Windows资源管理器或访达中访问。付费软件，大版本买断制，截至目前大版本号是4，许可证价格为39美元。CyberDuck：如果你不想付费，来自MountainDuck的开发者也开发了这款文件浏览工具，支持的协议与MountainDuck一样，只是不能在Windows资源管理器或访达中访问，但可以实现文件的浏览、下载、上传等操作。免费版本可以一直使用，但定期会有弹窗提示你考虑捐助开发者。捐助10美元及以上可以获得一个许可证，用来解除前述恼人的提示，同样地，也是买断制。RCLONE：一个命令行工具，支持在不同的存储后端之间复制、粘贴、移动、同步数据。支持的协议最为广泛，使用起来也不算复杂（大概吧）。服务方面Hetzner Storage Box：提供以FTP、FTPS、SFTP、WebDAV等多种方式访问的存储产品。AWS S3：AWS S3对象存储服务。其中Hetzner Storage Box不提供图形界面的文件浏览功能（类似Google云端硬盘的网页版），并且分享数据也比较困难（无法通过链接的形式分享文件）。但由于我不需要使用网页端，也没有朋友可以分享数据，因此Storage Box很适合我。如果你有这方面的需求，Hetzner提供了基于NextCloud的存储服务，叫Storage Share，本质上和你自己运行NextCloud是一样的，也支持WebDAV，但额外多了分享和网页端，同时NextCloud也有手机App，在易用性上更好。当然，价格也更贵一些（大约额外加价50%吧，5TB从10欧元涨到15欧元不到；10TB从21欧元涨到28不到；1TB的好像就贵了1欧元左右），但总体来说也还是比Google云端硬盘和DropBox便宜。设计思路UnRaid服务器上的数据暂且不备份，因为数据量大，比较贵，等我工作之后再说吧。手机上的照片同步到Google Photos之后，可以在网页端下载，也可以使用导出的方式获取所有照片。导出之后就可以当作普通数据存储到其他地方了。最关键的就是电脑上的数据了。由于本文想实现替代Google云端硬盘，因此主要有两方面需求：一个是备份重要的文件夹，如果可能的话应该留取多个版本；然后就是网盘，将一部分数据存放在远端，并通过挂载的方式随时存取。网盘部分的数据违反了321原则，因为它不存在本地原件，因此只有两份副本。但好处是它扩展了本地可用的存储，并且手机端通过支持WebDAV协议的文件管理器即可访问远端数据。关于备份，我使用了Duplicati，它提供了网页端的管理界面（默认只有本机能够访问），在设置上也简单明了，能够提供一个位置的不同版本的数据，以便在我后悔的时候及时恢复。Duplicati在备份过程中可以选择在本地加密，然后上传到远端。关于网盘，我是用MountainDuck将远端挂载为本地硬盘。它用起来其实和Google的客户端差不多，都是自动同步新增文件，按需下载并缓存远端文件。MountainDuck支持在远端建立加密的存储库，但需要使用同样的软件才可以解密并读取。 关于软件的易用性 MountainDuck的使用体验不如Google和DropBox的客户端细致，有时候会出现同一个文件需要上传多次、莫名其妙出现同步冲突的情况，也有时软件以为自己同步了，但远端文件长度是0，此时删掉本地缓存的话，文件就会丢失。虽然这是小概率事件，我也不清楚原因，但这就要求用户在写入时需要额外的检查（推荐使用7z等可校验格式，或者使用FastCopy等支持校验的软件），如果不想在写入时担惊受怕，可以考虑使用SFTP协议上传文件，然后使用MountainDuck将WebDAV挂载为只读。 以上的所有数据都通过WebDAV协议存储于Hetzner Storage Box上。而Hetzner Storage Box提供了快照功能，我设置了每天一次快照。但为了避免Hetzner无法访问，我还将Hetzner上面的数据定期同步到S3上。使用Rclone在一台服务器上配置好基于SFTP访问的Hetzner Storage Box和AWS S3的远端配置（为节省成本可以使用GLACIER_IR或其他归档存储类）。定期执行如下脚本：rclone -c -P sync hetzner-u316777: aws-us-east-1:skyblond-hetzner-u316777 --checkers 2 --retries 10以上命令是通过sync命令将hetzner远端的数据同步到aws上，使用MD5作为checksum检查文件是否更改，将会删除hetzner中不存在的文件，并写入新增的文件。如果想要增量备份，则可以考虑使用copy命令并通过生命周期配置定期删除老旧文件，以实现回收站功能。这里比较重要的一点是使用MD5作为checksum确认文件是否重复（-c标志）。因为S3远端再上传时，取决于文件大小，rclone会附带文件的MD5并存储于元数据中。因此只需要计算源文件的MD5即可确认是否需要更新。如果网盘中的文件不经常修改，那么同步完成之后就不会消耗太多流量。此外由于rclone不具有失败提醒的功能，所以我建议定期手动执行脚本，以便保证同步备份是有效的。关于后面的--checkers和--retries，前者用于限制计算MD5的线程数量，因为StorageBox会限制并发数，默认配置是8个，我MountainDuck占用一个，Duplicati占用一个，rclone主要进程占用一个，然后再来8个计算MD5的现成，肯定会导致失败。出现失败之后，通过后一个配置可以让rclone多尝试。 关于手把手教程 由于我比较懒，因此我不会在本文中提供手把手教学。如果我能一边读这些软件和服务的文档一边配置出我想要的效果，那么我相信屏幕前的你也一定可以。 关于在实践中发现的一点bug 我在使用中遇到一个关于Shell的文件名问题。Hetzner StorageBox使用了一个类似蜜罐环境的Shell用以限制用户可以进行的操作。这在Shared host上是可以理解并完全必要的，但该Shell环境在处理文件名时似乎有一些问题。具体的表现是我在将文件同步到AWS S3时，计算MD5的命令出现错误，根据返回代码判断是内存过大引发了OOM Kill。但是一般来说不应当如此，于是我仔细检查了命令，结果发现他们的Shell在处理形如(something) [something.pdf这种括号不匹配的文件名时就会出问题。我已经向Hetzner反馈了这个问题，但是将近半个月了还没有任何进展，我推测这个shell应该不是他们自己编写的，而是采用了一些开源产品，需要等待上游修复才行。当然，这些文件是我备份的Calibre文件夹，也好解决：要么打成压缩包，要么放回硬盘上用Duplicati备份。 那么，代价是什么呢？我换到这种方案已经有大约一个月了。从经济上来说，Hetzner提供的Storage Box就算是加上S3的费用，也要比Google云端硬盘和DropBox提供的方案要便宜。具体来说是这样的：Google云端硬盘的2TB档提供49.995美元每年每TB的价格，上传下载不限；隔壁DropBox的2TB档则是59.94美元每年每TB；而Hetzner的1TB档提供38.16美元每年每TB的价格（需要考虑欧元汇率，因为Hetzner使用欧元结算）。加上S3的存储，我使用了最便宜的Deep Archive存储层，每年每TB价格是12美元。S3的同步费用主要是PUT和GET请求，分别用于数据上传和MD5查询。对于查询请求，每百万个对象0.4美元，上传则是每万个对象0.5美元。若提前删除，还需要支付额外的存储费用（即最短存储期限），我建议每隔180天或90天备份一次，这样可以避免支付太多的存储费用。如果发生意外，我需要从S3上恢复全部数据，则一次的费用是：生命周期转换费用0.5美元每万个对象，3.84美元每TB每5天（假设恢复的文件5天后自动删除），90美元每TB的数据传输费用。因此恢复一次的费用大约在100美元左右。虽然一次数据恢复的成本很高，但是相比之前只是用Google云端硬盘或DropBox，如果被封号且申诉失败，届时连花钱买自己的数据都不可能。此外，加上S3的存储费用，Hetzner的1TB档年度存储成本已经和Google云端硬盘持平了，但如果考虑最大的20TB档，光是存储就可以降到25美元每年每TB，直接干爆Google。但是话虽这么说，用户体验并不只是存储单价，还有网络。谷歌在世界各地都有数据中心（中国和朝鲜除外），而Hetzner的Storage Box只能从德国机房访问。虽然相比Google可以裸连，但速度实在是不敢恭维：不到100KB/s，是的，所以无论如何都还是得挂代理。而由于服务器在德国，因此香港、日本、美国等常用地区的代理并不能发挥出最佳效果，下载速度只有10MB/s左右；使用德国地区的代理则能够达到20MB/s的下载速度。至于上传？我家4MB/s的小水管无论是谷歌还是Hetzner都能被跑满，无所谓了。后记不使用现成的商品，就意味着要自己折腾。自己折腾就意味着更多的麻烦事，更少的文档，以及更多的时间成本。本文的意图在于使用自己的方案平替之前依赖的谷歌服务。我想今后工作之后，经济状况不一样了，可能还会有新的解决方案。对于我来说，数据掌握在自己手里当然是最好的，所以我的终极方案可能会是使用TrueNAS来做存储池，然后使用其他软件来提供服务。当然，云服务的一个好处就在于实时在线，如果完全靠自己来实现备份321原则的话，恐怕成本会很高。但是借助云服务就不一样：自己家一份数据，单位或亲戚家里一份备份，最后在云服务上备份一份。 当然，以上都是后话，截至目前，在「如无需要勿增实体」的基本原则下，这篇文章所记载的方法应该是（对我来说）最稳妥的数据存储方案了。此外这篇文章主要使用WebDAV和SFTP两种协议访问存储后端。如果没有使用rclone的需求，那么其他任何WebDAV协议都可以配合MountainDuck和Duplicati工作。使用SFTP就是因为他可以在上传前计算MD5，这样就可以直接和S3远端确认数据是否有变更，而不需要每次重新传输大量数据——也就是说，你不在乎流量和带宽的话，SFTP并不是rclone的必选项。推广最后的最后，Hetzner Cloud（主营业务是VPS）有一个推广服务。如果您愿意使用我的推广，请通过如下链接注册Hetzner Cloud，注册后您会收到20欧元的点数，可用于支付Hetzner家的VPS；当您额外消费10欧元后，我也会收到10欧元的点数作为回馈：https://hetzner.cloud/?ref=XeiXFN7QIPaG遗憾的是Hetzner Robot（主营业务是独立服务器、Storage Box）并没有类似的推广业务，可能是因为这类业务真的没有可以送点数的空间。-全文完-