Add note on $GPG_TTY
This commit is contained in:
parent
9a76d39524
commit
0fae583d4e
65
gists.org
65
gists.org
|
@ -776,6 +776,71 @@ Based on an answer at the [[https://emacs.stackexchange.com/a/77480/34645][Emacs
|
|||
(org-set-property "URL" url))
|
||||
#+end_src
|
||||
|
||||
* Using gpg-agent inside Emacs in Termux
|
||||
:PROPERTIES:
|
||||
:URL: https://emacs.ch/@bram85/111580555195721041
|
||||
:END:
|
||||
|
||||
Getting =gpg-agent= to work properly inside #termux and have it properly accessed from #emacs is a bit tricky.
|
||||
|
||||
The first issue is Android related: by default the agent will spawn as a top level process. This makes the process prone to be randomly killed by Android for memory management purposes, causing you to enter your passphrase more often than you may have configured.
|
||||
|
||||
Since I always run Emacs anyway, I chose to execute it from the Emacs init file, and passing a shell for the =--daemon= flag. Then it becomes a child process and won't be killed at random. It occupies a hidden buffer /*gpg-agent*/.
|
||||
|
||||
#+begin_src elisp
|
||||
(defconst my/termux-p (getenv "ANDROID_ROOT"))
|
||||
|
||||
(when my/termux-p
|
||||
(start-process "gpg-agent" " *gpg-agent*" "gpg-agent" "--daemon" "/bin/sh"))
|
||||
#+end_src
|
||||
|
||||
The second issue is 'knowing' the correct TTY such that =pinentry= shows up correctly inside Emacs (using =(setq epg-pinentry-mode 'loopback)=).
|
||||
|
||||
Outside Emacs, =pinentry= shows up in the right place because the GPG manual dictates to have your $GPG_TTY set to the output of the =tty= command, preferably from your shell initialization.
|
||||
|
||||
Inside Emacs, the correct TTY may change: run =tty= inside =eshell= and it may output /dev/pts/1. Open another real terminal, go back to =eshell= and run =tty= again: /dev/pts/2. So commands inside =eshell=, such as =gpg=, =ssh= and =git= cannot rely on a fixed $GPG_TTY that was set when starting Emacs. With the wrong value, the loopback pinentry fails and no passphrase is prompted from the minibuffer. Instead, the terminal that displays Emacs gets messed up.
|
||||
|
||||
One could fix it with the following inside =eshell=:
|
||||
|
||||
#+begin_src sh
|
||||
tty
|
||||
(setenv "GPG_TTY" "/dev/pts/2")
|
||||
gpg-connect-agent updatestartuptty /bye
|
||||
#+end_src
|
||||
|
||||
Which needs to be executed every time you're about to run something that might trigger a =pinentry= (including remote operations with Magit or TRAMP).
|
||||
|
||||
These steps can be performed from various hooks such that any subprocess gets the proper $GPG_TTY to which Emacs responds.
|
||||
|
||||
First a function to retrieve the =tty= output /synchronously/. If we don't wait, a =ssh= subprocess may have been spawned in the meantime with an outdated/incorrect $GPG_TTY.
|
||||
|
||||
#+begin_src elisp
|
||||
(defun my/get-pty ()
|
||||
(with-temp-buffer
|
||||
(let* ((process-connection-type t) ; force PTY allocation
|
||||
(proc (start-process "tty" (current-buffer) "tty")))
|
||||
(while (process-live-p proc)
|
||||
(accept-process-output proc 0.01 nil t)) ; wait for process to terminate
|
||||
(car (string-lines (buffer-string)))))) ; return process output
|
||||
#+end_src
|
||||
|
||||
And then a function we can use for hooks to actually update $GPG_TTY and make sure that SSH uses the correct display for a possible passphrase prompt.
|
||||
|
||||
#+begin_src elisp
|
||||
(defun my/hook/set-gpg-tty ()
|
||||
(setenv "GPG_TTY" (my/get-pty))
|
||||
(call-process "gpg-connect-agent" nil nil nil "updatestartuptty" "/bye"))
|
||||
#+end_src
|
||||
|
||||
Finally, I attached this hook in three places:
|
||||
|
||||
#+begin_src elisp
|
||||
(add-hook 'find-file-hook #'my/hook/set-gpg-tty) ; for TRAMP
|
||||
(add-hook 'magit-pre-start-git-hook #'my/hook/set-gpg-tty)
|
||||
(add-hook 'eshell-pre-command-hook #'my/hook/set-gpg-tty 0 t)
|
||||
#+end_src
|
||||
|
||||
Which covers my (potential) GPG/SSH usage within Emacs. Now, anytime a I perform a GPG / SSH operation, the $GPG_TTY variable is set properly and if needed, the passhprase prompt shows up in the minibuffer.
|
||||
* Meta
|
||||
** License
|
||||
|
||||
|
|
Loading…
Reference in a new issue