1 ## Remoteusage without password-free login requirement
3 This is alternative to [[remoteusage|remoteusage]] where password-free
4 login is not a requirement. See [[remoteusage|remoteusage]] page for
5 other requirements and general information.
7 This solution uses one pre-made ssh connection where the client is put
8 into "master" mode (-M) for connection sharing. The wrapper script then
9 uses the control socket created by this pre-made ssh connection for
10 its own connection. As long as master ssh connection is live, slave
11 can use it. Disconnecting master all future attempts to connect
12 from the script will fail.
14 At the end of this document there is information for some possible ways
15 how master ssh connection can be done.
19 Write the following code to a file, for example `remote-notmuch.sh`.
24 # To trace execution, uncomment next line.
25 #BASH_XTRACEFD=6; exec 6>>remote-errors; echo -- >&6; set -x
27 : ${REMOTE_NOTMUCH_SSHCTRL_SOCK:=master-notmuch@remote:22}
28 : ${REMOTE_NOTMUCH_COMMAND:=notmuch}
30 readonly REMOTE_NOTMUCH_SSHCTRL_SOCK REMOTE_NOTMUCH_COMMAND
32 SSH_CONTROL_ARGS='-oControlMaster=no -S ~'/.ssh/$REMOTE_NOTMUCH_SSHCTRL_SOCK
33 readonly SSH_CONTROL_ARGS
35 printf -v ARGS '%q ' "$@" # bash feature
38 if ssh -q $SSH_CONTROL_ARGS 0.1 "$REMOTE_NOTMUCH_COMMAND" $ARGS
43 # continuing here in case ssh exited with nonzero value.
46 'config get user.primary_email') echo 'nobody@nowhere.invalid'; exit 0 ;;
47 'config get user.name') echo 'nobody'; exit 0 ;;
48 'count'*'--batch'*) while read line; do echo 1; done; exit 0 ;;
49 'count'*) echo 1; exit 0 ;;
50 'search-tags'*) echo 'errors'; exit 0 ;;
51 'search'*'--output=tags'*) echo 'errors'; exit 0 ;;
54 # for unhandled command line print only to stderr...
57 if ssh $SSH_CONTROL_ARGS -O check 0.1
59 echo " Control socket is alive but something exited with status $ev"
63 case $0 in */*) dn0=${0%/*} ;; *) dn0=. ;; esac
64 echo "See $dn0/nottoomuch-remote.rst for more information"
69 Note the `0.1` in ssh command line. It is used to avoid any opportunistic
70 behaviour ssh might do; for example if control socket is not alive ssh
71 would attempt to do it's own ssh connection to remote ssh server. As
72 address `0.1` is invalid this attempt will fail early.
76 Easiest way to test this script is to run the pre-made ssh connection
77 using the following command line:
79 ssh -M -S '~'/.ssh/master-notmuch@remote:22 [user@]remotehost sleep 600
81 (replace `[user@]remotehost` with your login info). Doing this the
82 above wrapper script can be run unmodified. After the above command has
83 been run on **one terminal**, enter `chmod +x remote-notmuch.sh` in
84 **another terminal** and then test the script with
86 ./remote-notmuch.sh help
88 Note that the '~' in the ssh command line above is inside single quotes
89 for a reason. In this case shell never expand it to `$HOME` -- ssh does
90 it by not reading `$HOME` but checking the real user home directory
91 from `/etc/passwd`. For security purposes this is just how it should
96 The path `'~'/.ssh/master-notmuch@remote:22` might look too generic to be
97 used as is as the control socket after initial testing (but it can
98 be used). It is presented as a template for what could be configured
99 to `$HOME/.ssh/config`. For example:
102 ControlPath ~/.ssh/master-%h@%p:%r
104 is a good entry to be written in `$HOME/.ssh/config`;
105 [[remoteusage|remoteusage]] uses the same. Now, let's say you'd
106 make your pre-made ssh connection with command
108 ssh -M robin@example.org
110 There are 3 options how to handle this with `./nottoomuch-remote.bash`:
112 1) Edit `./nottoomuch-remote.bash` and change `REMOTE_NOTMUCH_SSHCTRL_SOCK`
113 to contain the new value (being *master-robin@example.org:22* in this
117 `ln -sfT master-robin@example.org:22 ~/.ssh/master-notmuch@remote:22`
119 3) `REMOTE_NOTMUCH_SSHCTRL_SOCK` can be used via environment; like:
121 REMOTE_NOTMUCH_SSHCTRL_SOCK=master-robin@example.org:22 ./nottoomuch-remote.bash help
123 ## Configure Emacs on the client computer ##
125 Add something like the following functions to your Emacs (general(*) or
126 notmuch specific) configuration files:
128 ;; this should work as backend function when copied verbatim
129 (defun user/notmuch-remote-setup (sockname)
130 (setq notmuch-command "/path/to/nottoomuch-remote.bash")
131 (setenv "REMOTE_NOTMUCH_SSHCTRL_SOCK" sockname)
132 ;; If you use Fcc, you may want to do something like this on the client,
133 ;; to Bcc mails to yourself (if not, remove in your implementation):
134 (setq notmuch-fcc-dirs nil)
135 (add-hook 'message-header-setup-hook
136 (lambda () (insert (format "Bcc: %s <%s>\n"
138 (notmuch-user-primary-email))))))
140 ;; this is just an example to configure using "default" master socket
141 (defun user/notmuch-remote-default ()
143 (user/notmuch-remote-setup "master-notmuch@remote:22")
145 ;; usage example2: set USER & HOST1 according to your remote...
146 (defun user/notmuch-remote-at-HOST1 ()
148 (user/notmuch-remote-setup "master-USER@HOST1:22")
150 ;; ... you probably got the point now -- add relevant funcs to your config
151 (defun user/notmuch-remote-at-HOST2 ()
153 (user/notmuch-remote-setup "master-USER@HOST2:22")
155 ... and if you want to activate your remote by default just call
156 `(user/notmuch-remote-setup "master-USER@HOST:22")` without function call
159 (*) general most likely being ~/.emacs
161 ## Creating master connection
163 **(Note: all the examples below use the default master socket written in**
164 `./nottoomuch-remote.bash` **for initial test easiness; remove/change the**
165 `-S '~'/.ssh/master-notmuch@remote:22` **in case you don't need it.)**
167 As mentioned so many times, using this solution requires one pre-made
168 ssh connection in "master" mode. The simplest way is to dedicate one
169 terminal for the connection with shell access to the remote machine:
171 ssh -M -S '~'/.ssh/master-notmuch@remote:22 [user@]remotehost
173 One possibility is to have this dedicated terminal in a way that the
174 connection has (for example 1 hour) timeout:
176 ssh -M -S '~'/.ssh/master-notmuch@remote:22 [user@]remotehost sleep 3600
178 The above holds the terminal. The next alternative puts the command in
181 ssh -f -M -S '~'/.ssh/master-notmuch@remote:22 [user@]remotehost sleep 3600
183 If you don't want this to timeout so soon, use a longer sleep, like 99999999
184 (8 9:s, 1157 days, a bit more than 3 years).
186 A more "exotic" solution would be to make a shell script running on remote
187 machine, checking/inotifying when new mail arrives. When mail arrives it
188 could send message back to local host, where a graphical client (to be written)
189 pops up on display providing info about received mail (and exiting this
190 graphical client connection to remote host is terminated).
194 If you experience strange output when using from emacs first attempt to just
197 ./remote-notmuch.sh help
199 from command line and observe output. If it looks as it should be next uncomment
202 #BASH_XTRACEFD=6; exec 6>>remote-errors; echo -- >&6; set -x
204 in `./remote-notmuch.sh` and attempt to use it from emacs again -- and then
205 examine the contents of `remote-errors` in the working directory emacs was