The default behavior of Crostini’s Debian Stretch container is to use a curses-based pinentry. This behaves strangely, in two different ways:

  1. Inherently, it shows the semi-graphical pinentry dialog in the terminal that has last called gpg-connect-agent updatestartuptty /bye. You can do this in .bashrc or similar, but if your habit is (like mine) to run many different terminals at once, you would need to call this whenever focus changes — otherwise the pinentry dialog will invariably come up in a random terminal. Of course this might still be inconvenient if pinentry is triggered from a UI application instead of on the console.

  2. If the pinentry dialog comes up in a terminal other than the one where the gpg process originated, it doesn’t work correctly anyway — the dialog is drawn on screen, but the command prompt (or whatever is running) remains active in the background and grabs input. I didn’t investigate this any further.

As far as I’m aware, there is no way of making this work other than somehow executing gpg-connect-agent updatestartuptty /bye every time a terminal window is focused. I didn’t want to go down that path and I was wondering why a graphical UI pinentry wasn’t used by default. But of course the standard container is just a very basic starting point and especially doesn’t come with loads of UI stuff installed.

Some wasted time…

The first UI pinentry I tried was pinentry-gnome3, and I immediately stumbled upon the next issue: when started from the command line, the error No $DBUS_SESSION_BUS_ADDRESS found, falling back to curses was shown. I have never had reason to look into the exact details of how dbus-daemon is started on Debian, and I suspect that the launch process is somehow out of whack on Crostini due to the fact that no conventional X session is started. I found that dbus-daemon was running, but the environment wasn’t configured correctly. As a workaround I configured terminator to start through dbus-run-session. I created /usr/local/bin/dbus-terminator:

#!/bin/sh
/usr/bin/dbus-run-session -- /usr/bin/terminator

Then I copied /usr/share/applications/terminator.desktop to /usr/local/share/applications and modified it to use a different name (DBUS-Terminator) and call dbus-terminator. This approach means that the entry appears in the Chromebook launcher automatically, and it configures DBUS_SESSION_BUS_ADDRESS correctly for the terminator session.

This made pinentry-gnome3 quite happy and it stopped showing the error message. However, it still wouldn’t work! I did notice at this point that gpg-agent was ignoring pinentry-program in ~/.gnupg/gpg-agent.conf — it always ran pinentry regardless of the entry there — but pinentry is just a configured alternative anyway, so I can update-alternatives --config pinentry to explicitly activate pinentry-gnome3. In spite of all that, it would always fall back to curses — no idea why, I stopped investigating at this point because I wasn’t fixed on the Gnome version of pinentry. I summarized all of the above in the hopes that somebody else may benefit from it!

Then what?

Now for an actual working solution: pinentry-qt. It turns out that this is a much easier choice. Once installed and activated through update-alternatives, it runs correctly without further trouble. I ended up thinking, if only I’d been able to find a simple solution when I searched, one that really works in Crostini… so I wrote this, hope it helps!