理解 Keybase 文件系统

(关于 KBFS 更温和的介绍,请参阅我们的 发布公告。)

概览

Keybase 文件系统 (KBFS) 是一个具有端到端加密和全局命名空间的分布式文件系统。KBFS 代码是 开源的

“分布式”意味着您可以从任何设备访问它。

“文件系统”意味着没有同步模型——文件按需流式传输进出。除其他事项外,这意味着默认情况下,KBFS 上的文件不会永久占用您设备上的空间。(KBFS 确实使用本地磁盘存储临时和瞬态数据;有关更多详细信息,请参阅下面的“本地磁盘使用策略”部分。您也可以选择对某些文件夹或文件进行永久本地磁盘存储;有关更多详细信息,请参阅下面的“同步数据以供离线访问”部分。)

“端到端加密”意味着存储在 KBFS 中的所有数据都具有保证的完整性和身份验证,并在需要时具有机密性,并且只有预期的读写者才能操作数据。特别是,我们 (Keybase) 无法更改、读取甚至知道您的私有文件的名称。

“全局命名空间”意味着 KBFS 上的每个文件都有一个唯一的路径,无论您从哪个设备访问它。

Keybase 命名空间

Keybase 路径的形式为 /keybase/public/canonical_top_level_folder_name/subpath/keybase/private/canonical_top_level_folder_name/subpath/keybase/public 下的文件和文件夹已签名,/keybase/private 下的文件和文件夹除签名外还经过加密。

顶级文件夹 (TLF) 是 /keybase/public/keybase/private 的子目录。公开文件夹的规范名称形式为 writer1,writer2,...,私有文件夹的规范名称为 writer1,writer2,...writer1,writer2,...#reader1,reader2,...,其中每个写入者或读取者都是一个 Keybase 用户名,且写入者和读取者列表分别按字母顺序排列。TLF 的写入者既可以读取也可以写入该 TLF,而读取者只能读取。

TLF 的规范名称编码了哪些 Keybase 用户可以读取或写入它。对于公开文件夹,保证只有该文件夹的写入者曾写入过它。这是由 Keybase 客户端验证的,它会根据写入者的公钥检查该文件夹更新的签名。

对于私有文件夹,保证只有该文件夹的写入者曾写入过它,并且只有该文件夹的写入者和读取者可以读取它。这也由 Keybase 客户端验证。

有关 KBFS 加密设计的更多详细信息,请参阅 https://keybase.io/docs/kbfs-crypto。

您还可以通过非规范 TLF 名称路径访问 Keybase 文件。非规范 TLF 名称最简单的例子是写入者或读取者的顺序不是按字母排列的,但更有用的例子涉及使用声明 (assertions) 代替用户名。有关声明语法,请参阅 https://keybase.io/docs/command_line。

声明示例:

  • akalin 平凡地解析为 Keybase 用户 akalin
  • fakalin@twitter 解析为已证明拥有 Twitter 账户 fakalin 的 Keybase 用户。
  • fakalin@twitter+akalin@github 解析为已证明拥有 Twitter 账户 fakalin 以及 GitHub 账户 akalin 的 Keybase 用户。

在文件系统层面,每个非规范 TLF 名称都解析为指向规范 TLF 名称的符号链接。

安全模型

在高层次上,终端用户设备是受信任的,而 Keybase/KBFS/其他服务器是不受信任的。在桌面上,我们以当前用户身份运行所有 KBFS 进程,并使用操作系统级别的秘密存储,但我们不尝试防范同一用户或 root 拥有的其他进程。

KBFS 客户端不信任来自 Keybase 或 KBFS 服务器的任何数据,并根据相关用户的公钥验证任何接收到的数据。有关具体细节,请参阅 KBFS 加密文档。特别是,KBFS 服务器无法看到您(非公开)文件的内容或结构。

话虽如此,KBFS 服务器知道哪些用户可以访问哪些数据,并且只会向具有有效会话的 TLF 授权读取者提供数据。此外,它们只会向 TLF 的写入者提供历史(归档)数据,即使是公开 TLF 也是如此。

每个 TLF 由一个“隐式”Keybase 团队支持,访问该 TLF 所需的私钥由该团队管理;有关更多详细信息,请参阅 Keybase 团队文档。当您为账户配置新设备时,它会自动获得这些密钥的访问权限,从而获得 TLF 数据。当您吊销设备时,会为 TLF 创建一个新密钥并用于加密所有未来写入该 TLF 的数据,以确保该设备无法读取新数据。旧数据不会重新加密(尽管我们的服务器不会将其提供给已吊销的设备)。

文件系统语义

对于两个不同 TLF 中操作的相对顺序,没有任何保证。

TLF 最好被视为一系列线性变更。如果只有一个设备在 TLF 上操作,那么它所做的每个更改都会追加到此序列中,该序列称为“主分支” (master branch)。但是,如果有多个设备,则来自另一设备的更改可能会在当前设备的更改之前添加到主分支。在这种情况下,会分叉出一个该本地设备独有的单独分支。在这种状态(称为“暂存”,staged)下,本地设备上的操作通常对任何其他设备都不可见,尽管它们仍会在本地持久化(或者在关闭日志记录的情况下,在 KBFS 服务器上持久化),以防进程或设备重启。然后,后台进程会定期尝试将此分支合并到主分支中,并在必要时解决冲突。成功后,本地设备的更改将对其他所有人可见(但请参阅下面的冲突解决部分)。

在单个设备内,KBFS 的行为或多或少像一个普通(即符合 POSIX 标准)的文件系统,除了下面列出的例外情况。但是,很难对两个不同设备之间 TLF 中操作的相对顺序和可见性做出一般性陈述。但通常,一旦应用程序执行了一个成功发送到 KBFS 服务器的 fsync,所有先前写入的数据最终都将对第二个设备可见。请注意,文件写入纯粹是本地操作——设备上文件的写入在下一次同步或关闭之前对第二个设备是不可见的,而在同步之后,它们最终将对第二个设备可见。还有一个后台进程会频繁同步文件数据,以防应用程序没有同步或关闭文件。

默认情况下,KBFS 需要网络连接,除非正在读取的数据恰好缓存在内存中,否则无法进行离线读取。理论上,离线写入是可能的,并且会排队在您的本地磁盘上,直到网络连接可用。但是,写入通常涉及先读取,特别是为了更新包含文件的目录,因此在实践中,缺乏离线读取可能会阻碍离线写入。(有关离线访问的更多选项,请参阅下面的“同步数据以供离线访问”部分。)

持久性

出于性能原因,当 KBFS 收到写入调用(文件写入或目录修改)时,KBFS 会在内存中缓冲写入并成功响应,然后再将新数据持久化到磁盘或服务器上。这符合 POSIX 标准,但由于涉及延迟,KBFS 将数据保存在内存中的时间比大多数挂载的文件系统要长。默认情况下,它将数据保留最多 1 秒(或直到缓冲了 100 个操作,或 25 MB 的文件数据)。

任何 fsync 调用都会导致所有缓冲数据立即同步刷新到本地磁盘或 KBFS 服务器,具体取决于日志配置(见下文)。KBFS 目前没有任何针对同步单个文件的优化——它是全有或全无的。

应用程序可以在 TLF 内可读取的特殊 .kbfs_status 文件中检查当前缓冲的数据(例如,cat /keybase/private/me,you/.kbfs_statuskeybase fs read /keybase/private/me,you/.kbfs_status)。在该文件中,有一个 "DirtyPaths" 列表,指示哪些文件和目录的数据仅保存在内存中。

日志式写入 (Journaled writes)

默认情况下,KBFS 使用本地磁盘上的持久化 日志 (journal) 临时存储您对 TLF 所做的任何更改,直到它们可以保存到我们的服务器上。这使得写入速度更快,将您的网络延迟与文件系统延迟解耦,并为 KBFS 提供了将多个更改合并在一起并节省带宽的机会。这既适用于文件写入,也适用于目录更新。请注意,此日志中的所有数据在写入磁盘之前都经过加密。

使用日志意味着文件的同步或关闭保证数据已到达我们的 KBFS 服务器并将很快对其他设备可见。日志中的数据在后台刷新到服务器。当数据从日志上传时,您的 Keybase 应用图标将变为包含一个向上箭头。您可以使用 keybase fs uploads CLI 命令检查日志正在上传的更改的状态(以及上传完成的预计时间)。此外,在 .kbfs_status 文件(见上文)中,您还可以看到哪个本地目录正被用作日志;有关更多详细信息,请参阅下面的“本地磁盘使用策略”部分。

如果您想要更强的语义,或者如果您想避免即使是临时地使用任何磁盘空间来存储 KBFS 数据,您可以完全禁用日志记录,或者基于每个 TLF 禁用。例如,在 Linux 和 macOS 上,您可以执行以下操作:

  • 永久关闭未来访问的所有 TLF 的日志记录:echo 1 > /keybase/.kbfs_disable_auto_journals。(这不会影响可能已经在使用日志记录的 TLF;您必须手动禁用每一个。)
  • 关闭单个 TLF 的日志记录:echo 1 > /keybase/private/me,you/.kbfs_disable_journal。这仅在日志为空时有效。

与 Dropbox 等基于同步的系统相比,日志的使用在同一设备上的文件系统操作之间提供了更强的顺序保证,因为 KBFS 严格按照写入顺序上传数据。如果您知道一次只有一个设备写入特定的 TLF,这意味着在 KBFS 文件夹中运行像 git 这样的东西是相当安全的,即使其他设备可能同时从中读取,因为如果读取发生在错误的时间或者设备停顿或失败,您也不面临仓库损坏的风险。(当然,Keybase 也直接作为服务提供 加密 git 仓库,这也是基于 KBFS 的,但即使多个设备同时提交,也能提供通常的 git 安全保证。)

冲突解决

我们的冲突解决策略类似于 Dropbox,但因为我们拥有比他们更强的文件系统语义,所以我们可以用稍微不同的方式做事情,这更接近于两个用户并发更新本地 FS 时的行为(仅与边缘情况相关)。解决方案大致如下:

  • 当两个设备对同一目录进行不冲突的更改时,这些更改将被简单地合并。
  • 当两个设备写入同一文件时,“失败者”文件将被复制到一个新名称,并标记为执行写入的用户名称以及解决发生的时间。因此,如果两个用户都写入文件 a/b.txt,但用户 "bob" 输掉了比赛,解决后您应该会看到 a/b.txta/b.conflicted (bob’s macbook copy 2015-11-24).txt,其中 “bob” 是写入该文件的用户名,“macbook” 是 bob 写入该文件的设备的公开名称。KBFS 目前不尝试合并两个副本的内容,无论何种文件类型。
  • 当两个设备创建同名文件时,将发生与上述相同的解决。
  • 当两个设备创建同名目录时,它们将被智能合并(递归处理子项冲突)。
  • 如果一个设备创建目录,而另一个使用相同名称创建文件,则该文件始终重命名为上述提到的 .conflicted... 后缀,以便尽可能保留目录结构。
  • 与 Dropbox 不同,如果 "alice" 创建文件 a/foo,但 "bob" 执行 mv a b,解决后应该只有文件 b/foo。也就是说,目录的更新会跟随该目录的重命名。这与终端中的工作方式相同,如果您在一个目录中,而有人将该目录移走了。
  • 如果设备导致重命名循环,则使用符号链接解决。例如,"alice" 执行 mv b/ a/ 而 bob 执行 mv a/ b/。如果 alice 赢得了最初的比赛,解决方案将看起来像 a/b/a,其中第二个 a 是指向 ../ 的符号链接。
  • 一个奇怪的情况是当 alice 执行 mv a/ b/ 而 bob 并发执行 mkdir b。理想情况下,我们会合并这两个目录,但实现这一点非常棘手且昂贵,所以目前代码将其视为冲突。

陷入冲突模式的文件夹

在极少数情况下,如果 KBFS 在其冲突解决过程中存在 bug,或者设备上的资源压力阻止冲突解决完成,设备可能会永久陷入其文件夹的本地分支视图,而其他设备永远看不到该数据。如果是这种情况,TLF 中的 .kbfs_status 文件(见上文)的 ConflictStatus 将显示 IN_CONFLICT_AND_STUCK。如果您发现您的任何 TLF 处于此状态,请尽快使用 keybase log send 通知我们。

您可以使用 keybase fs clear-conflicts 命令将卡住的 TLF 恢复为“主”视图。这将把本地视图移动到一个新的只读路径名下,例如 /keybase/team/mycompany (local conflicted copy 2019-09-25),同时使“主”视图可以通过正常路径访问。然后可以手动将数据从卡住的视图复制到正常视图中。一旦恢复了任何所需的数据,就可以使用 keybase fs finish-resolving-conflicts 命令删除冲突视图(并回收相应的本地磁盘空间)。

偏离 POSIX 标准

权限完全由 TLF 名称决定,因此没有 POSIX 风格的权限。

不支持硬链接。支持符号链接,但只有当它们引用其他 KBFS 路径时才具有全局意义。

不支持 O_EXCLO_APPEND,尽管如果文件仅从单个设备操作,它们可能会起作用。特别是,任何进行文件锁定的东西(如 git)目前都不应从多个设备使用,并且应避免从多个设备向单个共享文件(例如日志文件)追加内容。我们将来可能会支持其中一个或两个。

KBFS 不支持 atime,因为那会将读取变成写入,并要求所有读取者也是写入者。此外,这会很慢。

典型的 POSIX 属性(如文件所有者、组和权限)在 KBFS 中意义不大。KBFS 将所有文件和目录的所有者设置为运行 KBFS 进程的本地用户的 UID。读写权限根据用户是否拥有 TLF 的读或写权限来设置。例如:

  • 可写私有 TLF 中的不可执行文件:0600 (-rw-------)
  • 可写私有 TLF 中的可执行文件:0700 (-rwx------)
  • 私有子目录:0700 (drwx------)
  • 用户有写权限的公开子目录:0700 (drwx------)
  • 只读公开子目录:0500 (-dr-x------)

请注意,TLF 本身的权限和所有权可能在访问 TLF 之前是不正确的。

任何更改所有者或组(例如,通过 chown)或设置权限(不包括可执行位)的请求都将显示为成功,但更改不会保存或传播到其他客户端。理想情况下,我们会让这些调用失败,但太多的应用程序(如 mvunzip)在这些调用失败时会彻底崩溃。此外,任何不会导致底层 KBFS 元数据实际更改的属性更改请求(例如,当可执行位已设置时再次设置它)都不会更新目录条目的相应 ctime。这违反了 POSIX,但对于某些常见工作负载(例如 rsync)来说,这是一项重要的优化。

符号链接可能指向 TLF 外部

Keybase 客户端允许指向 TLF 外部的符号链接。这是有意设计的,我们设想了各种很好的用例:

  • 您的公开文件夹的子文件夹,链接到您认可的朋友的公开文件夹
  • 存储指向所有您最喜欢的私有文件夹的私有链接
  • 完全指向 KBFS 外部到您认可的另一个全局文件系统的链接。例如,指向 IPFS 中的某物。

因此,您应该小心考虑盲目跟随(未注意到)由您不信任的人创建的符号链接的可能性。例如,如果您运行一个网络服务器并天真地提供某人 /keybase/public/ 文件夹中的内容——且您的服务器配置为跟随符号链接——用户可能会诱骗您将您自己的秘密文件服务出来。

存储、配额与历史

KBFS 服务器将您的数据存储在称为 (blocks) 的不透明 blob 中。TLF 中的文件和目录都存储为块,服务器无法分辨哪个块属于 TLF 中的哪个文件或目录。这些块中的数据是加密的,并且其大小会增加(即 填充,padding)以避免向我们的服务器泄露信息。

每个用户都有一个配额,以字节数表示。每当您写入文件或更改 TLF 的结构时,只有您更改的块会计入您的配额。每个块的完整大小(包括加密和填充)是计入配额的内容。请注意,由于 KBFS 内部数据结构的原因,更改文件或目录也会更改路径上一直回到 TLF 根目录的所有目录。因此,例如,如果您编辑 /keybase/private/you/a/b/c/foo 处的文件,您最终至少更改了五个块:/keybase/private/you 的 TLF 根目录块,aa/ba/b/c 的子目录块,以及 a/b/c/foo 的文件块。

您可以使用 keybase fs quota 检查您的配额使用情况,或者在 Linux 和 macOS 上使用 df。请注意,du 也可以工作(尽管可能非常慢)——但是,du 仅计算文件的明文大小,并且包括任何用户写入的数据,而不仅仅是您。

因新更改而弃用的块(例如,如果您覆盖文件的先前版本,或添加新的目录条目)将被标记为清理,每个客户端上的后台进程会在大约两周后清理这些旧块,尽管如果当前访问该文件夹的所有客户端都离线,这可能会延迟。这些弃用的块不计入您的配额。

时间旅行

您可以在旧的、归档的数据被清理之前的两周窗口内,查看并恢复 TLF 的旧版本数据。

每当您更改 KBFS TLF 中的某些内容(在根级别或任何子目录中)时,您都会创建该 TLF 的一个新版本,或 修订版 (revision)。每个修订版都分配有一个单调递增的 修订版号。您可以在 TLF 的 .kbfs_status 文件(见下文)的 Revision 字段中看到当前的修订版号。您还可以在同一文件的 LastGCRevision 字段中找到已清理(因此不再可访问)的最新文件夹版本的修订版号。查看 TLF 的旧版本时,您选择其中一个修订版进行浏览。它们是只读的,但您可以将数据从它们复制到 TLF 的当前副本中。

有多种查看旧数据的方法。在 keybase fs 命令套件中,您可以使用 lsstatread 命令访问旧数据,对于 cp 命令的源路径,可以使用以下标志:

  • -time: 指定数据从 KBFS 服务器对所有设备可用的日期和时间。它可以采用许多不同的格式,例如:

    • "Sun Jul 29 11:46:18 PDT 2018"
    • "July 29, 2018 11:46:18 PM PST"
    • "July 29, 2018"
    • "2018-07-18 13:13:43 +0800"

    请注意,如果没有给出时区,它将使用 UTC(而不是本地时区),以便在可能处于不同时区的用户/设备之间复制/粘贴命令时提供一致的行为。在月和日模糊的格式中(例如 "4/3/18" 或 "04-03-2018"),将被视为月在前,然后是日,如典型的美国日期格式。 * -reltime: 指定过去的相对时间,使用单位后缀,例如 "5m" 表示五分钟前,或 "5h3m2s" 表示五小时三分钟两秒前。有效的时间单位是 "ns", "us" (或 "µs"), "ms", "s", "m", "h"。当然,这将不可复制/粘贴,因为相对修订版可能会随当前时间而变化。 * -rev: 指定您正在浏览的 TLF 的确切修订版号,这对 Keybase 开发人员可能最有用。

例如,要查看五分钟前的 TLF(当前日期为 2018 年 7 月 29 日上午 11:51:00 旧金山时间):

$ keybase fs ls -reltime 5m /keybase/private/you
- 或 -
$ keybase fs ls -time "Sun Jul 29 11:46:00 PDT 2018" /keybase/private/you

您还可以直接在 KBFS 挂载点内浏览 TLF 的旧版本,使用 TLF 根目录下的这些特殊目录:

  • .kbfs_archived_time=<t>: 与上面的 -time 标志一样,您可以将 <t> 替换为任何时间。实际上,这只是充当指向该时间对应修订版的符号链接(见下文)。
  • .kbfs_archived_rev=<r>: 与上面的 -rev 标志一样,您可以在此处指定确切的修订版 <r>
  • .kbfs_archived_reltime=<r>: 与上述两个版本不同,这不是一个目录。它是一个文件,其内容包含对应于相对时间的修订版目录名称。这是为了避免跨时间的复制/粘贴问题。

对于上面的相同示例,您可以改为在挂载目录中执行此操作:

$ ls "/keybase/private/you/.kbfs_archived_time=Sun Jul 29 11:46:00 PDT 2018/
- 或 -
$ cd /keybase/private/you
$ ls `cat .kbfs_archived_reltime=5m`

如果您有兴趣浏览特定文件或目录的修订版,可以使用 keybase fs stat 命令列出它们。-show-archived 标志向您显示散布在整个归档历史中的文件的五个先前版本的统计信息。例如:

$ keybase fs stat --show-archived /keybase/private/you/tmp/foo
/private/you/foo
69403)  2018-08-01 11:22:50 PDT FILE    444 foo you
69393)  2018-08-01 11:22:29 PDT FILE    404 foo you
69387)  2018-08-01 11:22:20 PDT FILE    380 foo you
69369)  2018-08-01 11:21:53 PDT FILE    308 foo you
69295)  2018-08-01 11:20:00 PDT FILE    12  foo you

每行的第一个数字是修订版号。您可以将其传递给其他命令,例如 keybase fs readkeybase fs recover,以访问文件的该确切修订版。

另一个选项是 -show-last-archived 标志,它准确显示文件的最后五个修订版。如果需要,您可以使用它来迭代所有修订版。例如:

$ keybase fs stat --show-last-archived /keybase/private/you/foo
/private/you/foo
69403)  2018-08-01 11:22:50 PDT FILE    444 foo you
69402)  2018-08-01 11:22:48 PDT FILE    440 foo you
69401)  2018-08-01 11:22:47 PDT FILE    436 foo you
69400)  2018-08-01 11:22:45 PDT FILE    432 foo you
69399)  2018-08-01 11:22:44 PDT FILE    428 foo you
$ ./keybase fs stat --show-last-archived -rev 69399 /keybase/private/you/foo
/private/you/foo
69399)  2018-08-01 11:22:44 PDT FILE    428 foo you
69398)  2018-08-01 11:22:42 PDT FILE    424 foo you
69397)  2018-08-01 11:22:41 PDT FILE    420 foo you
69396)  2018-08-01 11:22:39 PDT FILE    416 foo you
69395)  2018-08-01 11:22:38 PDT FILE    412 foo you

keybase fs recover 提供了一个简单的辅助命令,用于将文件或目录的特定修订版恢复回 TLF。它采用与上述命令相同的 -time-reltime-rev 标志,并且只是用指定修订版的数据强制覆盖文件夹中的当前数据。它递归恢复目录。它不会删除旧版本目录中不存在的新文件。

KBFS 恢复的一个很好的属性是您可以恢复 TLF 的 一致 视图。也就是说,特定修订版中的所有文件版本都完全以那种方式、在同一时间存在。因此,可以保证如果您写入文件 a,然后写入文件 b,那么将来当您浏览 TLF 的修订版并看到该版本的 b 时,您也会看到在您写入 b 时存在的同一版本的 a。这对于恢复某些写入多个文件的应用程序类型(如数据库和存储库)可能很重要。

不过,如上所述,一个重要的注意事项是,在目录(包括 TLF 根目录本身)上使用 keybase fs recover 可能会留下您正在恢复的时间点不存在的新文件。如果需要对完整目录进行精确恢复,一种选择是使用 rsync --delete 通过文件系统的特殊 .kbfs_archived 目录进行恢复。

目前恢复数据的限制大约是过去两周,尽管我们将来可能会改进这一点。

本地磁盘使用策略

如上所述,KBFS 按需将数据流式传输进出您的设备,默认情况下不会将数据永久存储在您的磁盘上。但是,出于性能原因,KBFS 确实以两种不同的方式使用您的本地磁盘,根据存储本地主目录的磁盘分区上 当前可用 的磁盘空间量来限制其使用的空间量。(目前这仅适用于桌面设备,因为 KBFS 尚未在移动设备上可用。)所有存储到磁盘的数据首先都经过加密。

  • 临时本地写入:文件写入 KBFS 后,但在上传到服务器之前,它们将临时使用您设备上的磁盘空间——请参阅上面的“日志式写入”部分。我们将此使用限制为您可用磁盘空间的 85%,最大为 170 GB。一旦这些文件成功同步到 KBFS 服务器,它们就会被删除。
  • 磁盘瞬态缓存:KBFS 还在磁盘上的瞬态缓存中存储数据以提高性能。这限制为您可用磁盘空间的 10%,最大为 20 GB。如果其他应用程序开始使用更多磁盘空间,数据将自动从缓存中逐出以保持整体使用百分比。

如果您想调整这些限制,请参阅下面的“在资源受限系统上运行”部分。目前无法调整目录的位置。

此外,KBFS 进程会将日志文件写入您的 Keybase 日志目录。KBFS 日志总共限制为大约 400 MB。

同步数据以供离线访问

默认情况下,KBFS 不会将 TLF 数据永久存储在您的本地设备上。这是因为 KBFS 让您可以访问大量数据(例如,每个 Keybase 用户的公开文件!),因此在访问之前同步所有数据是不可行的。但这带来的代价是离线时无法访问数据。

KBFS 现在为您提供了一种选择加入的方式,将特定 TLF 或 TLF 内的特定子目录或文件中的数据“同步”到您的本地设备,以便即使在离线时也可以快速访问最新的数据版本。此过程的工作原理是将加密块存储在本地数据库中(类似于上面的“瞬态缓存”),并通过正常的 KBFS 挂载点使数据可用。它像 Dropbox 和其他服务那样以解密形式将数据“同步”到/从本地文件系统上的文件夹。当 KBFS 未运行时,同步的文件不可用。

目前,此功能仅在非移动设备上受支持,并且启用此功能的唯一方法是通过命令行。要启用同步,请使用 keybase fs sync enable 命令,如下所示:

# 同步整个 TLF
$ keybase fs sync enable /keybase/private/me

# 仅同步 TLF 的子目录
$ keybase fs sync enable /keybase/private/me,you/tax_docs

# 仅同步特定文件
$ keybase fs sync enable /keybase/team/mycompany/passwords.txt

还有一个 disable 子命令用于关闭同步(数据会在后台缓慢删除),以及一个 show 命令用于显示所有同步 TLF 或特定 TLF 的同步配置和进度(包括同步完成的预计时间)。

请注意,与上述瞬态缓存不同,KBFS 将根据需要使用尽可能多的本地存储来存储此数据。因此,如果您尝试同步的数据量超过了可用磁盘空间,您将填满磁盘。

针对文件同步的 GUI 和移动支持即将推出。

收藏夹

每个 Keybase 用户都有自己的“收藏夹”列表,显示在 /keybase/private/keybase/public 下。每当您访问新目录时(例如,您运行 ls /keybase/public/malgorithms@twitter),它都会以其规范名称(例如 /keybase/public/chris)添加到您的收藏夹列表中。

您可以使用 rmdir 针对规范 TLF 名称(例如 rmdir /keybase/public/chris)从收藏夹列表中删除条目,或者选择在 Keybase GUI 应用程序中忽略该文件夹。

挂载点

在 macOS 和 Linux 上,官方 Keybase 软件包支持一台计算机的多个本地用户同时使用 KBFS(假设登录到不同的 Keybase 账户,但这并非强制要求)。我们通过将 KBFS 挂载到每个用户文件系统的唯一位置来实现这一点。

  • macOS: 对于本地 macOS 账户名为 user 的用户,KBFS 挂载在 /Volumes/Keybase (user)
  • Linux: 如果用户(Linux 账户名为 user)在其环境中设置了 $XDG_RUNTIME_DIR,KBFS 挂载在 $XDG_RUNTIME_DIR/keybase/kbfs。否则,我们将其挂载在 /home/user/.config/keybase/kbfs

值得注意的是,我们不会像其他文件存储应用程序那样创建 ~/keybase 目录,因为 KBFS 是一个真正的挂载点,并让您可以访问团队和公开目录,因此它会减慢像备份软件、dufind 等爬取主目录的程序。(不幸的是,未设置 $XDG_RUNTIME_DIR 的 Linux 用户仍会遇到此问题。)

您可以使用 keybase status | grep mount 找出当前的挂载点。

根重定向器 (Root redirector)

那么,如果 /keybase 不是 KBFS 挂载点,这个神奇的路径是如何工作的呢?我们在那里挂载了所谓的 根重定向器,它会根据请求的用户显示指向每个用户挂载的不同符号链接。这允许我们的用户发送和发布指向 KBFS 文件的全局路径,这些路径对所有 Linux 和 macOS 用户(以及通过 keybase fs 命令集的 Windows 用户)都有效,同时支持多个本地用户。

请注意,在 macOS 10.15 或更高版本的新 Keybase 安装上,操作系统不允许在文件系统根级别创建新挂载点。在这种情况下,根重定向器改为挂载在 /Volumes/Keybase

我们认识到并非所有人都想运行根重定向器。特别是它以 root 权限在您的计算机上运行(在 Linux 上通过 root-suid 二进制文件,在 macOS 上通过 root 辅助进程),并且它还在本地文件系统的根目录下创建了一个目录,这两者都可能不受欢迎。因此,如果您更愿意直接通过每用户挂载点访问 KBFS,可以通过在 /etc/keybase/config.json 创建包含以下内容的根级别 Keybase 配置文件来关闭根重定向器:

{
  "disable-root-redirector": true
}

然后在 Linux 上,执行:

sudo killall keybase-redirector
sudo chmod a-s /usr/bin/keybase-redirector

在 macOS 上,您可以执行此操作:

keybase uninstall -c redirector

此后,即使升级,重定向器也应永久保持关闭状态。

自定义挂载点

如果您不喜欢默认挂载点位置,可以使用 keybase config set mountdir </a/better/location> 覆盖它,然后重启 Keybase。

根重定向器挂载点目前无法更改。

Windows

目前,一次只能有一位 Windows 用户使用 Keybase 和 KBFS。如果可能,我们会挂载到 K:\ 驱动器,如果需要,会选择另一个可用的驱动器号。您可以使用 keybase config set mountdir X: 自定义驱动器号。

在资源受限系统上运行

在台式机和笔记本电脑上,KBFS 大量使用内存来缓存最近读取的数据以提高性能。它还使用 CPU 和网络资源来 预取 您可能在不久的将来访问的数据,例如最近编辑的文件或刚请求数据的后续数据块。对于没有任何额外 RAM 或 CPU 可用的系统,这些优化权衡可能不是所希望的。从 Keybase 4.6.0 开始,我们允许用户将其台式机和笔记本电脑配置为以与移动设备相同的方式运行,从而禁用这些优化。为此,请运行以下命令:

keybase config set kbfs.mode constrained

然后重启 KBFS。可以使用以下命令恢复默认行为:

keybase config set kbfs.mode --clear

随后重启。

还可以通过 keybase config set 设置其他一些配置选项:

  • kbfs.block_cache.mem_max_bytes(整数,必须使用 -i 标志设置):内存数据缓存一次可容纳的最大字节数。此数字的默认值为 512 MB 或设备总 RAM 的 1/8,以较小者为准。减小此数字有助于减少 KBFS 的内存占用。
  • kbfs.block_cache.disk_max_fraction(浮点数,必须使用 -f 标志设置):本地磁盘可用字节数中可用于磁盘 瞬态 缓存的分数。如果使用率超过此分数,块将从缓存中逐出,直到再次符合该分数。此分数的默认值为 0.10(10%,如上所述)。
  • kbfs.block_cache.sync_max_fraction(浮点数,必须使用 -f 标志设置):本地磁盘可用字节数中可用于同步以供离线访问数据的分数。数据永远不会从该缓存中逐出;如果其大小超过配置的磁盘分数,则后台同步将失败,直到有更多空间可用。此分数的默认值为 1.00 (100%)。

KBFS 必须重启才能使任何这些选项生效。

调试

对于大多数用户,keybase log send 就足够了。这将打包一些日志文件并将其发送给 Keybase 管理员。日志文件可能包含有关您文件的元数据(大小等),尽管文件和目录名称已被混淆,无法从日志中推断出来。

对于更好奇的用户,在 macOS 上,访问 KBFS 日志的最简单方法是通过 [Console.app](https://en.wikipedia.org/wiki/Console_(OS_X))。在左侧 FILES 下,它应该位于 ~/Library/Logs 下的 keybase.kbfs.logkeybase.service.log 也可能有用。然后,您可以复制并粘贴显示行的一部分,或者拖放 “keybase.kbfs.log” 以附加整个文件,或者右键单击并选择“在 Finder 中显示”以找到实际文件。

有许多特殊的不可见 KBFS 文件,它们要么包含调试信息,要么打开和关闭 KBFS 设置。它们都以 .kbfs_ 开头,KBFS 不允许您创建带有该前缀的文件。

由于默认情况下未列出这些文件,因此您需要使用终端来访问这些文件。

从任何文件夹,均可访问以下文件:

  • .kbfs_error: 包含最近几个错误及其堆栈跟踪的列表。
  • .kbfs_metrics: 包含一些指标(主要是 RPC 相关)的列表。
  • .kbfs_profiles/: 包含表示 Golang profiles 的文件。

在 TLF 内,还可以访问以下附加文件:

  • .kbfs_status: 列出有关当前 TLF 的一些状态信息。
  • .kbfs_update_history: 显示此 TLF 所有修订版的 JSON 格式列表,包括何时执行了什么操作,以及由哪个授权的 TLF 写入者执行。这会从服务器获取所有修订版,对于具有长历史记录的 TLF 可能会非常慢。它包含大量内部调试信息,对于非 KBFS 开发人员来说可能难以阅读;制作更友好的版本是未来的工作。
  • .kbfs_fileinfo_XXX(其中 XXX 是该 TLF 子目录中的文件或目录的名称):显示有关给定文件的一些调试信息,包括谁最后声称编写了它(这在没有显式加密验证的情况下显示——验证是在 TLF 级别完成的,而不是在单个文件级别)。