]> git.notmuchmail.org Git - notmuch-wiki/blob - remoteusage/124.mdwn
fb016788541136edc19f0b799458b7ccd1562649
[notmuch-wiki] / remoteusage / 124.mdwn
1 ## Remoteusage without password-free login requirement
2
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.
6
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.
13
14 At the end of this document there is information for some possible ways
15 how master ssh connection can be done.
16
17 ## The script
18
19 Write the following code to a file, for example `remote-notmuch.sh`.
20
21         #!/bin/bash
22
23         set -eu
24         # To trace execution, uncomment next line:
25         #BASH_XTRACEFD=6; exec 6>>remote-errors; echo -- >&6; set -x
26
27         : ${REMOTE_NOTMUCH_SSHCTRL_SOCK:=master-notmuch@remote:22}
28         : ${REMOTE_NOTMUCH_COMMAND:=notmuch}
29
30         readonly REMOTE_NOTMUCH_SSHCTRL_SOCK REMOTE_NOTMUCH_COMMAND
31
32         SSH_CONTROL_ARGS='-oControlMaster=no -S ~'/.ssh/$REMOTE_NOTMUCH_SSHCTRL_SOCK
33         readonly SSH_CONTROL_ARGS
34
35         printf -v ARGS '%q ' "$@" # bash feature
36         readonly ARGS
37
38         if ssh -q $SSH_CONTROL_ARGS 0.1 "$REMOTE_NOTMUCH_COMMAND" $ARGS
39         then exit 0
40         else ev=$?
41         fi
42
43         # continuing here in case ssh exited with nonzero value
44
45         case $* in
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 ;;
52         esac
53
54         # fallback exit handler; print only to stderr...
55         exec >&2
56
57         if ssh $SSH_CONTROL_ARGS -O check 0.1
58         then
59          echo " Control socket is alive but something exited with status $ev"
60          exit $ev
61         fi
62
63         echo " See`sed '1d;2d;s/.//;q' "$0"` for help"
64         exit $ev
65         #eof
66
67 Note the `0.1` in ssh command line. It is used to avoid any opportunistic
68 behaviour ssh might do; for example if control socket is not alive ssh
69 would attempt to do it's own ssh connection to remote ssh server. As
70 address `0.1` is invalid this attempt will fail early.
71
72 ## Test
73
74 Easiest way to test this script is to run the pre-made ssh connection
75 using the following command line:
76
77         ssh -M -S '~'/.ssh/master-notmuch@remote:22 [user@]remotehost sleep 600
78
79 (replace `[user@]remotehost` with your login info). Doing this the
80 above wrapper script can be run unmodified. After the above command has
81 been run on **one terminal**, enter `chmod +x remote-notmuch.sh` in
82 **another terminal** and then test the script with
83
84         ./remote-notmuch.sh help
85
86 Note that the '~' in the ssh command line above is inside single quotes
87 for a reason. In this case shell never expand it to `$HOME` -- ssh does
88 it by not reading `$HOME` but checking the real user home directory
89 from `/etc/passwd`.  For security purposes this is just how it should
90 be.
91
92 ## Tune
93
94 The path `'~'/.ssh/master-notmuch@remote:22` might look too generic to be
95 used as is as the control socket after initial testing (but it can
96 be used). It is presented as a template for what could be configured
97 to `$HOME/.ssh/config`. For example:
98
99         Host *
100             ControlPath ~/.ssh/master-%h@%p:%r
101
102 is a good entry to be written in `$HOME/.ssh/config`;
103 [[remoteusage|remoteusage]] uses the same. Now, let's say you'd
104 make your pre-made ssh connection with command
105
106         ssh -M robin@example.org
107
108 There are 3 options how to handle this with `./nottoomuch-remote.bash`:
109
110 1) Edit `./nottoomuch-remote.bash` and change `REMOTE_NOTMUCH_SSHCTRL_SOCK`
111    to contain the new value (being *master-robin@example.org:22* in this
112    case)
113
114 2) Make symlink:
115    `ln -sfT master-robin@example.org:22 ~/.ssh/master-notmuch@remote:22`
116
117 3) `REMOTE_NOTMUCH_SSHCTRL_SOCK` can be used via environment; like:
118
119       REMOTE_NOTMUCH_SSHCTRL_SOCK=master-robin@example.org:22 ./nottoomuch-remote.bash help
120
121 ## Configure Emacs on the client computer ##
122
123 Add something like the following functions to your Emacs (general(*) or
124 notmuch specific) configuration files:
125
126     ;; this should work as backend function when copied verbatim
127     (defun user/notmuch-remote-setup (sockname)
128       (setq notmuch-command "/path/to/nottoomuch-remote.bash")
129       (setenv "REMOTE_NOTMUCH_SSHCTRL_SOCK" sockname)
130       ;; If you use Fcc, you may want to do something like this on the client,
131       ;; to Bcc mails to yourself (if not, remove in your implementation):
132       (setq notmuch-fcc-dirs nil)
133       (add-hook 'message-header-setup-hook
134                 (lambda () (insert (format "Bcc: %s <%s>\n"
135                                            (notmuch-user-name)
136                                            (notmuch-user-primary-email))))))
137
138      ;; this is just an example to configure using "default" master socket
139      (defun user/notmuch-remote-default ()
140        (interactive)
141        (user/notmuch-remote-setup "master-notmuch@remote:22")
142
143      ;; usage example2: set USER & HOST1 according to your remote...
144      (defun user/notmuch-remote-at-HOST1 ()
145        (interactive)
146        (user/notmuch-remote-setup "master-USER@HOST1:22")
147
148      ;; ... you probably got the point now -- add relevant funcs to your config
149      (defun user/notmuch-remote-at-HOST2 ()
150        (interactive)
151        (user/notmuch-remote-setup "master-USER@HOST2:22")
152
153 ... and if you want to activate your remote by default just call
154 `(user/notmuch-remote-setup "master-USER@HOST:22")` without function call
155 wrapper.
156
157 (*) general most likely being ~/.emacs
158
159 ## Creating master connection
160
161 **(Note: all the examples below use the default master socket written in**
162 `./nottoomuch-remote.bash` **for initial test easiness; remove/change the**
163 `-S '~'/.ssh/master-notmuch@remote:22` **in case you don't need it.)**
164
165 As mentioned so many times, using this solution requires one pre-made
166 ssh connection in "master" mode. The simplest way is to dedicate one
167 terminal for the connection with shell access to the remote machine:
168
169         ssh -M -S '~'/.ssh/master-notmuch@remote:22 [user@]remotehost
170
171 One possibility is to have this dedicated terminal in a way that the
172 connection has (for example 1 hour) timeout:
173
174         ssh -M -S '~'/.ssh/master-notmuch@remote:22 [user@]remotehost sleep 3600
175
176 The above holds the terminal. The next alternative puts the command in
177 background:
178
179         ssh -f -M -S '~'/.ssh/master-notmuch@remote:22 [user@]remotehost sleep 3600
180
181 If you don't want this to timeout so soon, use a longer sleep, like 99999999
182 (8 9:s, 1157 days, a bit more than 3 years).
183
184 A more "exotic" solution would be to make a shell script running on remote
185 machine, checking/inotifying when new mail arrives. When mail arrives it
186 could send message back to local host, where a graphical client (to be written)
187 pops up on display providing info about received mail (and exiting this
188 graphical client connection to remote host is terminated).
189
190 ## Troubleshooting
191
192 If you experience strange output when using from emacs first attempt to just
193 run
194
195         ./remote-notmuch.sh help
196
197 from command line and observe output. If it looks as it should be next uncomment
198 the line
199
200         #BASH_XTRACEFD=6; exec 6>>remote-errors; echo -- >&6; set -x
201
202 in `./remote-notmuch.sh` and attempt to use it from emacs again -- and then
203 examine the contents of `remote-errors` in the working directory emacs was
204 started.