]> Cypherpunks.ru repositories - nncp.git/blob - doc/integration.texi
Download link for 6.4.0 release
[nncp.git] / doc / integration.texi
1 @node Integration
2 @unnumbered Integration with existing software
3
4 Here is some examples of how you can solve popular tasks with NNCP,
5 making them store-and-forward friendly.
6
7 @menu
8 * Index files for freqing: FreqIndex.
9 * Postfix::
10 * Exim::
11 * Web feeds: Feeds.
12 * Web pages: WARCs.
13 * BitTorrent and huge files: BitTorrent.
14 * Downloading service: DownloadService.
15 * Git::
16 * Multimedia streaming: Multimedia.
17 @end menu
18
19 @node FreqIndex
20 @section Index files for freqing
21
22 In many cases you do not know exact files list on remote machine you
23 want to freq from. Because files can be updated there. It is useful to
24 run cron-ed job on it to create files listing you can freq and search
25 for files in it:
26
27 @example
28 0  4  *  *  *  cd /storage ; tmp=`mktemp` ; \
29     tree -f -h -N --du --timefmt \%Y-\%m-\%d |
30     zstdmt -19 > $tmp && chmod 644 $tmp && mv $tmp TREE.txt.zst ; \
31     tree -J -f --timefmt \%Y-\%m-\%d |
32     zstdmt -19 > $tmp && chmod 644 $tmp && mv $tmp TREE.json.zst
33 @end example
34
35 @node Postfix
36 @section Integration with Postfix
37
38 This section is taken from @url{http://www.postfix.org/UUCP_README.html,
39 Postfix and UUCP} manual and just replaces UUCP-related calls with NNCP
40 ones.
41
42 @strong{Setting up a Postfix Internet to NNCP gateway}
43
44 Here is how to set up a machine that sits on the Internet and that forwards
45 mail to a LAN that is connected via NNCP.
46
47 @itemize
48
49 @item You need an @ref{nncp-exec} program that extracts the sender
50 address from mail that arrives via NNCP, and that feeds the mail into
51 the Postfix @command{sendmail} command.
52
53 @item Define a @command{pipe(8)} based mail delivery transport for
54 delivery via NNCP:
55 @example
56 /usr/local/etc/postfix/master.cf:
57 nncp      unix  -       n       n       -       -       pipe
58   flags=FRqhu user=nncp argv=nncp-exec -quiet $nexthop sendmail $recipient
59 @end example
60
61 This runs the @command{nncp-exec} command to place outgoing mail into
62 the NNCP queue after replacing @var{$nexthop} by the receiving NNCP
63 node and after replacing @var{$recipient} by the recipients. The
64 @command{pipe(8)} delivery agent executes the @command{nncp-exec}
65 command without assistance from the shell, so there are no problems with
66 shell meta characters in command-line parameters.
67
68 Pay attention to @code{flags}, containing @code{R}, telling Postfix to
69 include @code{Return-Path:} header. Otherwise that envelope sender
70 information will be lost. Possibly you will also need somehow to
71 preserve that header on the receiving side, because @command{sendmail}
72 command will replace it. For example you can rename it before feeding to
73 @command{sendmail} with
74 @code{reformail -R Return-Path: X-Original-Return-Path: | sendmail}, or
75 extract with:
76
77 @verbatiminclude sendmail.sh
78
79 @item Specify that mail for @emph{example.com}, should be delivered via
80 NNCP, to a host named @emph{nncp-host}:
81
82 @example
83 /usr/local/etc/postfix/transport:
84     example.com     nncp:nncp-host
85     .example.com    nncp:nncp-host
86 @end example
87
88 See the @command{transport(5)} manual page for more details.
89
90 @item Execute the command @command{postmap /etc/postfix/transport}
91 whenever you change the @file{transport} file.
92
93 @item Enable @file{transport} table lookups:
94
95 @example
96 /usr/local/etc/postfix/main.cf:
97     transport_maps = hash:$config_directory/transport
98 @end example
99
100 @item Add @emph{example.com} to the list of domains that your site is
101 willing to relay mail for.
102
103 @example
104 /usr/local/etc/postfix/main.cf:
105     relay_domains = example.com ...other relay domains...
106 @end example
107
108 See the @option{relay_domains} configuration parameter description for
109 details.
110
111 @item Execute the command @command{postfix reload} to make the changes
112 effective.
113
114 @end itemize
115
116 @strong{Setting up a Postfix LAN to NNCP gateway}
117
118 Here is how to relay mail from a LAN via NNCP to the Internet.
119
120 @itemize
121
122 @item You need an @ref{nncp-exec} program that extracts the sender
123 address from mail that arrives via NNCP, and that feeds the mail into
124 the Postfix @command{sendmail} command.
125
126 @item Specify that all remote mail must be sent via the @command{nncp}
127 mail transport to your NNCP gateway host, say, @emph{nncp-gateway}:
128
129 @example
130 /usr/local/etc/postfix/main.cf:
131     relayhost = nncp-gateway
132     default_transport = nncp
133 @end example
134
135 Postfix 2.0 and later also allows the following more succinct form:
136
137 @example
138 /usr/local/etc/postfix/main.cf:
139     default_transport = nncp:nncp-gateway
140 @end example
141
142 @item Define a @command{pipe(8)} based message delivery transport for
143 mail delivery via NNCP:
144
145 @example
146 /usr/local/etc/postfix/master.cf:
147 nncp      unix  -       n       n       -       -       pipe
148   flags=Fqhu user=nncp argv=nncp-exec -quiet $nexthop sendmail $recipient
149 @end example
150
151 This runs the @command{nncp-exec} command to place outgoing mail into
152 the NNCP queue. It substitutes the hostname (@emph{nncp-gateway}, or
153 whatever you specified) and the recipients before execution of the
154 command. The @command{nncp-exec} command is executed without assistance
155 from the shell, so there are no problems with shell meta characters.
156
157 @item Execute the command @command{postfix reload} to make the changes
158 effective.
159
160 @end itemize
161
162 @node Exim
163 @section Integration with Exim
164
165 This section is unaltered copy-paste of
166 @url{https://changelog.complete.org/archives/10165-asynchronous-email-exim-over-nncp-or-uucp, Asynchronous Email: Exim over NNCP (or UUCP)}
167 article by John Goerzen, with his permission.
168
169 @strong{Sending from Exim to a smarthost}
170
171 One common use for async email is from a satellite system: one that
172 doesn't receive mail, or have local mailboxes, but just needs to get
173 email out to the Internet. This is a common situation even for
174 conventionally-connected systems; in Exim speak, this is a "satellite
175 system that routes mail via a smarthost". That is, every outbound
176 message goes to a specific target, which then is responsible for
177 eventual delivery (over the Internet, LAN, whatever).
178
179 This is fairly simple in Exim.
180
181 We actually have two choices for how to do this: bsmtp or rmail mode.
182 bsmtp (batch SMTP) is the more modern way, and is essentially a
183 derivative of SMTP that explicitly can be queued asynchronously.
184 Basically it's a set of SMTP commands that can be saved in a file. The
185 alternative is "rmail" (which is just an alias for sendmail these days),
186 where the data is piped to rmail/sendmail with the recipients given on
187 the command line. Both can work with Exim and NNCP, but because we're
188 doing shiny new things, we'll use bsmtp.
189
190 These instructions are loosely based on the
191 @url{https://people.debian.org/~jdg/bsmtp.html, Using outgoing BSMTP with Exim HOWTO}.
192 Some of these may assume Debianness in the configuration, but should be
193 easily enough extrapolated to other configs as well.
194
195 First, configure Exim to use satellite mode with minimal DNS lookups
196 (assuming that you may not have working DNS anyhow).
197
198 Then, in the Exim primary router section for smarthost
199 (@file{router/200_exim4-config_primary} in Debian split configurations),
200 just change @code{transport = remote_smtp_smarthost to transport = nncp}.
201
202 Now, define the NNCP transport. If you are on Debian, you might name this
203 @file{transports/40_exim4-config_local_nncp}:
204
205 @example
206 nncp:
207   debug_print = "T: nncp transport for $local_part@@$domain"
208   driver = pipe
209   user = nncp
210   batch_max = 100
211   use_bsmtp
212   command = /usr/local/nncp/bin/nncp-exec -noprogress -quiet hostname_goes_here rsmtp
213 .ifdef REMOTE_SMTP_HEADERS_REWRITE
214   headers_rewrite = REMOTE_SMTP_HEADERS_REWRITE
215 .endif
216 .ifdef REMOTE_SMTP_RETURN_PATH
217   return_path = REMOTE_SMTP_RETURN_PATH
218 .endif
219 @end example
220
221 This is pretty straightforward. We pipe to @command{nncp-exec}, run it
222 as the nncp user. @command{nncp-exec} sends it to a target node and runs
223 whatever that node has called @command{rsmtp} (the command to receive
224 bsmtp data). When the target node processes the request, it will run the
225 configured command and pipe the data in to it.
226
227 @strong{More complicated: Routing to various NNCP nodes}
228
229 Perhaps you would like to be able to send mail directly to various NNCP
230 nodes. There are a lot of ways to do that.
231
232 Fundamentally, you will need a setup similar to the UUCP example in
233 @url{https://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_manualroute_router.html,
234 Exim's manualroute manual}, which lets you define how to reach various
235 hosts via UUCP/NNCP. Perhaps you have a star topology (every NNCP node
236 exchanges email with a central hub). In the NNCP world, you have two
237 choices of how you do this. You could, at the Exim level, make the
238 central hub the smarthost for all the side nodes, and let it
239 redistribute mail. That would work, but requires decrypting messages at
240 the hub to let Exim process. The other alternative is to configure NNCP
241 to just send to the destinations via the central hub; that takes
242 advantage of onion routing and doesn't require any Exim processing at
243 the central hub at all.
244
245 @strong{Receiving mail from NNCP}
246
247 On the receiving side, first you need to configure NNCP to authorize the
248 execution of a mail program. In the section of your receiving host where
249 you set the permissions for the client, include something like this:
250
251 @example
252 exec: @{
253     rsmtp: ["/usr/sbin/sendmail", "-bS"]
254 @}
255 @end example
256
257 The -bS option is what tells Exim to receive BSMTP on @code{stdin}.
258
259 Now, you need to tell Exim that nncp is a trusted user (able to set From
260 headers arbitrarily). Assuming you are running NNCP as the nncp user,
261 then add @code{MAIN_TRUSTED_USERS = nncp} to a file such as
262 @file{/etc/exim4/conf.d/main/01_exim4-config_local-nncp}. That's it!
263
264 Some hosts, of course, both send and receive mail via NNCP and will need
265 configurations for both.
266
267 @node Feeds
268 @section Integration with Web feeds
269
270 RSS and Atom feeds could be collected using
271 @url{https://github.com/wking/rss2email, rss2email} program. It converts
272 all incoming feed entries to email messages. Read about how to integrate
273 @ref{Postfix}/@ref{Exim} with email. @command{rss2email} could be run in
274 a cron, to collect feeds without any user interaction. Also this program
275 supports ETags and won't pollute the channel if remote server supports
276 them too.
277
278 After installing @command{rss2email}, create configuration file:
279
280 @example
281 $ r2e new rss-robot@@address.com
282 @end example
283
284 and add feeds you want to retrieve:
285
286 @example
287 $ r2e add http://www.git.cypherpunks.ru/?p=nncp.git;a=atom
288 @end example
289
290 and run the process:
291
292 @example
293 $ r2e run
294 @end example
295
296 @node WARCs
297 @section Integration with Web pages
298
299 Simple HTML web page can be downloaded very easily for sending and
300 viewing it offline after:
301
302 @example
303 $ wget http://www.example.com/page.html
304 @end example
305
306 But most web pages contain links to images, CSS and JavaScript files,
307 required for complete rendering.
308 @url{https://www.gnu.org/software/wget/, GNU Wget} supports that
309 documents parsing and understanding page dependencies. You can download
310 the whole page with dependencies the following way:
311
312 @example
313 $ wget \
314     --page-requisites \
315     --convert-links \
316     --adjust-extension \
317     --restrict-file-names=ascii \
318     --span-hosts \
319     --random-wait \
320     --execute robots=off \
321     http://www.example.com/page.html
322 @end example
323
324 that will create @file{www.example.com} directory with all files
325 necessary to view @file{page.html} web page. You can create single file
326 compressed tarball with that directory and send it to remote node:
327
328 @example
329 $ tar cf - www.example.com | zstd |
330     nncp-file - remote.node:www.example.com-page.tar.zst
331 @end example
332
333 But there are multi-paged articles, there are the whole interesting
334 sites you want to get in a single package. You can mirror the whole web
335 site by utilizing @command{wget}'s recursive feature:
336
337 @example
338 $ wget \
339     --recursive \
340     --timestamping \
341     -l inf \
342     --no-remove-listing \
343     --no-parent \
344     [...]
345     http://www.example.com/
346 @end example
347
348 There is a standard for creating
349 @url{https://en.wikipedia.org/wiki/Web_ARChive, Web ARChives}:
350 @strong{WARC}. Fortunately again, @command{wget} supports it as an
351 output format.
352
353 @example
354 $ wget \
355     --warc-file www.example_com-$(date '+%Y%M%d%H%m%S') \
356     --no-warc-compression \
357     --no-warc-keep-log \
358     [...]
359     http://www.example.com/
360 @end example
361
362 That command will create uncompressed @file{www.example_com-XXX.warc}
363 web archive. By default, WARCs are compressed using
364 @url{https://en.wikipedia.org/wiki/Gzip, gzip}, but, in example above,
365 we have disabled it to compress with stronger and faster
366 @url{https://en.wikipedia.org/wiki/Zstd, zstd}, before sending via
367 @command{nncp-file}.
368
369 There are plenty of software acting like HTTP proxy for your browser,
370 allowing to view that WARC files. However you can extract files from
371 that archive using @url{https://pypi.python.org/pypi/Warcat, warcat}
372 utility, producing usual directory hierarchy:
373
374 @example
375 $ python3 -m warcat extract \
376     www.example_com-XXX.warc \
377     --output-dir www.example.com-XXX \
378     --progress
379 @end example
380
381 @node BitTorrent
382 @section BitTorrent and huge files
383
384 If dealing with @ref{Git}, @ref{Feeds, web feeds} and @ref{Multimedia,
385 multimedia} goes relatively fast, then BitTorrent and huge files
386 consumes much time. You can not wait for downloads finish, but want to
387 queue them after.
388
389 @url{http://aria2.github.io/, aria2} multi-protocol download utility
390 could be used for solving that issue conveniently. It supports HTTP,
391 HTTPS, FTP, SFTP and BitTorrent protocols, together with
392 @url{http://tools.ietf.org/html/rfc5854, Metalink} format. BitTorrent
393 support is fully-featured: UDP trackers, DHT, PEX, encryption, magnet
394 URIs, Web-seeding, selective downloads, LPD. @command{aria2} can
395 accelerate HTTP*/*FTP downloads by segmented multiple parallel
396 connections.
397
398 You can queue you files after they are completely downloaded.
399 @file{aria2-downloaded.sh} contents:
400
401 @verbatiminclude aria2-downloaded.sh
402
403 Also you can prepare
404 @url{http://aria2.github.io/manual/en/html/aria2c.html#files, input file}
405 with the jobs you want to download:
406
407 @example
408 $ cat jobs
409 http://www.nncpgo.org/download/nncp-0.11.tar.xz
410     out=nncp.txz
411 http://www.nncpgo.org/download/nncp-0.11.tar.xz.sig
412     out=nncp.txz.sig
413 $ aria2c \
414     --on-download-complete aria2-downloaded.sh \
415     --input-file jobs
416 @end example
417
418 and all that downloaded (@file{nncp.txz}, @file{nncp.txz.sig}) files
419 will be sent to @file{remote.node} when finished.
420
421 @node DownloadService
422 @section Downloading service
423
424 Previous sections tell about manual downloading and sending results to
425 remote node. But one wish to remotely initiate downloading. That can be
426 easily solved with @ref{CfgExec, exec} handles.
427
428 @verbatim
429 exec: {
430   warcer: ["/bin/sh", "/path/to/warcer.sh"]
431   wgeter: ["/bin/sh", "/path/to/wgeter.sh"]
432   aria2c: [
433     "/usr/local/bin/aria2c",
434     "--on-download-complete", "aria2-downloaded.sh",
435     "--on-bt-download-complete", "aria2-downloaded.sh"
436   ]
437 }
438 @end verbatim
439
440 @file{warcer.sh} contents:
441
442 @verbatiminclude warcer.sh
443
444 @file{wgeter.sh} contents:
445
446 @verbatiminclude wgeter.sh
447
448 Now you can queue that node to send you some website's page, file or
449 BitTorrents:
450
451 @example
452 $ echo http://www.nncpgo.org/Postfix.html |
453     nncp-exec remote.node warcer postfix-whole-page
454 $ echo http://www.nncpgo.org/Postfix.html |
455     nncp-exec remote.node wgeter postfix-html-page
456 $ echo \
457     http://www.nncpgo.org/download/nncp-0.11.tar.xz
458     http://www.nncpgo.org/download/nncp-0.11.tar.xz.sig |
459     nncp-exec remote.node aria2c
460 @end example
461
462 @node Git
463 @section Integration with Git
464
465 @url{https://git-scm.com/, Git} version control system already has all
466 necessary tools for store-and-forward networking.
467 @url{https://git-scm.com/docs/git-bundle, git-bundle} command is
468 everything you need.
469
470 Use it to create bundles containing all required blobs/trees/commits and tags:
471
472 @example
473 $ git bundle create repo-initial.bundle master --tags --branches
474 $ git tag -f last-bundle
475 $ nncp-file repo-initial.bundle remote.node:repo-$(date % '+%Y%M%d%H%m%S').bundle
476 @end example
477
478 Do usual working with the Git: commit, add, branch, checkout, etc. When
479 you decide to queue your changes for sending, create diff-ed bundle and
480 transfer them:
481
482 @example
483 $ git bundle create repo-$(date '+%Y%M%d%H%m%S').bundle last-bundle..master
484 or maybe
485 $ git bundle create repo-$(date '+%Y%M%d').bundle --since=10.days master
486 @end example
487
488 Received bundle on remote machine acts like usual remote:
489
490 @example
491 $ git clone -b master repo-XXX.bundle
492 @end example
493
494 overwrite @file{repo.bundle} file with newer bundles you retrieve and
495 fetch all required branches and commits:
496
497 @example
498 $ git pull # assuming that origin remote points to repo.bundle
499 $ git fetch repo.bundle master:localRef
500 $ git ls-remote repo.bundle
501 @end example
502
503 Bundles are also useful when cloning huge repositories (like Linux has).
504 Git's native protocol does not support any kind of interrupted download
505 resuming, so you will start from the beginning if connection is lost.
506 Bundles, being an ordinary files, can be downloaded with native
507 HTTP/FTP/NNCP resuming capabilities. After you fetch repository via the
508 bundle, you can add an ordinary @file{git://} remote and fetch the
509 difference.
510
511 Also you can find the following exec-handler useful:
512
513 @verbatiminclude git-bundler.sh
514
515 And it allows you to request for bundles like that:
516 @code{echo some-old-commit..master | nncp-exec REMOTE bundler REPONAME}.
517
518 @node Multimedia
519 @section Integration with multimedia streaming
520
521 Many video and audio streams could be downloaded using
522 @url{http://yt-dl.org/, youtube-dl} program.
523 @url{https://rg3.github.io/youtube-dl/supportedsites.html, Look} how
524 many of them are supported, including @emph{Dailymotion}, @emph{Vimeo}
525 and @emph{YouTube}.
526
527 When you multimedia becomes an ordinary file, you can transfer it easily.
528
529 @example
530 $ youtube-dl \
531     --exec 'nncp-file @{@} remote.node:' \
532     'https://www.youtube.com/watch?list=PLd2Cw8x5CytxPAEBwzilrhQUHt_UN10FJ'
533 @end example