leafnode - NNTP server for small (dialup) sites
leafnode [-e] [-d spooldir] [-D debugmode] [-F configfile] [-v [...]]
Leafnode is a USENET package intended for small sites, where there are few users and little disk space, but where a large number of groups is desired.
The design of leafnode is intended to self-repair after problems, and to require no manual maintenance.
The leafnode program itself is the NNTP server. It is run from /etc/inetd.conf when someone wants to read news. The other parts of the package, fetchnews and texpire, are responsible for fetching new news from another server, and for deleting old news.
All options in this sections are valid for all leafnode programs.
|Switch spool directory from the compiled-in default /var/spool/news to spooldir.|
|Set debug mode. debugmode is a bit-wise OR of debug options, expressed as decimal number. It will log a lot of information via syslog to the "news" facility with priority "debug". See /etc/leafnode/config.example for a detailed description of how to set this parameter.|
|-e||Redirect logging from syslog to the standard error channel (stderr). This is useful for debugging and when using service supervisors such as Gerrit Pape’s runit or Daniel J. Bernstein’s daemontools.|
|Note: This option must be the first option for the leafnode program and it must not be merged with other options if you want to log initialization errors on stderr, too. Other programs such as fetchnews or texpire do not need this.|
|Read configuration from an alternative file instead of /etc/leafnode/config.|
|-v||Increase verbosity level. This option can be repeated for increased effect.|
|-V||Report leafnode version and exit.|
No network-level access control is supported. This is a deliberate omission: Implementing this is a job which should not be redone for each and every service.
I recommend that either firewalling or tcpd be used for access control.
All the files in /etc/leafnode must be readable, but not writable, by user "news".
/etc/inetd.conf contains the line which starts leafnode. It is strongly recommended to start leafnode as user news.
/etc/leafnode/config contains the configuration parameters for leafnode. See CONFIGURATION below.
/etc/leafnode/users contains the passwords if authenticate = internal is set. See GENERAL OPTIONAL PARAMETERS below.
/var/spool/news contains the news articles; e.g. /var/spool/news/alt/fan/agulbra contains the articles in the alt.fan.agulbra group. Each directory contains articles in numbered files (decimal numbers, monotonically increasing), and a special file called .overview which contains the "Subject", "From", "Date", "Message-ID", "References", "Bytes" and "Lines" headers for each article in the group.
Several subdirectories are special:
/var/spool/news/leaf.node contains the files that leafnode creates during operation, for example the groupinfo file which contains information about each USENET newsgroup. This file is built by fetchnews(8). You can force a complete rebuild of the groupinfo file by calling fetchnews with the parameter -f (see fetchnews(8)).
/var/spool/news/out.going contains local postings that fetchnews(8) is to pass to the upstream NNTP server.
/var/spool/news/failed.postings contains local postings that the upstream server rejected. fetchnews(8) will create files in this directory, but none of the leafnode programs will delete anything in it.
/var/spool/news/message.id contains hard links to each message; this is used in place of the dbz database typically used by bigger servers. (A directory such as this is probably more efficient for the small servers leafnode is designed for but scales very badly.)
/var/spool/news/interesting.groups contains one file for each group an NNTP client has asked to read. leafnode will touch the the relevant file when a LISTGROUP, XOVER, XHDR, STAT, HEAD, BODY or ARTICLE command is issued immediately after a GROUP command is issued, and fetchnews(8) will retrieve all new articles in all groups whose files have been either
|- touched during the past two days, or|
|- touched more than once, and at least once within the past week.|
All configuration is done using the file /etc/leafnode/config. All global parameters must be mentioned before server and server-specific parameters.
For the purposes of this section, whitespace shall be defined as an arbitrary sequence consisting of one or more SPACE or HTAB characters, ASCII positions 32 and 9, respectively.
The configuration file is strictly line-oriented with LF or CRLF as line terminator.
Empty lines and lines consisting of only whitespace, possibly followed by a comment (introduced by a hash mark (#) and extending through the end of the line), are skipped.
All other lines have exactly three mandatory fields, a plain text parameter, an assignment character (=) optionally surrounded by whitespace and a value. The value is either plain text or - new since leafnode v1.11 - a string in double quotes with trivial backslash escape (see below).
Plain text starts at the first non-whitespace character and extends through the last non-whitespace character on the line that is not a comment. A trailing comment on a line is skipped.
Quoted strings are enclosed in double quote characters ("). The backslash character (\) is skipped, but it copies the immediately following character verbatim, so that you can specify the backslash itself by doubling it (\\) or a double quote character as part of the string by preceding it with a backslash (\"); the hash mark has no special meaning as command introducer inside quoted strings. Text after the end of the string is silently ignored (this may change in future versions). Comments after quoted strings are ignored.
|server = news02.bigprovider.com|
|"server" is used by fetchnews(8) to select what NNTP server(s) to retrieve news from and to post your articles to. You can specify more than one news server; in that case, the servers will be queried from the top down. If you want to post articles, at least one of your servers should allow you to post. In the example above, news02.bigprovider.com is the news server.|
|expire = 5|
|"expire" is the number of days a thread should be kept around. In the example, five days after the thread has last been read, it is deleted by texpire(8).|
|SERVER-SPECIFIC OPTIONAL PARAMETERS|
|username = myname|
|If any of your news servers requires authentication, you can enter your username on that server here. This field may occur multiple times, once after each server definition.|
|password = mypassword|
|If any of your news servers requires authentication, you can enter your password on that server here. This field may occur multiple times, once after each server definition. Since the password is available in clear text, it is recommended that you set the rights on the config file as restrictive as possible, otherwise other users of your computer will be able to get your password(s) from that file.|
|feedtype = type|
|Determine how to send postings to the upstream server. Can be any of NNTP (default), UUCP or NONE. Case does not matter.|
|timeout = 90|
|By default, leafnode tries to connect for 30 seconds to a server and then gives up. If you have a slow server, you can try for a longer time by setting the timeout higher (in this example, 90 seconds). The timeout can be tuned individually for each server and applies to each of the server’s addresses if it has multiple addresses anew.|
|noactive = 1|
|In some configurations, the user does not want to download the list of newsgroups from a particular server, and this is the magic word to prevent it. It can be used if you want to use this as a supplement server for fast downloads but it has way too many news groups.|
|nodesc = 1|
|Some servers do not deliver news groups descriptions correctly because they cannot parse the LIST NEWSGROUPS command. In that case, put this line after the "server" line.|
|noread = 1|
|Prevent fetching news articles or active files from this server. You can use this if the upstream is good to post, but too slow to fetch news from.|
|port = 8000|
|By default, leafnode tries to connect to its upstream news servers on the NNTP port (119). If your servers run on a different port, you can specify those here. This field may occur multiple times, once after each server definition.|
|usexhdr = 1|
|fetchnews will usually use XOVER to retrieve header information from the remote server. Under special circumstances, it may be faster to have it use XHDR instead. This line will try to enforce XHDR, but fetchnews will still fall back to XOVER if you also want to use filters in a group or if you work with "delaybody" set (because in these cases it will always be faster to use XOVER).|
|only_groups_pcre = PCRE|
|This parameter lists the Perl-compatible regular expression of groups that are fetched or posted to this server. The PCRE is automatically anchored at the left hand side, so you can omit the leading ^. Remember to escape dots, as in: de\.comp\.|de\.comm\. Another example might be only_groups_pcre=de\.(?!alt) that fetches all de.* groups that are not de.alt.* groups. Consult the PCRE documentation for details.
If this parameter is omitted, all groups are fetched from and posted to this server.
Note this parameter can be abused to achieve some kind of "newsgroup routing". To do this, you must use only_groups_pcre for each of the servers in your configuration file, and only one of them may list the hierarchy that needs to be routed to a specific server. This is not very comfortable and hence not fully documented, although it works.
Note that you need to reload the active file (-f) for this option to have an immediate effect.
|GENERAL OPTIONAL PARAMETERS|
|run_as_user = abuild|
|Use user account "abuild" when dropping privileges. This user account must not be privileged, i. e. it must not have user ID #0. It is recommended that a separate user and group account be created for leafnode; some systems create a user and group named "news" by default, which should be good to use as long as it is unprivileged. This means that the user’s id is not 0 this user does not belong to a group with group id #0 (usually "root" or "wheel").|
|hostname = host.domain.country|
|If your messages do not already have message IDs (generated by the newsreader), Leafnode will generate a message ID for them. However, it will never ever overwrite an existing message ID. By default, it tries to do this from the name of your computer. However, some upstream servers demand message IDs of a certain type. In this case, you can override the name of your computer by setting "hostname" to a sensible value. The abuse of this option can cause your upstreams to silently drop your postings!|
|authenticate = METHOD|
|Require that NNTP clients authenticate themselves.|
|If METHOD is pam (on systems that support PAM), leafnode expects to authenticate and check an account, the service name is "leafnode". BEWARE: Allowing users to log in with their regular system password is a security risk because the password is sent in clear text! You had better do this only for users who cannot log in (where the "shell" field in passwd is a statically linked /sbin/nologin, for instance).|
|If METHOD is internal, leafnode expects a file /etc/leafnode/users which lists users and their passwords. The file has one line per user, with the user name (which cannot contain spaces), then a colon (:), then the crypt(3) encrypted password.|
|To generate these lines, you can either use Apache’s htpasswd(8) command if it’s installed or use the simple Perl program tools/make_pass.pl, for example, if you want to add a user enigma with a password of break!me, type:
perl -wT tools/make_pass.pl ’enigma’ ’break!me’
and copy the resulting line to the /etc/leafnode/users file.
|log_poster_ip = 1|
|If you set this option, leafnode will add a "X-Leafnode-NNTP-Posting-Host" to every outgoing post containing the IP address of the poster. This helps tracking abuses on a publicly available server. The standard header "NNTP-Posting-Host" cannot be used as the server leafnode forwards the post to would change it to your leafnode server IP address.|
|create_all_links = 1|
|Normally, fetchnews will store articles only in the newsgroups which you consider interesting. If you set "create_all_links", fetchnews will create hardlinks for all newsgroups which it can find in the Newsgroups: header. This may be of interest if you want to apply a score- or killfile to the Xref: line.|
|no_direct_spool = 0|
|If this is set to a nonzero value, leafnode will not store locally posted articles directly into its spool, unless they are posted or crossposted to local groups. Instead, it will spool such locally posted articles only after a later fetchnews run has retrieved the freshly posted article from the upstream server.|
|maxfetch = 1000|
|"maxfetch" specifies the maximum number of articles fetchnews(8) should fetch from the upstream server in each group. Its use is not advised, because if you use it you will not see all the traffic in a group. By default there is no limit.|
|initialfetch = 1|
|"initialfetch" defines how many articles from a newly subscribed group should be fetched. The default is to fetch all old articles, which can get quite time-consuming when subscribing to a very busy group. This is equivalent to setting initialfetch to zero. If you want to get no old articles when subscribing to a new group, you should set initialfetch to one, as in the example above.|
|groupexpire = very.crowded.group 1
groupexpire = very.crowded.hierarchy.* 1
|"groupexpire" makes it possible to adjust expiry times for individual groups. Expiry times are given in days, negative values prevent expiry for the given groups. This value is used by texpire(8). You can specify as many groupexpire lines as you like. It is possible to specify glob(7)-like wildcard expressions. Note that the LAST line given in the configuration file takes the highest precedence - put the most specific rules last.|
|filterfile = /etc/leafnode/filters|
|Leafnode can filter the input headers for arbitrary regular expressions. These are stored in a file designated "filterfile". The format of "filterfile" is described in filterfile(5).|
|timeout_client = 300|
|Wait timeout_client seconds for a command from the client (newsreader) before exiting.|
|timeout_delaybody = hours|
|Retry at fetchnews runs in the next timeout_delaybody hours after an article has been marked for download to download it (only applies to delaybody mode). Be sure to run fetchnews at least once within that interval, so set 25 here if you run fetchnews once daily. Default: use the same value as group expiry, either from groupexpire or, if that is unset, from the global expire.|
|timeout_short = 2|
|By default, a group that has been accidentally touched is being fetched for two days. You can change this time by changing timeout_short.|
|timeout_long = 7|
|By default, a group that has not been read at all is being fetched for seven days before being unsubscribed. This interval can be changed by setting timeout_long to a different value.|
|timeout_active = 90|
|By default, active files from the upstream servers are re-read every 90 days. This interval can be changed by setting timeout_active to a different value. Be aware that reading an active file transfers about one MB of information if the server that you are using carries a reasonable number of groups (i.e. around 20,000).|
|delaybody = 1|
|With this option set, fetchnews(8) fetches only the headers of an article for visual inspection. Only when the headers have been read, the bodies of the articles will be retrieved the next time fetchnews(8) is called. This can save a huge amount of download time and disk space.|
|groupdelaybody = some.news.groups.*|
|If you want delaybody mode only for selected groups, you can enable this download mode for one specific group. The global delaybody switch above causes all groups to be treated that way, groupdelaybody enables delaybody for all groups matching the pattern.|
|debugmode = 260|
|With this option set, fetchnews(8), texpire(8) and leafnode(8) will start to log lots of debugging output via syslog(8) to news.debug. Use it for tracking down problems with your feed. See config.example for details.|
|windowsize = 5|
|This option defaults to 5, it will specify how many ARTICLE commands the fetchnews program sends ahead before reading articles, to minimize network round trip delays without using additional threads. Set this higher (say, 100 as a rule of thumb) for high-throughput, high-latency or for congested links (satellite or DSL without "fast path" option). In case of trouble (fetchnews hangs), you can set this to 1, although no such trouble has been reported so far.|
Here are the NNTP commands supported by this server.
The rest of the commands given in the NNTP RFC or added in other servers are left out in order to keep the server simple and bug-free.
|Used to authenticate a user at the server. See README for details.|
|Return the headers and body text of an article.|
|BODY||Return the body text of an article.|
|DATE||Return the current GMT (UT) date and time of the server in YYMMDDhhmmss format.|
|GROUP||Sets the current USENET group and article pointer, and returns the status information about this group.|
|HEAD||Return the headers of an article.|
|HELP||Accepted but I’m afraid it is not very helpful.|
|IHAVE||Known but rejected.|
|LAST||Moves the article pointer back by 1.|
|LIST||Lists the available USENET groups.|
|List some extensions.|
|Lists the articles present in the current group, or the argument group if an argument is present.|
|MODE||Accepted and blithely ignored.|
|Lists newsgroups which have been newly created.|
|Return articles which have been received since a certain time.|
|NEXT||Moves the article pointer forward by 1.|
|POST||Post a new article. Only scant syntax checking is performed. The article is sent to the upstream NNTP server by fetchnews(8).|
|QUIT||Quit reading news.|
|SLAVE||Accepted but ignored.|
|STAT||Return the availability of an article.|
|XHDR||Return a certain header for a range of articles in a group.|
|XOVER||Returns the "Subject", "From", "Date", "Message-ID", "References", "Lines" and "Bytes" headers for the indicated article(s).|
|XPAT||Return a range of headers for articles matched by a certain pattern.|
|When this environment variable exists, the client cannot post. The server will send a 201 no posting banner. Additionally, if this variable is non-empty, its contents are appended to the initial banner.
This is useful in context with hosts.allow when your leafnode runs under tcp_wrappers access control, for example (this assumes your libwrap is compiled with -DHOSTS_OPTIONS):
leafnode: 192.168.1.4: allow
leafnode: 192.168.1.0/255.255.255.0:allow:setenv NOPOSTING -
leafnode: ALL: deny
Would allow full access to 192.168.1.4, read-only access to the other IPs in 192.168.1.* an deny access from all other clients.
Some strings are chopped after 1024 characters, notably configuration and filter configuration.
This manual page needs revision.
Written by Arnt Gulbrandsen <agulbra> and copyright 1995 Troll Tech AS, Postboks 6133 Etterstad, 0602 Oslo, Norway, fax +47 22646949.
Modified by Cornelius Krasel <krasel>, Randolf Skerka <Randolf.Skerka> and Markus Enzenberger <enz>. Copyright of the modifications 1997-2000.
Written and Copyright 2002 by Jörg Dietrich <joerg>
Written and Copyright 2002 by Ralf Wildenhues <ralf.wildenhues>
Written and Copyright 2000 - 2005 by Matthias Andree <matthias.andree>.
Written and Copyright 2002 by Ralf Wildenhues <ralf.wildenhues>
Written and Copyright 2000 - 2005 by Matthias Andree <matthias.andree>.
The initial development of leafnode has been paid for by Uninett AS (http://www.uninett.no/).