keybase / keybase/client

KBFS: broken integration with Finder on macOS < 12 & > 13: read this for a very kludgy workaround!

Open
#25,830 17 comments 10 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
9.2k
Forks
1.3k
Avg merge
12h 58m
Merged PRs (30d)
56

Description

Hello all,

After seven frustrating months without the ability to use the Finder integration on macOS Big Sur (currently at 11.7.9 (20G1426)), I finally found a workaround! I'm posting this here because every month someone complains about the integration of Keybase with Finder not working any longer with either very old or very new versions of macOS.

TL;DR (well, not really, the workaround has many steps to follow)

(way longer explanations on the comment below, if you really wish to know more)

The issue

In order for Keybase to mount KBFS as a 'regular' filesystem (as viewed by Finder), it uses Filesystem in Userspace (FUSE). This requires a kernel extension to be installed, and every version of macOS requires at least a recompilation of that extension in order to work in subsequent versions. You can grab FUSE from elsewhere, but for several reasons, Keybase bundles its own version.

Unfortunately, on Dec 12, 2022, @mmaxim, in an attempt to get a quick fix for macOS Ventura users, published, in quick succession, the commits #25335 and #25338. These fixed the issue for Ventura, while breaking it for essentially everybody else. @mmaxim has been strangely absent — he doesn't reply to messages and has barely committed anything during 2023 (and nothing related to Keybase). As far as we can publicly see, the last time he logged in to GitHub was back in March. @chrisnojima, who publishes at least one new commit every day (sometimes, even more than one), is apparently unaware of the Big Mess that @mmaxim left behind, or simply hasn't got time to do a real fix.

Partial list of issues filed from users affected with this problem

Some are directly related, others indirectly; the list still continues to be expanded.

If you've seen the following popup:

Keybase error message about failed kext install

then you're welcome to the club! You can see it's not very exclusive — lots of people have experienced exactly the same issue (and still are!) and are waiting for a fix. Here is a sample:

  • #24366 (the first report, on early November 2022)
  • #24376
  • #25043
  • #25130
  • #25226
  • #25263
  • #25271
  • #25294
  • #25297
  • #25321
  • #25328
  • #25333
  • #25379
  • #25452
  • #25486
  • #25510
  • #25526
  • #25632
  • #25637
  • #25718
  • #25729
  • #25729
  • #25767
  • #25770

Note: the above list may be very incomplete, I essentially followed a chain of issues that referred to each other; there might be many more who never made any reference — meaning that the author of the issue never bothered to search here — and thus I couldn't find it. But it should give the Keybase developers some pause for thought.

The only known workaround so far is to install a previous version of Keybase, in the hope that it will still bring the "old" Keybase FUSE port which still works with older kernels (as it should). The newer versions of Keybase will always overwrite any attempts of "fixing" the Keybase FUSE kernel extension (by replacing it with a working one); thus my kludgy workaround below.

Going 'back in time' to an old version may not be always possible, of course, and that's why I'm suggesting a very kludgy workaround, which should work with every future version of Keybase (I'm testing it with the nightly builds).

All that the Keybase devs need to do is to partially revert the changes made in early December 2022, keeping the old kernel support in, while adding support for newer kernels (just like the current macFUSE version does).

My kludgy workaround

I have found a very, very kludgy workaround for those who simply cannot live without this feature (myself included!) and would give an arm and a leg just to get it fixed.

Fair warning: this is not for the faint of heart. You might break everything (I didn't, but I guess I was lucky) and never be able to use Keybase again. Or even your Mac. I don't know, and I won't help you out if you have a problem; accept this solution 'as is' and don't complain if it bricked your Mac — you're doing this on your sole responsibility, and, who knows, you might not even get Apple to fix your Mac during the warranty time. Caveat utilitor.

That said, I'm not sure if this will work on anything but macOS Big Sur, because that's the version I've got. However, I'm pretty sure that the following macOS versions should work: 10.5, 10.6, 10.7, 10.8, 10.9, 10.10, 10.11, 10.12, 10.13, 10.14, 10.15, 10.16, 11.X. Anything above that... well, I cannot say, but at least the latest Keybase version works 'out of the box' with 12 and 13. You're out of luck with 14, though.

  1. The first step is simply to launch Keybase normally, let it complain showing the usual errors, etc. etc.
  2. Then, open Terminal (or whatever you like to use for command-line prompts) and change to the following directory: cd ~/Library/LaunchAgents/. There should be three files there, starting with keybase...
  3. Make a copy of keybase.kbfs.plist: e.g. cp keybase.kbfs.plist ~/Desktop (or wherever you prefer).
  4. Completely close Keybase. Make sure that nothing from Keybase is running; to be double-sure, do ps xaww | grep -i Keybase a few times, just to see if some process is lingering (and, if it is, force-quit it from the shell prompt with a kill -9 <pid>, or even with sudo kill -9 <pid>).
  5. You will now notice that the three files mentioned before are gone (that's why you made the copy of the only one that matters).
  6. With your code editor of choice (please, no rich text editor — stick to TextEdit in text-only mode, if you have nothing else to work with), open the copy you did before, and which should still be on ~/Desktop/keybase.kbfs.plist.
  7. This file should roughly look like this (with your username instead, of course):
<!-- It's not advisable to edit this plist, it may be overwritten -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>keybase.kbfs</string>
  <key>EnvironmentVariables</key>
  <dict>
    <key>KEYBASE_LABEL</key>
    <string>keybase.kbfs</string>
    <key>KEYBASE_SERVICE_TYPE</key>
    <string>launchd</string>
    <key>KEYBASE_RUN_MODE</key>
    <string>prod</string>
  </dict>
  <key>ProgramArguments</key>
  <array>
    <string>/Applications/Keybase.app/Contents/SharedSupport/bin/kbfs</string>
    <string>-debug</string>
    <string>-log-file=/Users/[[[YOUR USERNAME HERE]]]/Library/Logs/keybase.kbfs.log</string>
    <string>-runtime-dir=/Users//[[[YOUR USERNAME HERE]]]/Library/Caches/Keybase</string>
    <string>/Volumes/Keybase (/[[[YOUR USERNAME HERE]]])</string>
  </array>
  <key>KeepAlive</key>
  <true/>
  <key>StandardErrorPath</key>
  <string>/Users//[[[YOUR USERNAME HERE]]]/Library/Logs/keybase.start.log</string>
  <key>StandardOutPath</key>
  <string>/Users//[[[YOUR USERNAME HERE]]]/Library/Logs/keybase.start.log</string>
  <key>WorkingDirectory</key>
  <string>/tmp</string>
</dict>
</plist>

There might be some slight variants, but it should essentially be what's above.
8. Locate <key>ProgramArguments</key>, and, below, inside the <array>, you can see the parameters being passed to kbfs. We want to add a new parameter, right at the start. Just before <string>-debug</string>, add a new line with <string>-use-system-fuse</string>. Save it! Your file should now look like this:

<!-- It's not advisable to edit this plist, it may be overwritten -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>keybase.kbfs</string>
  <key>EnvironmentVariables</key>
  <dict>
    <key>KEYBASE_LABEL</key>
    <string>keybase.kbfs</string>
    <key>KEYBASE_SERVICE_TYPE</key>
    <string>launchd</string>
    <key>KEYBASE_RUN_MODE</key>
    <string>prod</string>
  </dict>
  <key>ProgramArguments</key>
  <array>
    <string>/Applications/Keybase.app/Contents/SharedSupport/bin/kbfs</string>
    <string>-use-system-fuse</string>
    <string>-debug</string>
    <string>-log-file=/Users/[[[YOUR USERNAME HERE]]]/Library/Logs/keybase.kbfs.log</string>
    <string>-runtime-dir=/Users//[[[YOUR USERNAME HERE]]]/Library/Caches/Keybase</string>
    <string>/Volumes/Keybase (/[[[YOUR USERNAME HERE]]])</string>
  </array>
  <key>KeepAlive</key>
  <true/>
  <key>StandardErrorPath</key>
  <string>/Users//[[[YOUR USERNAME HERE]]]/Library/Logs/keybase.start.log</string>
  <key>StandardOutPath</key>
  <string>/Users//[[[YOUR USERNAME HERE]]]/Library/Logs/keybase.start.log</string>
  <key>WorkingDirectory</key>
  <string>/tmp</string>
</dict>
</plist>
  1. To make double-sure that you haven't added anything you shouldn't, exit your text editor, and, from the shell, just run cat ~/Desktop/keybase.kbfs.plist and check that no weird characters have been added. It should be a pure ASCII file. If you're paranoid, you can even do a file ~/Desktop/keybase.kbfs.plist which should say exported SGML document text, ASCII text. The part that is important is the ASCII text. If you get data or binaryor Rich Text Format instead, then you have probably inserted some characters you shouldn't; either fix it or delete it and restart from scratch (i.e., back to 1.).
  2. Copy the file back, i.e. cp ~/Desktop/keybase.kbfs.plist ~/Library/LaunchAgents/. Confirm that it's in the right place!
  3. Make the file immutable with chflags uimmutable ~/Library/LaunchAgents/keybase.kbfs.plist. Check that this worked properly (the dollar sign is your prompt, do not copy & paste it by mistake):
$ /bin/ls -lO ~/Library/LaunchAgents/keybase.kbfs.plist
-rw-r--r--  1 myusername  staff  uchg 1217 26 Jul 11:53 /Users/myusername/Library/LaunchAgents/keybase.kbfs.plist

The crucial flag there is the uchg (which means unchangeable). So long as that flag is there, nobody can touch that file. Ever. Not even the superuser! You can try that on your own — sudo rm -f ~/Library/LaunchAgents/keybase.kbfs.plist should give an error. (If you wish to know more about what this does, you'll have to read it on the long version below.) Nevermind the date or the file size, they will obviously be different on your system.

Ok, this got rid of Keybase's own FUSE package. Now we have to install the 'correct' kernel extension for FUSE:

  1. If you don't have Homebrew to manage your packages, you should. Make sure it's properly installed and configured for your platform.
  2. Get a 'fresh' version of the old OSXFUSE package with brew install osxfuse. Ignore if brew complains about security issues and nags you to install the much more recent version, now rebranded macFUSE. Ignore it. You want OSXFUSE. I believe that the version bundled by Homebrew is 3.11.2.
  3. Once Homebrew considers that it has installed everything, it's time to load the kernel extension into its place. First, check the exact version of macOS that you're running; I usually check About this Mac from the Apple menu, or use sw_vers -productVersion from the shell, if you prefer. If you're on Big Sur, for instance, you should have something like 11.7.9.
  4. See what versions are supported by your release of osxfuse; note that Homebrew might give different results for different versions of macOS and/or architectures. Here is what I have in an Intel MacBook Pro (mid-2014) with Big Sur:
$ ls -la /Library/Filesystems/osxfuse.fs/Contents/Extensions/
total 0
drwxr-xr-x 15 root wheel 480 Jul 24 17:00 .
drwxr-xr-x  7 root wheel 224 Oct  4  2020 ..
lrwxr-xr-x  1 root wheel   4 Jul 24 17:00 10.10 -> 10.9
drwxr-xr-x  3 root wheel  96 Oct  4  2020 10.11
lrwxr-xr-x  1 root wheel   5 Jul 24 17:00 10.12 -> 10.11
lrwxr-xr-x  1 root wheel   5 Jul 24 17:00 10.13 -> 10.11
lrwxr-xr-x  1 root wheel   5 Jul 24 17:00 10.14 -> 10.11
lrwxr-xr-x  1 root wheel   5 Jul 24 17:00 10.15 -> 10.11
lrwxr-xr-x  1 root wheel   5 Jul 24 17:00 10.16 -> 10.11
drwxr-xr-x  3 root wheel  96 Oct  4  2020 10.5
drwxr-xr-x  3 root wheel  96 Oct  4  2020 10.6
lrwxr-xr-x  1 root wheel   4 Jul 24 17:00 10.7 -> 10.6
lrwxr-xr-x  1 root wheel   4 Jul 24 17:00 10.8 -> 10.6
drwxr-xr-x  3 root wheel  96 Oct  4  2020 10.9
lrwxr-xr-x  1 root wheel   5 Jul 24 17:00 11 -> 10.11

You wish to use the version that matches your version of macOS (note that sometimes kernel extensions work across versions, thus the symbolic links).
5. Now load the kernel extension. Cross your fingers! For instance, if your macOS version is 10.12, then you should run the following command:

$ kmutil load --bundle-path /Library/Filesystems/osxfuse.fs/Contents/Extensions/10.12/osxfuse.kext

Apple Silicon (ARM-based) Macs may need to follow further instructions. For your reference (in case of link rot), this is what Apple's manual says:

Kexts must be explicitly enabled for a Mac with Apple silicon by holding the power button at startup to enter into One True Recovery (1TR) mode, then downgrading to Reduced Security and ticking the box to enable kernel extensions.

Also note (if you have Apple Silicon) that the Keybase-provided FUSE kernel extension is a 'fat binary' supporting Intel and ARM64. Homebrew apparently ships the extensions only for whatever architecture you've got, but it's worth figuring out if that's true: if you do a file /Library/Filesystems/osxfuse.fs/Contents/Extensions/10.12/osxfuse.kext/Contents/MacOS/osxfuse, it should tell you what architecture it has been compiled for. Under my old Intel Mac, Homebrew just provided me with a 'thin' binary for x86_64; YMMV.
6. Check if it was properly loaded:

$ kmutil showloaded --bundle-identifier com.github.osxfuse.filesystems.osxfuse
No variant specified, falling back to release
Index Refs Address            Size       Wired      Name (Version) UUID <Linked Against>
  173    0 0xffffff7f9cd3f000 0x17000    0x17000    com.github.osxfuse.filesystems.osxfuse (3.11.2) FC635049-53AB-3DA8-8939-69D200ABD3C4 <8 6 5 3 1>

Again, what matters here is that you actually get that line displayed — numbers, etc, will be different.
7. If your macOS version doesn't have the kmutil command, you can use the (deprecated) kextload(instead of kmutil load) and kextstat -b (instead of kmutil showloaded --bundle-identifier).

All right! Now everything should be in place. Most people will require a reboot at this stage, others will have some luck merely by launching Keybase...

If you do a reboot, the first thing to check is if the kext has been properly loaded, using the command shown on 6. above. This ought to be working.

After a reboot, some magic should have happened, even before you start Keybase. You see, because we left the immutable file on ~/Library/LaunchAgents, the system launcher ought to have launched kbfs, the Keybase FileSystem daemon, which provides the 'bridge' between Keybase, Finder, and the FUSE kernel extension. You can check that it's running:

$ ps xawww | grep kbfs
   2789   ??  S      0:51.16 /Applications/Keybase.app/Contents/SharedSupport/bin/kbfs -use-system-fuse -debug -log-file=/Users/[[[YOUR USERNAME HERE]]]/Library/Logs/keybase.kbfs.log -runtime-dir=/Users/[[[YOUR USERNAME HERE]]]/Library/Caches/Keybase /Volumes/Keybase ([[[YOUR USERNAME HERE]]])

If you do look at the logs, you will see a lot of errors, which is to be expected: Keybase hasn't been launched yet, and that means no authentication was performed, thus kbfs cannot do anything until that happens.

You should also now get a new icon on the Preferences Pane, at the bottom, saying "FUSE". When you click on it, it should tell you the version of FUSE that has been installed by Homebrew. Do not click on update. I know it's tempting, but you do not want a different version — not until Keybase releases a permanent fix.

It is also possible that at some stage you'll encounter a popup like this one:

image

It might not be exactly that (I forgot to take a snapshot, so I'm reusing an image from a different context), but the purpose will be the same: authorise your Mac to run a kernel extension signed by Benjamin Fleischer, a legitimate Apple-approved developer, who has been doing versions of FUSE for Mac for many, many years. The box is a bit cryptic, and sometimes it's not easy to switch to the Preferences and click on the right place that gives permission to run the kernel extension. Or sometimes you have it all greyed out and have to click on the lock to be allowed to make any changes... and when you do that, the message to allow the extension to be run disappears! It's terrible, I know, but the alternative is to give permission via the command line instead:

$ /usr/sbin/spctl kext-consent add 3T5GSNBU6W

Why 3T5GSNBU6W? Well, that 'magic number' actually identifies Benjamin Fleischer — that's his 'Team ID' as registered by Apple. If you wish to see who else has registered Team IDs on your system, you can see them all here:

sudo sqlite3 /private/var/db/SystemPolicyConfiguration/KextPolicy "select * from kext_policy;"

It shouldn't surprise you to see Keybase, Inc. listed there as well, with the Team ID 99229SGT5K.

Note that this is basically just a list of extensions that are allowed to run; they aren't necessarily active (with the command above, the third column should show extensions allowed to run — 1 — and those that have been at some point installed in the system but aren't allowed to run any more — 0). Therefore, it doesn't matter if you have multiple versions or variants of FUSE for Mac on that list (including the one from Keybase!). What matters is that the one we want to run has permissions to do so.

All right, everything is in place now — it's time to start Keybase!

A lot of things will happen, most of which will be very confusing to follow, especially if you bother to look at the logs. What Keybase will now try to do is to change the immutable file to launch its own kernel extension instead; this will give some errors (possibly on the logs). Since we have our version of kbfs correctly configured to 'talk' to the correct kernel extension, Keybase won't be able to start its own — it will try, though, and get impossibly confused, as now two kbfs are running on the system, one of which non-operational. In one circumstance, Keybase even attempted to get my permission to reinstall the kernel extension, hoping to 'fix' the mess (according to its perspective); I allowed it to do so, confident that it couldn't do much about the immutable file — and, indeed, that's exactly what happened.

In my case, during this 'crash of titans', 'our' tweaked version of kbfs may shortly notice that it has been granted authentication to connect to Keybase's remote filesystem, and start happily to tell that to Finder. This might only last a few moments, though, because the 'flawed' kbfs instance will try to 'steal' that authentication for itself, and both will compete to get hold of Finder (potentially crashing it, BTW). Anyway, while it's fun to watch (with the logs open, no less!), it's not what we wish to have, so the trick is to put an end to it all, and this is accomplished simply with

$ killall -9 kbfs

(you can even do a sudo killall -9 kbfs for good measure)

What happens next is actually also amusing. Of course, when kbfs dies — all instances of it — your Finder access will not work with the remote folder, and, again, it's not impossible that Finder won't crash again. However, there is now a difference: the mechanism that launches kbfs is not Keybase, but rather the system's launcher, which is set to launch kbfs over and over again, every time it 'dies' for whatever reason. Keybase, therefore, doesn't interfere with the process any more — it knows that, sooner or later (usually sooner!), kbfs will be up again. Also, kbfs is a helper function for Finder — as you have noticed, during all these past few months, you could always access your files, either from the GUI (under Files) or from the command-line (with keybase fs (...) series of commands). It's only Finder that needs kbfs, so Keybase leaves it in peace.

Eventually, therefore, the system launcher will re-launch kbfs again — but this time, it only has our immutable file to load, and therefore it will cleanly launch kbfs connected to the correct kernel extension — and Finder will be immediately aware of the service!

In theory, this is something you only need to do once — possibly killing kbfs again after you install a newer version of Keybase, which might try to run its own installation script again and fight for the right to bind to Finder. In practice, I would guess that every now and then you will need to happily kill some processes, restart Keybase, or even reboot, in order to fix things. I've noticed some inconsistent behaviour after 'waking up' the PowerBook which had been in 'deep sleep'. Also, if you close Keybase (or even just the GUI) and start it again, it might trigger the conflicts once more.

If by any chance Keybase kicks your 'tweaked' kbfs out of the process list, and tries to launch its own untweaked version, then you can try doing the following:

# Repeat the next command as often as necessary, checking with `ps xawww | grep kbfs` that it's dead
$ killall kbfs
$ cd ~/Library/LaunchAgents
$ launchctl enable user/501/keybase.kbfs
$ launchctl load keybase.kbfs.plist
$ launchctl start keybase.kbfs.plist

Eventually, one of the last three commands will kick the 'correct' kbfs into place. Be prepared to do more frequent reboots, though; this hacky configuration may leave Finder unresponsive (as warned earlier) and utterly confused about what mounts are still valid; while sometimes Force Quit on Finder will work, other times you have no choice but to reboot.

As said in the very beginning — I told you that this was a kludgy workaround, right? 😸

There you go. That's all. The rest is reference material for those really interested in more information, and how I figured out this very crude and ugly way of 'fixing' things.

Oh, and make sure you send @mmaxim a few messages, asking him to revert the mess he did in December 2022.

(And I apologise for the length of this issue; there are simply way too many steps to take until it works)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read the macOS KBFS/Finder integration around the kbfs launch configuration and compare commits #25335 and #25338 first. Reproduce the reported failure on the affected macOS versions, then verify that the resulting FUSE behavior supports both older and newer systems without the manual plist workaround.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, macos
Domain
desktop-dev, operating-systems
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.